Browse Source

[REFACTOR] Remove the default sampler from the Texture

Panagiotis Christopoulos Charitos 8 years ago
parent
commit
0c6b9ef3d9
39 changed files with 205 additions and 327 deletions
  1. 0 12
      src/anki/gr/CommandBuffer.h
  2. 0 10
      src/anki/gr/RenderGraph.h
  3. 31 1
      src/anki/gr/Sampler.h
  4. 1 35
      src/anki/gr/Texture.h
  5. 0 41
      src/anki/gr/gl/CommandBuffer.cpp
  6. 8 0
      src/anki/gr/gl/SamplerImpl.cpp
  7. 12 23
      src/anki/gr/gl/StateTracker.h
  8. 2 44
      src/anki/gr/gl/TextureImpl.cpp
  9. 0 7
      src/anki/gr/vulkan/CommandBuffer.cpp
  10. 0 12
      src/anki/gr/vulkan/CommandBufferImpl.h
  11. 0 15
      src/anki/gr/vulkan/DescriptorSet.h
  12. 0 4
      src/anki/gr/vulkan/TextureImpl.cpp
  13. 0 2
      src/anki/gr/vulkan/TextureImpl.h
  14. 7 5
      src/anki/renderer/Bloom.cpp
  15. 0 3
      src/anki/renderer/Dbg.cpp
  16. 2 5
      src/anki/renderer/DepthDownscale.cpp
  17. 2 3
      src/anki/renderer/DownscaleBlur.cpp
  18. 6 5
      src/anki/renderer/FinalComposite.cpp
  19. 12 8
      src/anki/renderer/ForwardShading.cpp
  20. 0 2
      src/anki/renderer/GBuffer.cpp
  21. 5 7
      src/anki/renderer/Indirect.cpp
  22. 4 2
      src/anki/renderer/LensFlare.cpp
  23. 15 12
      src/anki/renderer/LightShading.cpp
  24. 1 1
      src/anki/renderer/MainRenderer.cpp
  25. 8 10
      src/anki/renderer/Renderer.cpp
  26. 8 2
      src/anki/renderer/Renderer.h
  27. 1 3
      src/anki/renderer/ShadowMapping.cpp
  28. 8 8
      src/anki/renderer/Ssao.cpp
  29. 0 1
      src/anki/renderer/TemporalAA.cpp
  30. 1 1
      src/anki/renderer/Tonemapping.cpp
  31. 7 7
      src/anki/renderer/Volumetric.cpp
  32. 8 10
      src/anki/resource/TextureResource.cpp
  33. 7 0
      src/anki/resource/TextureResource.h
  34. 2 2
      src/anki/scene/ParticleEmitter.cpp
  35. 2 1
      src/anki/scene/RenderComponent.cpp
  36. 7 1
      src/anki/ui/Canvas.cpp
  37. 1 0
      src/anki/ui/Canvas.h
  38. 0 2
      src/anki/ui/Font.cpp
  39. 37 20
      tests/gr/Gr.cpp

+ 0 - 12
src/anki/gr/CommandBuffer.h

@@ -223,18 +223,6 @@ public:
 		setBlendOperation(attachment, func, func);
 		setBlendOperation(attachment, func, func);
 	}
 	}
 
 
-	/// Bind texture.
-	/// @param set The set to bind to.
-	/// @param binding The binding to bind to.
-	/// @param tex The texture to bind.
-	/// @param usage The state the tex is in.
-	/// @param aspect The depth stencil aspect.
-	void bindTexture(U32 set,
-		U32 binding,
-		TexturePtr tex,
-		TextureUsageBit usage,
-		DepthStencilAspectBit aspect = DepthStencilAspectBit::DEPTH);
-
 	/// Bind texture and sample.
 	/// Bind texture and sample.
 	/// @param set The set to bind to.
 	/// @param set The set to bind to.
 	/// @param binding The binding to bind to.
 	/// @param binding The binding to bind to.

+ 0 - 10
src/anki/gr/RenderGraph.h

@@ -139,16 +139,6 @@ public:
 		TextureUsageBit& usage,
 		TextureUsageBit& usage,
 		DepthStencilAspectBit& aspect) const;
 		DepthStencilAspectBit& aspect) const;
 
 
-	/// Convenience method.
-	void bindTexture(U32 set, U32 binding, RenderTargetHandle handle)
-	{
-		TexturePtr tex;
-		TextureUsageBit usage;
-		DepthStencilAspectBit aspect;
-		getRenderTargetState(handle, tex, usage, aspect);
-		m_commandBuffer->bindTexture(set, binding, tex, usage, aspect);
-	}
-
 	/// Convenience method.
 	/// Convenience method.
 	void bindTextureAndSampler(U32 set, U32 binding, RenderTargetHandle handle, SamplerPtr sampler)
 	void bindTextureAndSampler(U32 set, U32 binding, RenderTargetHandle handle, SamplerPtr sampler)
 	{
 	{

+ 31 - 1
src/anki/gr/Sampler.h

@@ -6,7 +6,6 @@
 #pragma once
 #pragma once
 
 
 #include <anki/gr/GrObject.h>
 #include <anki/gr/GrObject.h>
-#include <anki/gr/Texture.h>
 
 
 namespace anki
 namespace anki
 {
 {
@@ -14,6 +13,37 @@ namespace anki
 /// @addtogroup graphics
 /// @addtogroup graphics
 /// @{
 /// @{
 
 
+/// Sampler initializer.
+class alignas(4) SamplerInitInfo : public GrBaseInitInfo
+{
+public:
+	F32 m_minLod = -1000.0;
+	F32 m_maxLod = 1000.0;
+	SamplingFilter m_minMagFilter = SamplingFilter::NEAREST;
+	SamplingFilter m_mipmapFilter = SamplingFilter::BASE;
+	CompareOperation m_compareOperation = CompareOperation::ALWAYS;
+	I8 m_anisotropyLevel = 0;
+	Bool8 m_repeat = true; ///< Repeat or clamp.
+	U8 _m_padding[3] = {0, 0, 0};
+
+	SamplerInitInfo() = default;
+
+	SamplerInitInfo(CString name)
+		: GrBaseInitInfo(name)
+	{
+	}
+
+	U64 computeHash() const
+	{
+		const U8* const first = reinterpret_cast<const U8* const>(&m_minLod);
+		const U8* const last = reinterpret_cast<const U8* const>(&m_repeat) + sizeof(m_repeat);
+		const U size = last - first;
+		ANKI_ASSERT(size
+			== sizeof(F32) * 2 + sizeof(SamplingFilter) * 2 + sizeof(CompareOperation) + sizeof(I8) + sizeof(Bool8));
+		return anki::computeHash(first, size);
+	}
+};
+
 /// GPU sampler.
 /// GPU sampler.
 class Sampler : public GrObject
 class Sampler : public GrObject
 {
 {

+ 1 - 35
src/anki/gr/Texture.h

@@ -13,37 +13,6 @@ namespace anki
 /// @addtogroup graphics
 /// @addtogroup graphics
 /// @{
 /// @{
 
 
-/// Sampler initializer.
-class alignas(4) SamplerInitInfo : public GrBaseInitInfo
-{
-public:
-	F32 m_minLod = -1000.0;
-	F32 m_maxLod = 1000.0;
-	SamplingFilter m_minMagFilter = SamplingFilter::NEAREST;
-	SamplingFilter m_mipmapFilter = SamplingFilter::BASE;
-	CompareOperation m_compareOperation = CompareOperation::ALWAYS;
-	I8 m_anisotropyLevel = 0;
-	Bool8 m_repeat = true; ///< Repeat or clamp.
-	U8 _m_padding[3] = {0, 0, 0};
-
-	SamplerInitInfo() = default;
-
-	SamplerInitInfo(CString name)
-		: GrBaseInitInfo(name)
-	{
-	}
-
-	U64 computeHash() const
-	{
-		const U8* const first = reinterpret_cast<const U8* const>(&m_minLod);
-		const U8* const last = reinterpret_cast<const U8* const>(&m_repeat) + sizeof(m_repeat);
-		const U size = last - first;
-		ANKI_ASSERT(size
-			== sizeof(F32) * 2 + sizeof(SamplingFilter) * 2 + sizeof(CompareOperation) + sizeof(I8) + sizeof(Bool8));
-		return anki::computeHash(first, size);
-	}
-};
-
 /// Texture initializer.
 /// Texture initializer.
 class alignas(4) TextureInitInfo : public GrBaseInitInfo
 class alignas(4) TextureInitInfo : public GrBaseInitInfo
 {
 {
@@ -64,13 +33,10 @@ public:
 
 
 	U8 _m_padding = 0;
 	U8 _m_padding = 0;
 
 
-	SamplerInitInfo m_sampling;
-
 	TextureInitInfo() = default;
 	TextureInitInfo() = default;
 
 
 	TextureInitInfo(CString name)
 	TextureInitInfo(CString name)
 		: GrBaseInitInfo(name)
 		: GrBaseInitInfo(name)
-		, m_sampling(name)
 	{
 	{
 	}
 	}
 
 
@@ -82,7 +48,7 @@ public:
 		ANKI_ASSERT(size
 		ANKI_ASSERT(size
 			== sizeof(U32) * 4 + sizeof(TextureUsageBit) * 2 + sizeof(TextureType) + sizeof(U8) + sizeof(PixelFormat)
 			== sizeof(U32) * 4 + sizeof(TextureUsageBit) * 2 + sizeof(TextureType) + sizeof(U8) + sizeof(PixelFormat)
 				+ sizeof(U8));
 				+ sizeof(U8));
-		return appendHash(first, size, m_sampling.computeHash());
+		return anki::computeHash(first, size);
 	}
 	}
 };
 };
 
 

+ 0 - 41
src/anki/gr/gl/CommandBuffer.cpp

@@ -630,47 +630,6 @@ void CommandBuffer::setBlendOperation(U32 attachment, BlendOperation funcRgb, Bl
 	}
 	}
 }
 }
 
 
-void CommandBuffer::bindTexture(
-	U32 set, U32 binding, TexturePtr tex, TextureUsageBit usage, DepthStencilAspectBit aspect)
-{
-	class Cmd final : public GlCommand
-	{
-	public:
-		U32 m_unit;
-		TexturePtr m_tex;
-		Bool8 m_samplerChanged;
-
-		Cmd(U32 unit, TexturePtr tex, Bool samplerChanged)
-			: m_unit(unit)
-			, m_tex(tex)
-			, m_samplerChanged(samplerChanged)
-		{
-		}
-
-		Error operator()(GlState&)
-		{
-			if(m_tex)
-			{
-				glBindTextureUnit(m_unit, static_cast<const TextureImpl&>(*m_tex).getGlName());
-			}
-
-			if(m_samplerChanged)
-			{
-				glBindSampler(m_unit, 0);
-			}
-			return Error::NONE;
-		}
-	};
-
-	ANKI_GL_SELF(CommandBufferImpl);
-	Bool texChanged, samplerChanged;
-	if(self.m_state.bindTexture(set, binding, tex, aspect, texChanged, samplerChanged))
-	{
-		U unit = binding + MAX_TEXTURE_BINDINGS * set;
-		self.pushBackNewCommand<Cmd>(unit, (texChanged) ? tex : TexturePtr(), samplerChanged);
-	}
-}
-
 void CommandBuffer::bindTextureAndSampler(
 void CommandBuffer::bindTextureAndSampler(
 	U32 set, U32 binding, TexturePtr tex, SamplerPtr sampler, TextureUsageBit usage, DepthStencilAspectBit aspect)
 	U32 set, U32 binding, TexturePtr tex, SamplerPtr sampler, TextureUsageBit usage, DepthStencilAspectBit aspect)
 {
 {

+ 8 - 0
src/anki/gr/gl/SamplerImpl.cpp

@@ -18,11 +18,13 @@ void SamplerImpl::init(const SamplerInitInfo& sinit)
 	{
 	{
 		glSamplerParameteri(m_glName, GL_TEXTURE_WRAP_S, GL_REPEAT);
 		glSamplerParameteri(m_glName, GL_TEXTURE_WRAP_S, GL_REPEAT);
 		glSamplerParameteri(m_glName, GL_TEXTURE_WRAP_T, GL_REPEAT);
 		glSamplerParameteri(m_glName, GL_TEXTURE_WRAP_T, GL_REPEAT);
+		glSamplerParameteri(m_glName, GL_TEXTURE_WRAP_R, GL_REPEAT);
 	}
 	}
 	else
 	else
 	{
 	{
 		glSamplerParameteri(m_glName, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 		glSamplerParameteri(m_glName, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 		glSamplerParameteri(m_glName, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 		glSamplerParameteri(m_glName, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+		glSamplerParameteri(m_glName, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
 	}
 	}
 
 
 	// Set filtering type
 	// Set filtering type
@@ -39,6 +41,12 @@ void SamplerImpl::init(const SamplerInitInfo& sinit)
 	}
 	}
 #endif
 #endif
 
 
+	if(sinit.m_compareOperation != CompareOperation::ALWAYS)
+	{
+		glSamplerParameteri(m_glName, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
+		glSamplerParameteri(m_glName, GL_TEXTURE_COMPARE_FUNC, convertCompareOperation(sinit.m_compareOperation));
+	}
+
 	glSamplerParameteri(m_glName, GL_TEXTURE_MIN_LOD, sinit.m_minLod);
 	glSamplerParameteri(m_glName, GL_TEXTURE_MIN_LOD, sinit.m_minLod);
 	glSamplerParameteri(m_glName, GL_TEXTURE_MAX_LOD, sinit.m_maxLod);
 	glSamplerParameteri(m_glName, GL_TEXTURE_MAX_LOD, sinit.m_maxLod);
 }
 }

+ 12 - 23
src/anki/gr/gl/StateTracker.h

@@ -454,38 +454,27 @@ public:
 
 
 	Array2d<TextureBinding, MAX_DESCRIPTOR_SETS, MAX_TEXTURE_BINDINGS> m_textures;
 	Array2d<TextureBinding, MAX_DESCRIPTOR_SETS, MAX_TEXTURE_BINDINGS> m_textures;
 
 
-	Bool bindTexture(
-		U32 set, U32 binding, TexturePtr tex, DepthStencilAspectBit aspect, Bool& texChanged, Bool& samplerChanged)
+	Bool bindTextureAndSampler(U32 set, U32 binding, TexturePtr tex, SamplerPtr sampler, DepthStencilAspectBit aspect)
 	{
 	{
 		TextureBinding& b = m_textures[set][binding];
 		TextureBinding& b = m_textures[set][binding];
-		TextureImpl* texi = static_cast<TextureImpl*>(tex.get());
 
 
-		texChanged = false;
-		samplerChanged = false;
+		TextureImpl* teximpl = static_cast<TextureImpl*>(tex.get());
+		SamplerImpl* samplerimpl = static_cast<SamplerImpl*>(sampler.get());
 
 
-		if(texi != b.m_tex)
+		Bool dirty;
+		if(b.m_tex != teximpl || b.m_sampler != samplerimpl || b.m_aspect != aspect)
 		{
 		{
-			b.m_tex = texi;
-			texChanged = true;
+			b.m_tex = teximpl;
+			b.m_sampler = samplerimpl;
+			b.m_aspect = aspect;
+			dirty = true;
 		}
 		}
-
-		if(b.m_sampler != nullptr)
+		else
 		{
 		{
-			b.m_sampler = nullptr;
-			samplerChanged = true;
+			dirty = false;
 		}
 		}
 
 
-		b.m_aspect = aspect;
-		return samplerChanged || texChanged;
-	}
-
-	Bool bindTextureAndSampler(U32 set, U32 binding, TexturePtr tex, SamplerPtr sampler, DepthStencilAspectBit aspect)
-	{
-		TextureBinding& b = m_textures[set][binding];
-		b.m_tex = static_cast<TextureImpl*>(tex.get());
-		b.m_sampler = static_cast<SamplerImpl*>(sampler.get());
-		b.m_aspect = aspect;
-		return true;
+		return dirty;
 	}
 	}
 
 
 	class ShaderBufferBinding
 	class ShaderBufferBinding

+ 2 - 44
src/anki/gr/gl/TextureImpl.cpp

@@ -172,7 +172,6 @@ void TextureImpl::init(const TextureInitInfo& init)
 	ANKI_ASSERT(!isCreated());
 	ANKI_ASSERT(!isCreated());
 
 
 	GrAllocator<U8> alloc = getAllocator();
 	GrAllocator<U8> alloc = getAllocator();
-	const SamplerInitInfo& sinit = init.m_sampling;
 
 
 	// Create
 	// Create
 	//
 	//
@@ -204,49 +203,8 @@ void TextureImpl::init(const TextureInitInfo& init)
 		ANKI_ASSERT(0);
 		ANKI_ASSERT(0);
 	}
 	}
 
 
-	// Set parameters
-	if(init.m_samples == 1)
-	{
-		if(sinit.m_repeat)
-		{
-			glTexParameteri(m_target, GL_TEXTURE_WRAP_S, GL_REPEAT);
-			glTexParameteri(m_target, GL_TEXTURE_WRAP_T, GL_REPEAT);
-			glTexParameteri(m_target, GL_TEXTURE_WRAP_R, GL_REPEAT);
-		}
-		else
-		{
-			glTexParameteri(m_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-			glTexParameteri(m_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-			glTexParameteri(m_target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
-		}
-
-		// Make sure that the texture is complete
-		glTexParameteri(m_target, GL_TEXTURE_MAX_LEVEL, m_mipCount - 1);
-
-		// Set filtering type
-		GLenum minFilter = GL_NONE;
-		GLenum magFilter = GL_NONE;
-		convertFilter(sinit.m_minMagFilter, sinit.m_mipmapFilter, minFilter, magFilter);
-
-		glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, minFilter);
-		glTexParameteri(m_target, GL_TEXTURE_MAG_FILTER, magFilter);
-
-#if ANKI_GL == ANKI_GL_DESKTOP
-		if(sinit.m_anisotropyLevel > 1)
-		{
-			glTexParameteri(m_target, GL_TEXTURE_MAX_ANISOTROPY_EXT, GLint(sinit.m_anisotropyLevel));
-		}
-#endif
-
-		if(sinit.m_compareOperation != CompareOperation::ALWAYS)
-		{
-			glTexParameteri(m_target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
-			glTexParameteri(m_target, GL_TEXTURE_COMPARE_FUNC, convertCompareOperation(sinit.m_compareOperation));
-		}
-
-		glTexParameteri(m_target, GL_TEXTURE_MIN_LOD, sinit.m_minLod);
-		glTexParameteri(m_target, GL_TEXTURE_MAX_LOD, sinit.m_maxLod);
-	}
+	// Make sure that the texture is complete
+	glTexParameteri(m_target, GL_TEXTURE_MAX_LEVEL, m_mipCount - 1);
 
 
 	ANKI_CHECK_GL_ERROR();
 	ANKI_CHECK_GL_ERROR();
 }
 }

+ 0 - 7
src/anki/gr/vulkan/CommandBuffer.cpp

@@ -173,13 +173,6 @@ void CommandBuffer::setBlendOperation(U32 attachment, BlendOperation funcRgb, Bl
 	self.setBlendOperation(attachment, funcRgb, funcA);
 	self.setBlendOperation(attachment, funcRgb, funcA);
 }
 }
 
 
-void CommandBuffer::bindTexture(
-	U32 set, U32 binding, TexturePtr tex, TextureUsageBit usage, DepthStencilAspectBit aspect)
-{
-	ANKI_VK_SELF(CommandBufferImpl);
-	self.bindTexture(set, binding, tex, usage, aspect);
-}
-
 void CommandBuffer::bindTextureAndSampler(
 void CommandBuffer::bindTextureAndSampler(
 	U32 set, U32 binding, TexturePtr tex, SamplerPtr sampler, TextureUsageBit usage, DepthStencilAspectBit aspect)
 	U32 set, U32 binding, TexturePtr tex, SamplerPtr sampler, TextureUsageBit usage, DepthStencilAspectBit aspect)
 {
 {

+ 0 - 12
src/anki/gr/vulkan/CommandBufferImpl.h

@@ -219,18 +219,6 @@ public:
 		m_state.setBlendOperation(attachment, funcRgb, funcA);
 		m_state.setBlendOperation(attachment, funcRgb, funcA);
 	}
 	}
 
 
-	void bindTexture(U32 set, U32 binding, TexturePtr tex_, TextureUsageBit usage, DepthStencilAspectBit aspect)
-	{
-		commandCommon();
-		const U realBinding = binding;
-		const Texture& tex = *tex_;
-		const TextureImpl& teximpl = static_cast<const TextureImpl&>(tex);
-		ANKI_ASSERT((!teximpl.m_depthStencil || !!aspect) && "Need to set aspect for DS textures");
-		const VkImageLayout lay = teximpl.computeLayout(usage, 0);
-		m_dsetState[set].bindTexture(realBinding, &tex, aspect, lay);
-		m_microCmdb->pushObjectRef(tex_);
-	}
-
 	void bindTextureAndSampler(
 	void bindTextureAndSampler(
 		U32 set, U32 binding, TexturePtr& tex_, SamplerPtr sampler, TextureUsageBit usage, DepthStencilAspectBit aspect)
 		U32 set, U32 binding, TexturePtr& tex_, SamplerPtr sampler, TextureUsageBit usage, DepthStencilAspectBit aspect)
 	{
 	{

+ 0 - 15
src/anki/gr/vulkan/DescriptorSet.h

@@ -110,21 +110,6 @@ public:
 		m_layoutDirty = true;
 		m_layoutDirty = true;
 	}
 	}
 
 
-	void bindTexture(U binding, const Texture* tex, DepthStencilAspectBit aspect, VkImageLayout layout)
-	{
-		AnyBinding& b = m_bindings[binding];
-		b = {};
-		b.m_type = DescriptorType::TEXTURE;
-		b.m_uuids[0] = b.m_uuids[1] = tex->getUuid();
-
-		b.m_tex.m_tex = static_cast<const TextureImpl*>(tex);
-		b.m_tex.m_sampler = static_cast<const TextureImpl*>(tex)->m_sampler.get();
-		b.m_tex.m_aspect = aspect;
-		b.m_tex.m_layout = layout;
-
-		m_anyBindingDirty = true;
-	}
-
 	void bindTextureAndSampler(
 	void bindTextureAndSampler(
 		U binding, const Texture* tex, const Sampler* sampler, DepthStencilAspectBit aspect, VkImageLayout layout)
 		U binding, const Texture* tex, const Sampler* sampler, DepthStencilAspectBit aspect, VkImageLayout layout)
 	{
 	{

+ 0 - 4
src/anki/gr/vulkan/TextureImpl.cpp

@@ -45,12 +45,8 @@ TextureImpl::~TextureImpl()
 Error TextureImpl::init(const TextureInitInfo& init_)
 Error TextureImpl::init(const TextureInitInfo& init_)
 {
 {
 	TextureInitInfo init = init_;
 	TextureInitInfo init = init_;
-	init.m_sampling.setName(init.getName());
-
 	ANKI_ASSERT(textureInitInfoValid(init));
 	ANKI_ASSERT(textureInitInfoValid(init));
 
 
-	ANKI_CHECK(getGrManagerImpl().getSamplerFactory().newInstance(init.m_sampling, m_sampler));
-
 	// Set some stuff
 	// Set some stuff
 	m_width = init.m_width;
 	m_width = init.m_width;
 	m_height = init.m_height;
 	m_height = init.m_height;

+ 0 - 2
src/anki/gr/vulkan/TextureImpl.h

@@ -34,8 +34,6 @@ ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(TextureImplWorkaround, inline)
 class TextureImpl final : public Texture, public VulkanObject<Texture, TextureImpl>
 class TextureImpl final : public Texture, public VulkanObject<Texture, TextureImpl>
 {
 {
 public:
 public:
-	MicroSamplerPtr m_sampler;
-
 	VkImage m_imageHandle = VK_NULL_HANDLE;
 	VkImage m_imageHandle = VK_NULL_HANDLE;
 
 
 	GpuMemoryHandle m_memHandle;
 	GpuMemoryHandle m_memHandle;

+ 7 - 5
src/anki/renderer/Bloom.cpp

@@ -35,7 +35,6 @@ Error Bloom::initExposure(const ConfigSet& config)
 		m_exposure.m_height,
 		m_exposure.m_height,
 		BLOOM_RT_PIXEL_FORMAT,
 		BLOOM_RT_PIXEL_FORMAT,
 		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
 		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
-		SamplingFilter::LINEAR,
 		"Bloom Exp");
 		"Bloom Exp");
 	m_exposure.m_rtDescr.bake();
 	m_exposure.m_rtDescr.bake();
 
 
@@ -68,7 +67,6 @@ Error Bloom::initUpscale(const ConfigSet& config)
 		m_upscale.m_height,
 		m_upscale.m_height,
 		BLOOM_RT_PIXEL_FORMAT,
 		BLOOM_RT_PIXEL_FORMAT,
 		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
 		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
-		SamplingFilter::LINEAR,
 		"Bloom Upscale");
 		"Bloom Upscale");
 	m_upscale.m_rtDescr.bake();
 	m_upscale.m_rtDescr.bake();
 
 
@@ -147,7 +145,7 @@ void Bloom::runExposure(RenderPassWorkContext& rgraphCtx)
 
 
 	cmdb->setViewport(0, 0, m_exposure.m_width, m_exposure.m_height);
 	cmdb->setViewport(0, 0, m_exposure.m_width, m_exposure.m_height);
 	cmdb->bindShaderProgram(m_exposure.m_grProg);
 	cmdb->bindShaderProgram(m_exposure.m_grProg);
-	rgraphCtx.bindTexture(0, 0, m_r->getDownscaleBlur().getPassRt(MAX_U));
+	rgraphCtx.bindTextureAndSampler(0, 0, m_r->getDownscaleBlur().getPassRt(MAX_U), m_r->getLinearSampler());
 
 
 	Vec4* uniforms = allocateAndBindUniforms<Vec4*>(sizeof(Vec4), cmdb, 0, 0);
 	Vec4* uniforms = allocateAndBindUniforms<Vec4*>(sizeof(Vec4), cmdb, 0, 0);
 	*uniforms = Vec4(m_exposure.m_threshold, m_exposure.m_scale, 0.0, 0.0);
 	*uniforms = Vec4(m_exposure.m_threshold, m_exposure.m_scale, 0.0, 0.0);
@@ -164,13 +162,17 @@ void Bloom::runUpscaleAndSslf(RenderPassWorkContext& rgraphCtx)
 	// Upscale
 	// Upscale
 	cmdb->setViewport(0, 0, m_upscale.m_width, m_upscale.m_height);
 	cmdb->setViewport(0, 0, m_upscale.m_width, m_upscale.m_height);
 	cmdb->bindShaderProgram(m_upscale.m_grProg);
 	cmdb->bindShaderProgram(m_upscale.m_grProg);
-	rgraphCtx.bindTexture(0, 0, m_runCtx.m_exposureRt);
+	rgraphCtx.bindTextureAndSampler(0, 0, m_runCtx.m_exposureRt, m_r->getLinearSampler());
 	drawQuad(cmdb);
 	drawQuad(cmdb);
 
 
 	// SSLF
 	// SSLF
 	cmdb->bindShaderProgram(m_sslf.m_grProg);
 	cmdb->bindShaderProgram(m_sslf.m_grProg);
 	cmdb->setBlendFactors(0, BlendFactor::ONE, BlendFactor::ONE);
 	cmdb->setBlendFactors(0, BlendFactor::ONE, BlendFactor::ONE);
-	cmdb->bindTexture(0, 1, m_sslf.m_lensDirtTex->getGrTexture(), TextureUsageBit::SAMPLED_FRAGMENT);
+	cmdb->bindTextureAndSampler(0,
+		1,
+		m_sslf.m_lensDirtTex->getGrTexture(),
+		m_sslf.m_lensDirtTex->getSampler(),
+		TextureUsageBit::SAMPLED_FRAGMENT);
 	drawQuad(cmdb);
 	drawQuad(cmdb);
 
 
 	// Retore state
 	// Retore state

+ 0 - 3
src/anki/renderer/Dbg.cpp

@@ -15,8 +15,6 @@
 #include <anki/util/Enum.h>
 #include <anki/util/Enum.h>
 #include <anki/misc/ConfigSet.h>
 #include <anki/misc/ConfigSet.h>
 #include <anki/collision/ConvexHullShape.h>
 #include <anki/collision/ConvexHullShape.h>
-#include <anki/Ui.h> /// XXX
-#include <anki/renderer/Clusterer.h> /// XXX
 
 
 namespace anki
 namespace anki
 {
 {
@@ -49,7 +47,6 @@ Error Dbg::lazyInit()
 		m_r->getHeight(),
 		m_r->getHeight(),
 		DBG_COLOR_ATTACHMENT_PIXEL_FORMAT,
 		DBG_COLOR_ATTACHMENT_PIXEL_FORMAT,
 		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE,
 		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE,
-		SamplingFilter::LINEAR,
 		"Dbg");
 		"Dbg");
 	m_rtDescr.bake();
 	m_rtDescr.bake();
 
 

+ 2 - 5
src/anki/renderer/DepthDownscale.cpp

@@ -24,7 +24,6 @@ Error DepthDownscale::initHalf(const ConfigSet&)
 		height,
 		height,
 		GBUFFER_DEPTH_ATTACHMENT_PIXEL_FORMAT,
 		GBUFFER_DEPTH_ATTACHMENT_PIXEL_FORMAT,
 		TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE,
 		TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE,
-		SamplingFilter::LINEAR,
 		"Half depth");
 		"Half depth");
 	m_half.m_depthRtDescr.bake();
 	m_half.m_depthRtDescr.bake();
 
 
@@ -32,7 +31,6 @@ Error DepthDownscale::initHalf(const ConfigSet&)
 		height,
 		height,
 		PixelFormat(ComponentFormat::R32, TransformFormat::FLOAT),
 		PixelFormat(ComponentFormat::R32, TransformFormat::FLOAT),
 		TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE | TextureUsageBit::SAMPLED_FRAGMENT,
 		TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE | TextureUsageBit::SAMPLED_FRAGMENT,
-		SamplingFilter::LINEAR,
 		"Half depth col");
 		"Half depth col");
 	m_half.m_colorRtDescr.bake();
 	m_half.m_colorRtDescr.bake();
 
 
@@ -67,7 +65,6 @@ Error DepthDownscale::initQuarter(const ConfigSet&)
 		PixelFormat(ComponentFormat::R32, TransformFormat::FLOAT),
 		PixelFormat(ComponentFormat::R32, TransformFormat::FLOAT),
 		TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE | TextureUsageBit::SAMPLED_FRAGMENT
 		TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE | TextureUsageBit::SAMPLED_FRAGMENT
 			| TextureUsageBit::SAMPLED_COMPUTE,
 			| TextureUsageBit::SAMPLED_COMPUTE,
-		SamplingFilter::LINEAR,
 		"quarterdepth");
 		"quarterdepth");
 	m_quarter.m_colorRtDescr.bake();
 	m_quarter.m_colorRtDescr.bake();
 
 
@@ -114,7 +111,7 @@ void DepthDownscale::runHalf(RenderPassWorkContext& rgraphCtx)
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 
 
 	cmdb->bindShaderProgram(m_half.m_grProg);
 	cmdb->bindShaderProgram(m_half.m_grProg);
-	rgraphCtx.bindTexture(0, 0, m_r->getGBuffer().getDepthRt());
+	rgraphCtx.bindTextureAndSampler(0, 0, m_r->getGBuffer().getDepthRt(), m_r->getLinearSampler());
 
 
 	cmdb->setViewport(0, 0, m_r->getWidth() / 2, m_r->getHeight() / 2);
 	cmdb->setViewport(0, 0, m_r->getWidth() / 2, m_r->getHeight() / 2);
 	cmdb->setDepthCompareOperation(CompareOperation::ALWAYS);
 	cmdb->setDepthCompareOperation(CompareOperation::ALWAYS);
@@ -130,7 +127,7 @@ void DepthDownscale::runQuarter(RenderPassWorkContext& rgraphCtx)
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 
 
 	cmdb->bindShaderProgram(m_quarter.m_grProg);
 	cmdb->bindShaderProgram(m_quarter.m_grProg);
-	rgraphCtx.bindTexture(0, 0, m_runCtx.m_halfColorRt);
+	rgraphCtx.bindTextureAndSampler(0, 0, m_runCtx.m_halfColorRt, m_r->getLinearSampler());
 	cmdb->setViewport(0, 0, m_r->getWidth() / 4, m_r->getHeight() / 4);
 	cmdb->setViewport(0, 0, m_r->getWidth() / 4, m_r->getHeight() / 4);
 
 
 	drawQuad(cmdb);
 	drawQuad(cmdb);

+ 2 - 3
src/anki/renderer/DownscaleBlur.cpp

@@ -31,7 +31,6 @@ Error DownscaleBlur::initSubpass(U idx, const UVec2& inputTexSize)
 		LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT,
 		LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT,
 		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE
 		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE
 			| TextureUsageBit::SAMPLED_COMPUTE,
 			| TextureUsageBit::SAMPLED_COMPUTE,
-		SamplingFilter::LINEAR,
 		name.toCString());
 		name.toCString());
 	pass.m_rtDescr.bake();
 	pass.m_rtDescr.bake();
 
 
@@ -89,11 +88,11 @@ void DownscaleBlur::run(RenderPassWorkContext& rgraphCtx)
 	{
 	{
 		// Bind the previous pass' Rt
 		// Bind the previous pass' Rt
 
 
-		rgraphCtx.bindTexture(0, 0, m_runCtx.m_rts[passIdx - 1]);
+		rgraphCtx.bindTextureAndSampler(0, 0, m_runCtx.m_rts[passIdx - 1], m_r->getLinearSampler());
 	}
 	}
 	else
 	else
 	{
 	{
-		rgraphCtx.bindTexture(0, 0, m_r->getTemporalAA().getRt());
+		rgraphCtx.bindTextureAndSampler(0, 0, m_r->getTemporalAA().getRt(), m_r->getLinearSampler());
 	}
 	}
 
 
 	const Subpass& pass = m_passes[passIdx];
 	const Subpass& pass = m_passes[passIdx];

+ 6 - 5
src/anki/renderer/FinalComposite.cpp

@@ -43,7 +43,6 @@ Error FinalComposite::initInternal(const ConfigSet& config)
 			m_r->getHeight(),
 			m_r->getHeight(),
 			RT_PIXEL_FORMAT,
 			RT_PIXEL_FORMAT,
 			TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE | TextureUsageBit::SAMPLED_FRAGMENT,
 			TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE | TextureUsageBit::SAMPLED_FRAGMENT,
-			SamplingFilter::LINEAR,
 			"Final Composite");
 			"Final Composite");
 		m_rtDescr.bake();
 		m_rtDescr.bake();
 
 
@@ -115,12 +114,14 @@ void FinalComposite::run(const RenderingContext& ctx, RenderPassWorkContext& rgr
 	rgraphCtx.bindTextureAndSampler(
 	rgraphCtx.bindTextureAndSampler(
 		0, 0, m_r->getTemporalAA().getRt(), (drawToDefaultFb) ? m_r->getNearestSampler() : m_r->getLinearSampler());
 		0, 0, m_r->getTemporalAA().getRt(), (drawToDefaultFb) ? m_r->getNearestSampler() : m_r->getLinearSampler());
 
 
-	rgraphCtx.bindTexture(0, 1, m_r->getBloom().getRt());
-	cmdb->bindTexture(0, 2, m_lut->getGrTexture(), TextureUsageBit::SAMPLED_FRAGMENT);
-	cmdb->bindTexture(0, 3, m_blueNoise->getGrTexture(), TextureUsageBit::SAMPLED_FRAGMENT);
+	rgraphCtx.bindTextureAndSampler(0, 1, m_r->getBloom().getRt(), m_r->getLinearSampler());
+	cmdb->bindTextureAndSampler(
+		0, 2, m_lut->getGrTexture(), m_r->getLinearSampler(), TextureUsageBit::SAMPLED_FRAGMENT);
+	cmdb->bindTextureAndSampler(
+		0, 3, m_blueNoise->getGrTexture(), m_blueNoise->getSampler(), TextureUsageBit::SAMPLED_FRAGMENT);
 	if(dbgEnabled)
 	if(dbgEnabled)
 	{
 	{
-		rgraphCtx.bindTexture(0, 5, m_r->getDbg().getRt());
+		rgraphCtx.bindTextureAndSampler(0, 5, m_r->getDbg().getRt(), m_r->getLinearSampler());
 	}
 	}
 
 
 	rgraphCtx.bindUniformBuffer(0, 1, m_r->getTonemapping().getAverageLuminanceBuffer());
 	rgraphCtx.bindUniformBuffer(0, 1, m_r->getTonemapping().getAverageLuminanceBuffer());

+ 12 - 8
src/anki/renderer/ForwardShading.cpp

@@ -43,7 +43,6 @@ Error ForwardShading::initInternal(const ConfigSet&)
 		m_height,
 		m_height,
 		FORWARD_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT,
 		FORWARD_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT,
 		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE,
 		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE,
-		SamplingFilter::LINEAR,
 		"forward");
 		"forward");
 	m_rtDescr.bake();
 	m_rtDescr.bake();
 
 
@@ -113,8 +112,9 @@ void ForwardShading::drawVolumetric(RenderingContext& ctx, RenderPassWorkContext
 
 
 	rgraphCtx.bindTextureAndSampler(0, 0, m_r->getDepthDownscale().getHalfDepthColorRt(), m_r->getNearestSampler());
 	rgraphCtx.bindTextureAndSampler(0, 0, m_r->getDepthDownscale().getHalfDepthColorRt(), m_r->getNearestSampler());
 	rgraphCtx.bindTextureAndSampler(0, 1, m_r->getDepthDownscale().getQuarterColorRt(), m_r->getNearestSampler());
 	rgraphCtx.bindTextureAndSampler(0, 1, m_r->getDepthDownscale().getQuarterColorRt(), m_r->getNearestSampler());
-	rgraphCtx.bindTexture(0, 2, m_r->getVolumetric().getRt());
-	cmdb->bindTexture(0, 3, m_vol.m_noiseTex->getGrTexture(), TextureUsageBit::SAMPLED_FRAGMENT);
+	rgraphCtx.bindTextureAndSampler(0, 2, m_r->getVolumetric().getRt(), m_r->getLinearSampler());
+	cmdb->bindTextureAndSampler(
+		0, 3, m_vol.m_noiseTex->getGrTexture(), m_r->getTrilinearRepeatSampler(), TextureUsageBit::SAMPLED_FRAGMENT);
 
 
 	drawQuad(cmdb);
 	drawQuad(cmdb);
 
 
@@ -133,10 +133,14 @@ void ForwardShading::drawUpscale(const RenderingContext& ctx, RenderPassWorkCont
 	computeLinearizeDepthOptimal(
 	computeLinearizeDepthOptimal(
 		ctx.m_renderQueue->m_cameraNear, ctx.m_renderQueue->m_cameraFar, linearDepth->x(), linearDepth->y());
 		ctx.m_renderQueue->m_cameraNear, ctx.m_renderQueue->m_cameraFar, linearDepth->x(), linearDepth->y());
 
 
-	rgraphCtx.bindTexture(0, 0, m_r->getGBuffer().getDepthRt());
+	rgraphCtx.bindTextureAndSampler(0, 0, m_r->getGBuffer().getDepthRt(), m_r->getNearestSampler());
 	rgraphCtx.bindTextureAndSampler(0, 1, m_r->getDepthDownscale().getHalfDepthColorRt(), m_r->getNearestSampler());
 	rgraphCtx.bindTextureAndSampler(0, 1, m_r->getDepthDownscale().getHalfDepthColorRt(), m_r->getNearestSampler());
-	rgraphCtx.bindTexture(0, 2, m_runCtx.m_rt);
-	cmdb->bindTexture(0, 3, m_upscale.m_noiseTex->getGrTexture(), TextureUsageBit::SAMPLED_FRAGMENT);
+	rgraphCtx.bindTextureAndSampler(0, 2, m_runCtx.m_rt, m_r->getLinearSampler());
+	cmdb->bindTextureAndSampler(0,
+		3,
+		m_upscale.m_noiseTex->getGrTexture(),
+		m_r->getTrilinearRepeatSampler(),
+		TextureUsageBit::SAMPLED_FRAGMENT);
 
 
 	cmdb->setBlendFactors(0, BlendFactor::ONE, BlendFactor::SRC_ALPHA);
 	cmdb->setBlendFactors(0, BlendFactor::ONE, BlendFactor::SRC_ALPHA);
 
 
@@ -161,8 +165,8 @@ void ForwardShading::run(RenderingContext& ctx, RenderPassWorkContext& rgraphCtx
 	if(start != end)
 	if(start != end)
 	{
 	{
 		const LightShadingResources& rsrc = m_r->getLightShading().getResources();
 		const LightShadingResources& rsrc = m_r->getLightShading().getResources();
-		rgraphCtx.bindTexture(0, 0, m_r->getDepthDownscale().getQuarterColorRt());
-		rgraphCtx.bindTexture(0, 1, m_r->getShadowMapping().getShadowmapRt());
+		rgraphCtx.bindTextureAndSampler(0, 0, m_r->getDepthDownscale().getQuarterColorRt(), m_r->getLinearSampler());
+		rgraphCtx.bindTextureAndSampler(0, 1, m_r->getShadowMapping().getShadowmapRt(), m_r->getLinearSampler());
 		bindUniforms(cmdb, 0, 0, rsrc.m_commonUniformsToken);
 		bindUniforms(cmdb, 0, 0, rsrc.m_commonUniformsToken);
 		bindUniforms(cmdb, 0, 1, rsrc.m_pointLightsToken);
 		bindUniforms(cmdb, 0, 1, rsrc.m_pointLightsToken);
 		bindUniforms(cmdb, 0, 2, rsrc.m_spotLightsToken);
 		bindUniforms(cmdb, 0, 2, rsrc.m_spotLightsToken);

+ 0 - 2
src/anki/renderer/GBuffer.cpp

@@ -39,7 +39,6 @@ Error GBuffer::initInternal(const ConfigSet& initializer)
 		m_r->getHeight(),
 		m_r->getHeight(),
 		GBUFFER_DEPTH_ATTACHMENT_PIXEL_FORMAT,
 		GBUFFER_DEPTH_ATTACHMENT_PIXEL_FORMAT,
 		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE,
 		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE,
-		SamplingFilter::NEAREST,
 		"GBuffer depth");
 		"GBuffer depth");
 	m_depthRtDescr.bake();
 	m_depthRtDescr.bake();
 
 
@@ -50,7 +49,6 @@ Error GBuffer::initInternal(const ConfigSet& initializer)
 			m_r->getHeight(),
 			m_r->getHeight(),
 			MS_COLOR_ATTACHMENT_PIXEL_FORMATS[i],
 			MS_COLOR_ATTACHMENT_PIXEL_FORMATS[i],
 			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
 			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
-			SamplingFilter::NEAREST,
 			rtNames[i]);
 			rtNames[i]);
 		m_colorRtDescrs[i].bake();
 		m_colorRtDescrs[i].bake();
 	}
 	}

+ 5 - 7
src/anki/renderer/Indirect.cpp

@@ -149,7 +149,6 @@ Error Indirect::initGBuffer(const ConfigSet& config)
 			m_gbuffer.m_tileSize,
 			m_gbuffer.m_tileSize,
 			MS_COLOR_ATTACHMENT_PIXEL_FORMATS[0],
 			MS_COLOR_ATTACHMENT_PIXEL_FORMATS[0],
 			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
 			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
-			SamplingFilter::NEAREST, // Because we don't want the light pass to bleed to near faces
 			"GI GBuffer");
 			"GI GBuffer");
 
 
 		// Create color RT descriptions
 		// Create color RT descriptions
@@ -200,10 +199,8 @@ Error Indirect::initLightShading(const ConfigSet& config)
 			LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT,
 			LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT,
 			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE
 			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE
 				| TextureUsageBit::GENERATE_MIPMAPS,
 				| TextureUsageBit::GENERATE_MIPMAPS,
-			SamplingFilter::LINEAR,
 			"GI refl");
 			"GI refl");
 		texinit.m_mipmapsCount = m_lightShading.m_mipCount;
 		texinit.m_mipmapsCount = m_lightShading.m_mipCount;
-		texinit.m_sampling.m_mipmapFilter = SamplingFilter::LINEAR;
 		texinit.m_type = TextureType::CUBE_ARRAY;
 		texinit.m_type = TextureType::CUBE_ARRAY;
 		texinit.m_layerCount = m_cacheEntries.getSize();
 		texinit.m_layerCount = m_cacheEntries.getSize();
 		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
@@ -252,7 +249,6 @@ Error Indirect::initIrradiance(const ConfigSet& config)
 			m_irradiance.m_tileSize,
 			m_irradiance.m_tileSize,
 			LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT,
 			LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT,
 			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
 			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
-			SamplingFilter::LINEAR,
 			"GI irr");
 			"GI irr");
 
 
 		texinit.m_layerCount = m_cacheEntries.getSize();
 		texinit.m_layerCount = m_cacheEntries.getSize();
@@ -452,11 +448,13 @@ void Indirect::runLightShading(U32 faceIdx, RenderPassWorkContext& rgraphCtx)
 	const ReflectionProbeQueueElement& probe = *m_ctx.m_probe;
 	const ReflectionProbeQueueElement& probe = *m_ctx.m_probe;
 
 
 	// Set common state for all lights
 	// Set common state for all lights
+	// NOTE: Use nearest sampler because we don't want the result to sample the near tiles
 	for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
 	for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
 	{
 	{
-		rgraphCtx.bindTexture(0, i, m_ctx.m_gbufferColorRts[i]);
+		rgraphCtx.bindTextureAndSampler(0, i, m_ctx.m_gbufferColorRts[i], m_r->getNearestSampler());
 	}
 	}
-	rgraphCtx.bindTexture(0, GBUFFER_COLOR_ATTACHMENT_COUNT, m_ctx.m_gbufferDepthRt);
+	rgraphCtx.bindTextureAndSampler(
+		0, GBUFFER_COLOR_ATTACHMENT_COUNT, m_ctx.m_gbufferDepthRt, m_r->getNearestSampler());
 	cmdb->setVertexAttribute(0, 0, PixelFormat(ComponentFormat::R32G32B32, TransformFormat::FLOAT), 0);
 	cmdb->setVertexAttribute(0, 0, PixelFormat(ComponentFormat::R32G32B32, TransformFormat::FLOAT), 0);
 	cmdb->setViewport(0, 0, m_lightShading.m_tileSize, m_lightShading.m_tileSize);
 	cmdb->setViewport(0, 0, m_lightShading.m_tileSize, m_lightShading.m_tileSize);
 	cmdb->setBlendFactors(0, BlendFactor::ONE, BlendFactor::ONE);
 	cmdb->setBlendFactors(0, BlendFactor::ONE, BlendFactor::ONE);
@@ -586,7 +584,7 @@ void Indirect::runIrradiance(U32 faceIdx, RenderPassWorkContext& rgraphCtx)
 
 
 	// Set state
 	// Set state
 	cmdb->bindShaderProgram(m_irradiance.m_grProg);
 	cmdb->bindShaderProgram(m_irradiance.m_grProg);
-	rgraphCtx.bindTexture(0, 0, m_ctx.m_lightShadingRt);
+	rgraphCtx.bindTextureAndSampler(0, 0, m_ctx.m_lightShadingRt, m_r->getLinearSampler());
 	cmdb->setViewport(0, 0, m_irradiance.m_tileSize, m_irradiance.m_tileSize);
 	cmdb->setViewport(0, 0, m_irradiance.m_tileSize, m_irradiance.m_tileSize);
 
 
 	// Set uniforms
 	// Set uniforms

+ 4 - 2
src/anki/renderer/LensFlare.cpp

@@ -114,7 +114,8 @@ void LensFlare::updateIndirectInfo(const RenderingContext& ctx, RenderPassWorkCo
 	}
 	}
 
 
 	rgraphCtx.bindStorageBuffer(0, 1, m_runCtx.m_indirectBuffHandle);
 	rgraphCtx.bindStorageBuffer(0, 1, m_runCtx.m_indirectBuffHandle);
-	rgraphCtx.bindTexture(0, 0, m_r->getDepthDownscale().getQuarterColorRt());
+	// Bind neareset because you don't need high quality
+	rgraphCtx.bindTextureAndSampler(0, 0, m_r->getDepthDownscale().getQuarterColorRt(), m_r->getNearestSampler());
 	cmdb->dispatchCompute(count, 1, 1);
 	cmdb->dispatchCompute(count, 1, 1);
 }
 }
 
 
@@ -196,7 +197,8 @@ void LensFlare::runDrawFlares(const RenderingContext& ctx, CommandBufferPtr& cmd
 
 
 		// Render
 		// Render
 		ANKI_ASSERT(flareEl.m_texture);
 		ANKI_ASSERT(flareEl.m_texture);
-		cmdb->bindTexture(0, 0, TexturePtr(flareEl.m_texture), TextureUsageBit::SAMPLED_FRAGMENT);
+		cmdb->bindTextureAndSampler(
+			0, 0, TexturePtr(flareEl.m_texture), m_r->getTrilinearRepeatSampler(), TextureUsageBit::SAMPLED_FRAGMENT);
 
 
 		cmdb->drawArraysIndirect(
 		cmdb->drawArraysIndirect(
 			PrimitiveTopology::TRIANGLE_STRIP, 1, i * sizeof(DrawArraysIndirectInfo), m_indirectBuff);
 			PrimitiveTopology::TRIANGLE_STRIP, 1, i * sizeof(DrawArraysIndirectInfo), m_indirectBuff);

+ 15 - 12
src/anki/renderer/LightShading.cpp

@@ -94,7 +94,6 @@ Error LightShading::initInternal(const ConfigSet& config)
 		m_r->getHeight(),
 		m_r->getHeight(),
 		LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT,
 		LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT,
 		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE,
 		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE,
-		SamplingFilter::LINEAR,
 		"Light Shading");
 		"Light Shading");
 	m_rtDescr.bake();
 	m_rtDescr.bake();
 
 
@@ -131,25 +130,29 @@ void LightShading::run(const RenderingContext& ctx, RenderPassWorkContext& rgrap
 	cmdb->setViewport(0, 0, m_r->getWidth(), m_r->getHeight());
 	cmdb->setViewport(0, 0, m_r->getWidth(), m_r->getHeight());
 	cmdb->bindShaderProgram(m_progVariant->getProgram());
 	cmdb->bindShaderProgram(m_progVariant->getProgram());
 
 
-	rgraphCtx.bindTexture(1, 0, m_r->getGBuffer().getColorRt(0));
-	rgraphCtx.bindTexture(1, 1, m_r->getGBuffer().getColorRt(1));
-	rgraphCtx.bindTexture(1, 2, m_r->getGBuffer().getColorRt(2));
-	rgraphCtx.bindTexture(1, 3, m_r->getGBuffer().getDepthRt());
-	rgraphCtx.bindTexture(1, 4, m_r->getSsao().getRt());
+	rgraphCtx.bindTextureAndSampler(1, 0, m_r->getGBuffer().getColorRt(0), m_r->getNearestSampler());
+	rgraphCtx.bindTextureAndSampler(1, 1, m_r->getGBuffer().getColorRt(1), m_r->getNearestSampler());
+	rgraphCtx.bindTextureAndSampler(1, 2, m_r->getGBuffer().getColorRt(2), m_r->getNearestSampler());
+	rgraphCtx.bindTextureAndSampler(1, 3, m_r->getGBuffer().getDepthRt(), m_r->getNearestSampler());
+	rgraphCtx.bindTextureAndSampler(1, 4, m_r->getSsao().getRt(), m_r->getLinearSampler());
 
 
-	rgraphCtx.bindTexture(0, 0, m_r->getShadowMapping().getShadowmapRt());
-	rgraphCtx.bindTexture(0, 1, m_r->getIndirect().getReflectionRt());
-	rgraphCtx.bindTexture(0, 2, m_r->getIndirect().getIrradianceRt());
+	rgraphCtx.bindTextureAndSampler(0, 0, m_r->getShadowMapping().getShadowmapRt(), m_r->getLinearSampler());
+	rgraphCtx.bindTextureAndSampler(0, 1, m_r->getIndirect().getReflectionRt(), m_r->getLinearSampler());
+	rgraphCtx.bindTextureAndSampler(0, 2, m_r->getIndirect().getIrradianceRt(), m_r->getLinearSampler());
 	cmdb->bindTextureAndSampler(0,
 	cmdb->bindTextureAndSampler(0,
 		3,
 		3,
 		m_r->getIndirect().getIntegrationLut(),
 		m_r->getIndirect().getIntegrationLut(),
 		m_r->getIndirect().getIntegrationLutSampler(),
 		m_r->getIndirect().getIntegrationLutSampler(),
 		TextureUsageBit::SAMPLED_FRAGMENT);
 		TextureUsageBit::SAMPLED_FRAGMENT);
-	cmdb->bindTexture(
-		0, 4, (rsrc.m_diffDecalTex) ? rsrc.m_diffDecalTex : m_r->getDummyTexture(), TextureUsageBit::SAMPLED_FRAGMENT);
-	cmdb->bindTexture(0,
+	cmdb->bindTextureAndSampler(0,
+		4,
+		(rsrc.m_diffDecalTex) ? rsrc.m_diffDecalTex : m_r->getDummyTexture(),
+		m_r->getTrilinearRepeatSampler(),
+		TextureUsageBit::SAMPLED_FRAGMENT);
+	cmdb->bindTextureAndSampler(0,
 		5,
 		5,
 		(rsrc.m_normRoughnessDecalTex) ? rsrc.m_normRoughnessDecalTex : m_r->getDummyTexture(),
 		(rsrc.m_normRoughnessDecalTex) ? rsrc.m_normRoughnessDecalTex : m_r->getDummyTexture(),
+		m_r->getTrilinearRepeatSampler(),
 		TextureUsageBit::SAMPLED_FRAGMENT);
 		TextureUsageBit::SAMPLED_FRAGMENT);
 
 
 	bindUniforms(cmdb, 0, 0, rsrc.m_commonUniformsToken);
 	bindUniforms(cmdb, 0, 0, rsrc.m_commonUniformsToken);

+ 1 - 1
src/anki/renderer/MainRenderer.cpp

@@ -156,7 +156,7 @@ void MainRenderer::runBlit(RenderPassWorkContext& rgraphCtx)
 	cmdb->setViewport(0, 0, m_width, m_height);
 	cmdb->setViewport(0, 0, m_width, m_height);
 
 
 	cmdb->bindShaderProgram(m_blitGrProg);
 	cmdb->bindShaderProgram(m_blitGrProg);
-	rgraphCtx.bindTexture(0, 0, m_r->getFinalComposite().getRt());
+	rgraphCtx.bindTextureAndSampler(0, 0, m_r->getFinalComposite().getRt(), m_r->getLinearSampler());
 
 
 	cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 3, 1);
 	cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 3, 1);
 }
 }

+ 8 - 10
src/anki/renderer/Renderer.cpp

@@ -147,14 +147,19 @@ Error Renderer::initInternal(const ConfigSet& config)
 	m_dbg.reset(m_alloc.newInstance<Dbg>(this));
 	m_dbg.reset(m_alloc.newInstance<Dbg>(this));
 	ANKI_CHECK(m_dbg->init(config));
 	ANKI_CHECK(m_dbg->init(config));
 
 
-	SamplerInitInfo sinit;
+	SamplerInitInfo sinit("Renderer");
 	sinit.m_repeat = false;
 	sinit.m_repeat = false;
+	sinit.m_mipmapFilter = SamplingFilter::BASE;
 	sinit.m_minMagFilter = SamplingFilter::NEAREST;
 	sinit.m_minMagFilter = SamplingFilter::NEAREST;
 	m_nearestSampler = m_gr->newSampler(sinit);
 	m_nearestSampler = m_gr->newSampler(sinit);
 
 
 	sinit.m_minMagFilter = SamplingFilter::LINEAR;
 	sinit.m_minMagFilter = SamplingFilter::LINEAR;
 	m_linearSampler = m_gr->newSampler(sinit);
 	m_linearSampler = m_gr->newSampler(sinit);
 
 
+	sinit.m_mipmapFilter = SamplingFilter::LINEAR;
+	sinit.m_repeat = true;
+	m_trilinearRepeatSampler = m_gr->newSampler(sinit);
+
 	initJitteredMats();
 	initJitteredMats();
 
 
 	return Error::NONE;
 	return Error::NONE;
@@ -292,7 +297,7 @@ Vec3 Renderer::unproject(
 }
 }
 
 
 TextureInitInfo Renderer::create2DRenderTargetInitInfo(
 TextureInitInfo Renderer::create2DRenderTargetInitInfo(
-	U32 w, U32 h, const PixelFormat& format, TextureUsageBit usage, SamplingFilter filter, CString name)
+	U32 w, U32 h, const PixelFormat& format, TextureUsageBit usage, CString name)
 {
 {
 	ANKI_ASSERT(!!(usage & TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE));
 	ANKI_ASSERT(!!(usage & TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE));
 	TextureInitInfo init(name);
 	TextureInitInfo init(name);
@@ -306,15 +311,12 @@ TextureInitInfo Renderer::create2DRenderTargetInitInfo(
 	init.m_mipmapsCount = 1;
 	init.m_mipmapsCount = 1;
 	init.m_samples = 1;
 	init.m_samples = 1;
 	init.m_usage = usage;
 	init.m_usage = usage;
-	init.m_sampling.m_minMagFilter = filter;
-	init.m_sampling.m_repeat = false;
-	init.m_sampling.m_anisotropyLevel = 0;
 
 
 	return init;
 	return init;
 }
 }
 
 
 RenderTargetDescription Renderer::create2DRenderTargetDescription(
 RenderTargetDescription Renderer::create2DRenderTargetDescription(
-	U32 w, U32 h, const PixelFormat& format, TextureUsageBit usage, SamplingFilter filter, CString name)
+	U32 w, U32 h, const PixelFormat& format, TextureUsageBit usage, CString name)
 {
 {
 	ANKI_ASSERT(!!(usage & TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE));
 	ANKI_ASSERT(!!(usage & TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE));
 	RenderTargetDescription init(name);
 	RenderTargetDescription init(name);
@@ -328,10 +330,6 @@ RenderTargetDescription Renderer::create2DRenderTargetDescription(
 	init.m_mipmapsCount = 1;
 	init.m_mipmapsCount = 1;
 	init.m_samples = 1;
 	init.m_samples = 1;
 	init.m_usage = usage;
 	init.m_usage = usage;
-	init.m_sampling.m_minMagFilter = filter;
-	init.m_sampling.m_mipmapFilter = filter;
-	init.m_sampling.m_repeat = false;
-	init.m_sampling.m_anisotropyLevel = 0;
 
 
 	return init;
 	return init;
 }
 }

+ 8 - 2
src/anki/renderer/Renderer.h

@@ -225,11 +225,11 @@ anki_internal:
 
 
 	/// Create the init info for a 2D texture that will be used as a render target.
 	/// Create the init info for a 2D texture that will be used as a render target.
 	ANKI_USE_RESULT TextureInitInfo create2DRenderTargetInitInfo(
 	ANKI_USE_RESULT TextureInitInfo create2DRenderTargetInitInfo(
-		U32 w, U32 h, const PixelFormat& format, TextureUsageBit usage, SamplingFilter filter, CString name = {});
+		U32 w, U32 h, const PixelFormat& format, TextureUsageBit usage, CString name = {});
 
 
 	/// Create the init info for a 2D texture that will be used as a render target.
 	/// Create the init info for a 2D texture that will be used as a render target.
 	ANKI_USE_RESULT RenderTargetDescription create2DRenderTargetDescription(
 	ANKI_USE_RESULT RenderTargetDescription create2DRenderTargetDescription(
-		U32 w, U32 h, const PixelFormat& format, TextureUsageBit usage, SamplingFilter filter, CString name = {});
+		U32 w, U32 h, const PixelFormat& format, TextureUsageBit usage, CString name = {});
 
 
 	ANKI_USE_RESULT TexturePtr createAndClearRenderTarget(
 	ANKI_USE_RESULT TexturePtr createAndClearRenderTarget(
 		const TextureInitInfo& inf, const ClearValue& clearVal = ClearValue());
 		const TextureInitInfo& inf, const ClearValue& clearVal = ClearValue());
@@ -310,6 +310,11 @@ anki_internal:
 		return m_linearSampler;
 		return m_linearSampler;
 	}
 	}
 
 
+	SamplerPtr getTrilinearRepeatSampler() const
+	{
+		return m_trilinearRepeatSampler;
+	}
+
 private:
 private:
 	ThreadPool* m_threadpool = nullptr;
 	ThreadPool* m_threadpool = nullptr;
 	ResourceManager* m_resources = nullptr;
 	ResourceManager* m_resources = nullptr;
@@ -365,6 +370,7 @@ private:
 
 
 	SamplerPtr m_nearestSampler;
 	SamplerPtr m_nearestSampler;
 	SamplerPtr m_linearSampler;
 	SamplerPtr m_linearSampler;
+	SamplerPtr m_trilinearRepeatSampler;
 
 
 	ANKI_USE_RESULT Error initInternal(const ConfigSet& initializer);
 	ANKI_USE_RESULT Error initInternal(const ConfigSet& initializer);
 
 

+ 1 - 3
src/anki/renderer/ShadowMapping.cpp

@@ -52,7 +52,6 @@ Error ShadowMapping::initScratch(const ConfigSet& cfg)
 			m_scratchTileResolution,
 			m_scratchTileResolution,
 			SHADOW_DEPTH_PIXEL_FORMAT,
 			SHADOW_DEPTH_PIXEL_FORMAT,
 			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE,
 			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE,
-			SamplingFilter::LINEAR,
 			"Scratch ShadMap");
 			"Scratch ShadMap");
 		m_scratchRtDescr.bake();
 		m_scratchRtDescr.bake();
 
 
@@ -79,7 +78,6 @@ Error ShadowMapping::initEsm(const ConfigSet& cfg)
 			m_atlasResolution,
 			m_atlasResolution,
 			SHADOW_COLOR_PIXEL_FORMAT,
 			SHADOW_COLOR_PIXEL_FORMAT,
 			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
 			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
-			SamplingFilter::LINEAR,
 			"esm");
 			"esm");
 		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 		ClearValue clearVal;
 		ClearValue clearVal;
@@ -151,7 +149,7 @@ void ShadowMapping::runEsm(RenderPassWorkContext& rgraphCtx)
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 
 
 	cmdb->bindShaderProgram(m_esmResolveGrProg);
 	cmdb->bindShaderProgram(m_esmResolveGrProg);
-	rgraphCtx.bindTexture(0, 0, m_scratchRt);
+	rgraphCtx.bindTextureAndSampler(0, 0, m_scratchRt, m_r->getLinearSampler());
 
 
 	for(const EsmResolveWorkItem& workItem : m_esmResolveWorkItems)
 	for(const EsmResolveWorkItem& workItem : m_esmResolveWorkItems)
 	{
 	{

+ 8 - 8
src/anki/renderer/Ssao.cpp

@@ -93,7 +93,6 @@ Error Ssao::init(const ConfigSet& config)
 			m_height,
 			m_height,
 			Ssao::RT_PIXEL_FORMAT,
 			Ssao::RT_PIXEL_FORMAT,
 			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE | TextureUsageBit::CLEAR,
 			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE | TextureUsageBit::CLEAR,
-			SamplingFilter::LINEAR,
 			&RT_NAMES[i][0]);
 			&RT_NAMES[i][0]);
 		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 
 
@@ -132,10 +131,11 @@ void Ssao::runMain(const RenderingContext& ctx, RenderPassWorkContext& rgraphCtx
 	cmdb->setViewport(0, 0, m_width, m_height);
 	cmdb->setViewport(0, 0, m_width, m_height);
 	cmdb->bindShaderProgram(m_main.m_grProg);
 	cmdb->bindShaderProgram(m_main.m_grProg);
 
 
-	rgraphCtx.bindTexture(0, 0, m_r->getDepthDownscale().getQuarterColorRt());
+	rgraphCtx.bindTextureAndSampler(0, 0, m_r->getDepthDownscale().getQuarterColorRt(), m_r->getLinearSampler());
 	rgraphCtx.bindTextureAndSampler(0, 1, m_r->getGBuffer().getColorRt(2), m_r->getLinearSampler());
 	rgraphCtx.bindTextureAndSampler(0, 1, m_r->getGBuffer().getColorRt(2), m_r->getLinearSampler());
-	cmdb->bindTexture(0, 2, m_main.m_noiseTex->getGrTexture(), TextureUsageBit::SAMPLED_FRAGMENT);
-	rgraphCtx.bindTexture(0, 3, m_runCtx.m_rts[(m_r->getFrameCount() + 1) & 1]);
+	cmdb->bindTextureAndSampler(
+		0, 2, m_main.m_noiseTex->getGrTexture(), m_r->getTrilinearRepeatSampler(), TextureUsageBit::SAMPLED_FRAGMENT);
+	rgraphCtx.bindTextureAndSampler(0, 3, m_runCtx.m_rts[(m_r->getFrameCount() + 1) & 1], m_r->getLinearSampler());
 
 
 	struct Unis
 	struct Unis
 	{
 	{
@@ -162,8 +162,8 @@ void Ssao::runHBlur(RenderPassWorkContext& rgraphCtx)
 
 
 	cmdb->setViewport(0, 0, m_width, m_height);
 	cmdb->setViewport(0, 0, m_width, m_height);
 	cmdb->bindShaderProgram(m_hblur.m_grProg);
 	cmdb->bindShaderProgram(m_hblur.m_grProg);
-	rgraphCtx.bindTexture(0, 0, m_runCtx.m_rts[m_r->getFrameCount() & 1]);
-	rgraphCtx.bindTexture(0, 1, m_r->getDepthDownscale().getQuarterColorRt());
+	rgraphCtx.bindTextureAndSampler(0, 0, m_runCtx.m_rts[m_r->getFrameCount() & 1], m_r->getLinearSampler());
+	rgraphCtx.bindTextureAndSampler(0, 1, m_r->getDepthDownscale().getQuarterColorRt(), m_r->getLinearSampler());
 	drawQuad(cmdb);
 	drawQuad(cmdb);
 }
 }
 
 
@@ -173,8 +173,8 @@ void Ssao::runVBlur(RenderPassWorkContext& rgraphCtx)
 
 
 	cmdb->setViewport(0, 0, m_width, m_height);
 	cmdb->setViewport(0, 0, m_width, m_height);
 	cmdb->bindShaderProgram(m_vblur.m_grProg);
 	cmdb->bindShaderProgram(m_vblur.m_grProg);
-	rgraphCtx.bindTexture(0, 0, m_runCtx.m_rts[(m_r->getFrameCount() + 1) & 1]);
-	rgraphCtx.bindTexture(0, 1, m_r->getDepthDownscale().getQuarterColorRt());
+	rgraphCtx.bindTextureAndSampler(0, 0, m_runCtx.m_rts[(m_r->getFrameCount() + 1) & 1], m_r->getLinearSampler());
+	rgraphCtx.bindTextureAndSampler(0, 1, m_r->getDepthDownscale().getQuarterColorRt(), m_r->getLinearSampler());
 	drawQuad(cmdb);
 	drawQuad(cmdb);
 }
 }
 
 

+ 0 - 1
src/anki/renderer/TemporalAA.cpp

@@ -57,7 +57,6 @@ Error TemporalAA::initInternal(const ConfigSet& config)
 			m_r->getHeight(),
 			m_r->getHeight(),
 			LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT,
 			LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT,
 			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
 			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
-			SamplingFilter::LINEAR,
 			"TemporalAA"));
 			"TemporalAA"));
 	}
 	}
 
 

+ 1 - 1
src/anki/renderer/Tonemapping.cpp

@@ -68,7 +68,7 @@ void Tonemapping::run(RenderPassWorkContext& rgraphCtx)
 
 
 	cmdb->bindShaderProgram(m_grProg);
 	cmdb->bindShaderProgram(m_grProg);
 	rgraphCtx.bindStorageBuffer(0, 0, m_runCtx.m_buffHandle);
 	rgraphCtx.bindStorageBuffer(0, 0, m_runCtx.m_buffHandle);
-	rgraphCtx.bindTexture(0, 0, m_r->getDownscaleBlur().getPassRt(m_rtIdx));
+	rgraphCtx.bindTextureAndSampler(0, 0, m_r->getDownscaleBlur().getPassRt(m_rtIdx), m_r->getLinearSampler());
 
 
 	cmdb->dispatchCompute(1, 1, 1);
 	cmdb->dispatchCompute(1, 1, 1);
 }
 }

+ 7 - 7
src/anki/renderer/Volumetric.cpp

@@ -88,7 +88,6 @@ Error Volumetric::init(const ConfigSet& config)
 			m_height,
 			m_height,
 			LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT,
 			LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT,
 			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
 			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
-			SamplingFilter::LINEAR,
 			"volmain");
 			"volmain");
 		rtInit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 		rtInit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 		m_rtTextures[i] = m_r->createAndClearRenderTarget(rtInit);
 		m_rtTextures[i] = m_r->createAndClearRenderTarget(rtInit);
@@ -125,10 +124,11 @@ void Volumetric::runMain(const RenderingContext& ctx, RenderPassWorkContext& rgr
 
 
 	cmdb->setViewport(0, 0, m_width, m_height);
 	cmdb->setViewport(0, 0, m_width, m_height);
 
 
-	rgraphCtx.bindTexture(0, 0, m_r->getDepthDownscale().getQuarterColorRt());
-	cmdb->bindTexture(0, 1, m_main.m_noiseTex->getGrTexture(), TextureUsageBit::SAMPLED_FRAGMENT);
-	rgraphCtx.bindTexture(0, 2, m_runCtx.m_rts[(m_r->getFrameCount() + 1) & 1]);
-	rgraphCtx.bindTexture(0, 3, m_r->getShadowMapping().getShadowmapRt());
+	rgraphCtx.bindTextureAndSampler(0, 0, m_r->getDepthDownscale().getQuarterColorRt(), m_r->getLinearSampler());
+	cmdb->bindTextureAndSampler(
+		0, 1, m_main.m_noiseTex->getGrTexture(), m_r->getTrilinearRepeatSampler(), TextureUsageBit::SAMPLED_FRAGMENT);
+	rgraphCtx.bindTextureAndSampler(0, 2, m_runCtx.m_rts[(m_r->getFrameCount() + 1) & 1], m_r->getLinearSampler());
+	rgraphCtx.bindTextureAndSampler(0, 3, m_r->getShadowMapping().getShadowmapRt(), m_r->getLinearSampler());
 
 
 	const LightShadingResources& rsrc = m_r->getLightShading().getResources();
 	const LightShadingResources& rsrc = m_r->getLightShading().getResources();
 	bindUniforms(cmdb, 0, 0, rsrc.m_commonUniformsToken);
 	bindUniforms(cmdb, 0, 0, rsrc.m_commonUniformsToken);
@@ -166,7 +166,7 @@ void Volumetric::runHBlur(RenderPassWorkContext& rgraphCtx)
 {
 {
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 
 
-	rgraphCtx.bindTexture(0, 0, m_runCtx.m_rts[m_r->getFrameCount() & 1]);
+	rgraphCtx.bindTextureAndSampler(0, 0, m_runCtx.m_rts[m_r->getFrameCount() & 1], m_r->getLinearSampler());
 	cmdb->bindShaderProgram(m_hblur.m_grProg);
 	cmdb->bindShaderProgram(m_hblur.m_grProg);
 	cmdb->setViewport(0, 0, m_width, m_height);
 	cmdb->setViewport(0, 0, m_width, m_height);
 
 
@@ -177,7 +177,7 @@ void Volumetric::runVBlur(RenderPassWorkContext& rgraphCtx)
 {
 {
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 
 
-	rgraphCtx.bindTexture(0, 0, m_runCtx.m_rts[(m_r->getFrameCount() + 1) & 1]);
+	rgraphCtx.bindTextureAndSampler(0, 0, m_runCtx.m_rts[(m_r->getFrameCount() + 1) & 1], m_r->getLinearSampler());
 	cmdb->bindShaderProgram(m_vblur.m_grProg);
 	cmdb->bindShaderProgram(m_vblur.m_grProg);
 	cmdb->setViewport(0, 0, m_width, m_height);
 	cmdb->setViewport(0, 0, m_width, m_height);
 
 

+ 8 - 10
src/anki/resource/TextureResource.cpp

@@ -162,16 +162,6 @@ Error TextureResource::load(const ResourceFilename& filename, Bool async)
 	// mipmapsCount
 	// mipmapsCount
 	init.m_mipmapsCount = loader.getMipLevelsCount();
 	init.m_mipmapsCount = loader.getMipLevelsCount();
 
 
-	// filteringType
-	init.m_sampling.m_minMagFilter = SamplingFilter::LINEAR;
-	init.m_sampling.m_mipmapFilter = SamplingFilter::LINEAR;
-
-	// repeat
-	init.m_sampling.m_repeat = true;
-
-	// Anisotropy
-	init.m_sampling.m_anisotropyLevel = getManager().getTextureAnisotropy();
-
 	// Create the texture
 	// Create the texture
 	m_tex = getManager().getGrManager().newTexture(init);
 	m_tex = getManager().getGrManager().newTexture(init);
 
 
@@ -193,6 +183,14 @@ Error TextureResource::load(const ResourceFilename& filename, Bool async)
 		ANKI_CHECK(load(*ctx));
 		ANKI_CHECK(load(*ctx));
 	}
 	}
 
 
+	// Create sampler
+	SamplerInitInfo samplerInit("TextureRsrc");
+	samplerInit.m_minMagFilter = SamplingFilter::LINEAR;
+	samplerInit.m_mipmapFilter = SamplingFilter::LINEAR;
+	samplerInit.m_repeat = true;
+	samplerInit.m_anisotropyLevel = getManager().getTextureAnisotropy();
+	m_sampler = getManager().getGrManager().newSampler(samplerInit);
+
 	m_size = UVec3(init.m_width, init.m_height, init.m_depth);
 	m_size = UVec3(init.m_width, init.m_height, init.m_depth);
 	m_layerCount = init.m_layerCount;
 	m_layerCount = init.m_layerCount;
 	return Error::NONE;
 	return Error::NONE;

+ 7 - 0
src/anki/resource/TextureResource.h

@@ -37,6 +37,12 @@ public:
 		return m_tex;
 		return m_tex;
 	}
 	}
 
 
+	/// Get the sampler.
+	const SamplerPtr& getSampler() const
+	{
+		return m_sampler;
+	}
+
 	/// Get the texture
 	/// Get the texture
 	TexturePtr& getGrTexture()
 	TexturePtr& getGrTexture()
 	{
 	{
@@ -74,6 +80,7 @@ private:
 	class LoadingContext;
 	class LoadingContext;
 
 
 	TexturePtr m_tex;
 	TexturePtr m_tex;
+	SamplerPtr m_sampler;
 	UVec3 m_size = UVec3(0u);
 	UVec3 m_size = UVec3(0u);
 	U32 m_layerCount = 0;
 	U32 m_layerCount = 0;
 
 

+ 2 - 2
src/anki/scene/ParticleEmitter.cpp

@@ -372,8 +372,8 @@ Error ParticleEmitter::frameUpdate(Second prevUpdateTime, Second crntTime)
 	// - Calc the AABB
 	// - Calc the AABB
 	// - Calc the instancing stuff
 	// - Calc the instancing stuff
 	//
 	//
-	Vec4 aabbmin(MAX_F32, MAX_F32, MAX_F32, 0.0);
-	Vec4 aabbmax(MIN_F32, MIN_F32, MIN_F32, 0.0);
+	Vec4 aabbmin(MAX_F32, MAX_F32, MAX_F32, 0.0f);
+	Vec4 aabbmax(MIN_F32, MIN_F32, MIN_F32, 0.0f);
 	m_aliveParticlesCount = 0;
 	m_aliveParticlesCount = 0;
 
 
 	F32* verts = static_cast<F32*>(getSceneGraph().getStagingGpuMemoryManager().allocateFrame(
 	F32* verts = static_cast<F32*>(getSceneGraph().getStagingGpuMemoryManager().allocateFrame(

+ 2 - 1
src/anki/scene/RenderComponent.cpp

@@ -185,9 +185,10 @@ void RenderComponent::allocateAndSetupUniforms(
 		case ShaderVariableDataType::SAMPLER_3D:
 		case ShaderVariableDataType::SAMPLER_3D:
 		case ShaderVariableDataType::SAMPLER_CUBE:
 		case ShaderVariableDataType::SAMPLER_CUBE:
 		{
 		{
-			ctx.m_commandBuffer->bindTexture(set,
+			ctx.m_commandBuffer->bindTextureAndSampler(set,
 				progVariant.getTextureUnit(progvar),
 				progVariant.getTextureUnit(progvar),
 				mvar.getValue<TextureResourcePtr>()->getGrTexture(),
 				mvar.getValue<TextureResourcePtr>()->getGrTexture(),
+				mvar.getValue<TextureResourcePtr>()->getSampler(),
 				TextureUsageBit::SAMPLED_FRAGMENT);
 				TextureUsageBit::SAMPLED_FRAGMENT);
 			break;
 			break;
 		}
 		}

+ 7 - 1
src/anki/ui/Canvas.cpp

@@ -54,6 +54,12 @@ Error Canvas::init(FontPtr font, U32 fontHeight)
 		getAllocator().getMemoryPool().getAllocationCallbackUserData(),
 		getAllocator().getMemoryPool().getAllocationCallbackUserData(),
 		512_B);
 		512_B);
 
 
+	SamplerInitInfo samplerInit("Canvas");
+	samplerInit.m_minMagFilter = SamplingFilter::LINEAR;
+	samplerInit.m_mipmapFilter = SamplingFilter::LINEAR;
+	samplerInit.m_repeat = true;
+	m_sampler = m_manager->getGrManager().newSampler(samplerInit);
+
 	return Error::NONE;
 	return Error::NONE;
 }
 }
 
 
@@ -228,7 +234,7 @@ void Canvas::appendToCommandBuffer(CommandBufferPtr cmdb)
 			progToBind = m_grProgs[RGBA_TEX];
 			progToBind = m_grProgs[RGBA_TEX];
 
 
 			Texture* t = numberToPtr<Texture*>(ptrToNumber(cmd->texture.ptr) & ~FONT_TEXTURE_MASK);
 			Texture* t = numberToPtr<Texture*>(ptrToNumber(cmd->texture.ptr) & ~FONT_TEXTURE_MASK);
-			cmdb->bindTexture(0, 0, TexturePtr(t), TextureUsageBit::SAMPLED_FRAGMENT);
+			cmdb->bindTextureAndSampler(0, 0, TexturePtr(t), m_sampler, TextureUsageBit::SAMPLED_FRAGMENT);
 		}
 		}
 		else
 		else
 		{
 		{

+ 1 - 0
src/anki/ui/Canvas.h

@@ -72,6 +72,7 @@ private:
 
 
 	ShaderProgramResourcePtr m_prog;
 	ShaderProgramResourcePtr m_prog;
 	Array<ShaderProgramPtr, SHADER_COUNT> m_grProgs;
 	Array<ShaderProgramPtr, SHADER_COUNT> m_grProgs;
+	SamplerPtr m_sampler;
 
 
 	StackAllocator<U8> m_stackAlloc;
 	StackAllocator<U8> m_stackAlloc;
 
 

+ 0 - 2
src/anki/ui/Font.cpp

@@ -84,8 +84,6 @@ void Font::createTexture(const void* data, U32 width, U32 height)
 	texInit.m_usage =
 	texInit.m_usage =
 		TextureUsageBit::TRANSFER_DESTINATION | TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::GENERATE_MIPMAPS;
 		TextureUsageBit::TRANSFER_DESTINATION | TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::GENERATE_MIPMAPS;
 	texInit.m_mipmapsCount = 4;
 	texInit.m_mipmapsCount = 4;
-	texInit.m_sampling.m_minMagFilter = SamplingFilter::NEAREST;
-	texInit.m_sampling.m_mipmapFilter = SamplingFilter::NEAREST;
 
 
 	m_tex = m_manager->getGrManager().newTexture(texInit);
 	m_tex = m_manager->getGrManager().newTexture(texInit);
 
 

+ 37 - 20
tests/gr/Gr.cpp

@@ -578,8 +578,6 @@ ANKI_TEST(Gr, ViewportAndScissorOffscreen)
 	init.m_depth = 1;
 	init.m_depth = 1;
 	init.m_layerCount = 1;
 	init.m_layerCount = 1;
 	init.m_samples = 1;
 	init.m_samples = 1;
-	init.m_sampling.m_minMagFilter = SamplingFilter::NEAREST;
-	init.m_sampling.m_mipmapFilter = SamplingFilter::NEAREST;
 	init.m_type = TextureType::_2D;
 	init.m_type = TextureType::_2D;
 	TexturePtr rt = gr->newTexture(init);
 	TexturePtr rt = gr->newTexture(init);
 
 
@@ -596,6 +594,11 @@ ANKI_TEST(Gr, ViewportAndScissorOffscreen)
 
 
 	FramebufferPtr defaultFb = createDefaultFb(*gr);
 	FramebufferPtr defaultFb = createDefaultFb(*gr);
 
 
+	SamplerInitInfo samplerInit;
+	samplerInit.m_minMagFilter = SamplingFilter::NEAREST;
+	samplerInit.m_mipmapFilter = SamplingFilter::BASE;
+	SamplerPtr sampler = gr->newSampler(samplerInit);
+
 	static const Array2d<U, 4, 4> VIEWPORTS = {{{{0, 0, RT_WIDTH / 2, RT_HEIGHT / 2}},
 	static const Array2d<U, 4, 4> VIEWPORTS = {{{{0, 0, RT_WIDTH / 2, RT_HEIGHT / 2}},
 		{{RT_WIDTH / 2, 0, RT_WIDTH / 2, RT_HEIGHT / 2}},
 		{{RT_WIDTH / 2, 0, RT_WIDTH / 2, RT_HEIGHT / 2}},
 		{{RT_WIDTH / 2, RT_HEIGHT / 2, RT_WIDTH / 2, RT_HEIGHT / 2}},
 		{{RT_WIDTH / 2, RT_HEIGHT / 2, RT_WIDTH / 2, RT_HEIGHT / 2}},
@@ -663,7 +666,7 @@ ANKI_TEST(Gr, ViewportAndScissorOffscreen)
 			TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
 			TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
 			TextureUsageBit::SAMPLED_FRAGMENT,
 			TextureUsageBit::SAMPLED_FRAGMENT,
 			TextureSurfaceInfo(0, 0, 0, 0));
 			TextureSurfaceInfo(0, 0, 0, 0));
-		cmdb->bindTexture(0, 0, rt, TextureUsageBit::SAMPLED_FRAGMENT);
+		cmdb->bindTextureAndSampler(0, 0, rt, sampler, TextureUsageBit::SAMPLED_FRAGMENT);
 		cmdb->beginRenderPass(defaultFb, {}, {});
 		cmdb->beginRenderPass(defaultFb, {}, {});
 		cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 6);
 		cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 6);
 		cmdb->endRenderPass();
 		cmdb->endRenderPass();
@@ -876,8 +879,6 @@ ANKI_TEST(Gr, Texture)
 	init.m_depth = 1;
 	init.m_depth = 1;
 	init.m_layerCount = 1;
 	init.m_layerCount = 1;
 	init.m_samples = 1;
 	init.m_samples = 1;
-	init.m_sampling.m_minMagFilter = SamplingFilter::LINEAR;
-	init.m_sampling.m_mipmapFilter = SamplingFilter::LINEAR;
 	init.m_type = TextureType::_2D;
 	init.m_type = TextureType::_2D;
 
 
 	TexturePtr b = gr->newTexture(init);
 	TexturePtr b = gr->newTexture(init);
@@ -889,6 +890,15 @@ ANKI_TEST(Gr, DrawWithTexture)
 {
 {
 	COMMON_BEGIN()
 	COMMON_BEGIN()
 
 
+	//
+	// Create sampler
+	//
+	SamplerInitInfo samplerInit;
+	samplerInit.m_minMagFilter = SamplingFilter::NEAREST;
+	samplerInit.m_mipmapFilter = SamplingFilter::LINEAR;
+	samplerInit.m_repeat = false;
+	SamplerPtr sampler = gr->newSampler(samplerInit);
+
 	//
 	//
 	// Create texture A
 	// Create texture A
 	//
 	//
@@ -903,9 +913,6 @@ ANKI_TEST(Gr, DrawWithTexture)
 	init.m_samples = 1;
 	init.m_samples = 1;
 	init.m_depth = 1;
 	init.m_depth = 1;
 	init.m_layerCount = 1;
 	init.m_layerCount = 1;
-	init.m_sampling.m_repeat = false;
-	init.m_sampling.m_minMagFilter = SamplingFilter::NEAREST;
-	init.m_sampling.m_mipmapFilter = SamplingFilter::LINEAR;
 	init.m_type = TextureType::_2D;
 	init.m_type = TextureType::_2D;
 
 
 	TexturePtr a = gr->newTexture(init);
 	TexturePtr a = gr->newTexture(init);
@@ -1054,8 +1061,8 @@ ANKI_TEST(Gr, DrawWithTexture)
 		cmdb->bindShaderProgram(prog);
 		cmdb->bindShaderProgram(prog);
 		cmdb->beginRenderPass(fb, {}, {});
 		cmdb->beginRenderPass(fb, {}, {});
 
 
-		cmdb->bindTexture(0, 0, a, TextureUsageBit::SAMPLED_FRAGMENT);
-		cmdb->bindTexture(0, 1, b, TextureUsageBit::SAMPLED_FRAGMENT);
+		cmdb->bindTextureAndSampler(0, 0, a, sampler, TextureUsageBit::SAMPLED_FRAGMENT);
+		cmdb->bindTextureAndSampler(0, 1, b, sampler, TextureUsageBit::SAMPLED_FRAGMENT);
 		cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 6);
 		cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 6);
 		cmdb->endRenderPass();
 		cmdb->endRenderPass();
 		cmdb->flush();
 		cmdb->flush();
@@ -1122,6 +1129,11 @@ static void drawOffscreen(GrManager& gr, Bool useSecondLevel)
 	//
 	//
 	// Create textures
 	// Create textures
 	//
 	//
+	SamplerInitInfo samplerInit;
+	samplerInit.m_minMagFilter = SamplingFilter::LINEAR;
+	samplerInit.m_mipmapFilter = SamplingFilter::LINEAR;
+	SamplerPtr sampler = gr.newSampler(samplerInit);
+
 	const PixelFormat COL_FORMAT = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
 	const PixelFormat COL_FORMAT = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
 	const U TEX_SIZE = 256;
 	const U TEX_SIZE = 256;
 
 
@@ -1135,8 +1147,6 @@ static void drawOffscreen(GrManager& gr, Bool useSecondLevel)
 	init.m_depth = 1;
 	init.m_depth = 1;
 	init.m_layerCount = 1;
 	init.m_layerCount = 1;
 	init.m_samples = 1;
 	init.m_samples = 1;
-	init.m_sampling.m_minMagFilter = SamplingFilter::LINEAR;
-	init.m_sampling.m_mipmapFilter = SamplingFilter::LINEAR;
 	init.m_type = TextureType::_2D;
 	init.m_type = TextureType::_2D;
 
 
 	TexturePtr col0 = gr.newTexture(init);
 	TexturePtr col0 = gr.newTexture(init);
@@ -1243,8 +1253,8 @@ static void drawOffscreen(GrManager& gr, Bool useSecondLevel)
 		cmdb->beginRenderPass(dfb, {}, {});
 		cmdb->beginRenderPass(dfb, {}, {});
 		cmdb->bindShaderProgram(resolveProg);
 		cmdb->bindShaderProgram(resolveProg);
 		cmdb->setViewport(0, 0, WIDTH, HEIGHT);
 		cmdb->setViewport(0, 0, WIDTH, HEIGHT);
-		cmdb->bindTexture(0, 0, col0, TextureUsageBit::SAMPLED_FRAGMENT);
-		cmdb->bindTexture(0, 1, col1, TextureUsageBit::SAMPLED_FRAGMENT);
+		cmdb->bindTextureAndSampler(0, 0, col0, sampler, TextureUsageBit::SAMPLED_FRAGMENT);
+		cmdb->bindTextureAndSampler(0, 1, col1, sampler, TextureUsageBit::SAMPLED_FRAGMENT);
 		cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 6);
 		cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 6);
 		cmdb->endRenderPass();
 		cmdb->endRenderPass();
 
 
@@ -1284,13 +1294,17 @@ ANKI_TEST(Gr, ImageLoadStore)
 {
 {
 	COMMON_BEGIN()
 	COMMON_BEGIN()
 
 
+	SamplerInitInfo samplerInit;
+	samplerInit.m_minMagFilter = SamplingFilter::NEAREST;
+	samplerInit.m_mipmapFilter = SamplingFilter::BASE;
+	SamplerPtr sampler = gr->newSampler(samplerInit);
+
 	TextureInitInfo init;
 	TextureInitInfo init;
 	init.m_width = init.m_height = 4;
 	init.m_width = init.m_height = 4;
 	init.m_mipmapsCount = 2;
 	init.m_mipmapsCount = 2;
 	init.m_usage = TextureUsageBit::CLEAR | TextureUsageBit::SAMPLED_ALL | TextureUsageBit::IMAGE_COMPUTE_WRITE;
 	init.m_usage = TextureUsageBit::CLEAR | TextureUsageBit::SAMPLED_ALL | TextureUsageBit::IMAGE_COMPUTE_WRITE;
 	init.m_type = TextureType::_2D;
 	init.m_type = TextureType::_2D;
 	init.m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
 	init.m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
-	init.m_sampling.m_mipmapFilter = SamplingFilter::LINEAR;
 
 
 	TexturePtr tex = gr->newTexture(init);
 	TexturePtr tex = gr->newTexture(init);
 
 
@@ -1360,7 +1374,7 @@ ANKI_TEST(Gr, ImageLoadStore)
 
 
 		cmdb->bindShaderProgram(prog);
 		cmdb->bindShaderProgram(prog);
 		cmdb->beginRenderPass(dfb, {}, {});
 		cmdb->beginRenderPass(dfb, {}, {});
-		cmdb->bindTexture(0, 0, tex, TextureUsageBit::SAMPLED_FRAGMENT);
+		cmdb->bindTextureAndSampler(0, 0, tex, sampler, TextureUsageBit::SAMPLED_FRAGMENT);
 		cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 6);
 		cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 6);
 		cmdb->endRenderPass();
 		cmdb->endRenderPass();
 
 
@@ -1384,6 +1398,12 @@ ANKI_TEST(Gr, 3DTextures)
 {
 {
 	COMMON_BEGIN()
 	COMMON_BEGIN()
 
 
+	SamplerInitInfo samplerInit;
+	samplerInit.m_minMagFilter = SamplingFilter::NEAREST;
+	samplerInit.m_mipmapFilter = SamplingFilter::BASE;
+	samplerInit.m_repeat = false;
+	SamplerPtr sampler = gr->newSampler(samplerInit);
+
 	//
 	//
 	// Create texture A
 	// Create texture A
 	//
 	//
@@ -1398,9 +1418,6 @@ ANKI_TEST(Gr, 3DTextures)
 	init.m_samples = 1;
 	init.m_samples = 1;
 	init.m_depth = 2;
 	init.m_depth = 2;
 	init.m_layerCount = 1;
 	init.m_layerCount = 1;
-	init.m_sampling.m_repeat = false;
-	init.m_sampling.m_minMagFilter = SamplingFilter::NEAREST;
-	init.m_sampling.m_mipmapFilter = SamplingFilter::NEAREST;
 	init.m_type = TextureType::_3D;
 	init.m_type = TextureType::_3D;
 
 
 	TexturePtr a = gr->newTexture(init);
 	TexturePtr a = gr->newTexture(init);
@@ -1508,7 +1525,7 @@ ANKI_TEST(Gr, 3DTextures)
 		U idx = (F32(ITERATION_COUNT - iterations - 1) / ITERATION_COUNT) * TEX_COORDS_LOD.getSize();
 		U idx = (F32(ITERATION_COUNT - iterations - 1) / ITERATION_COUNT) * TEX_COORDS_LOD.getSize();
 		*uv = TEX_COORDS_LOD[idx];
 		*uv = TEX_COORDS_LOD[idx];
 
 
-		cmdb->bindTexture(0, 0, a, TextureUsageBit::SAMPLED_FRAGMENT);
+		cmdb->bindTextureAndSampler(0, 0, a, sampler, TextureUsageBit::SAMPLED_FRAGMENT);
 		cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 6);
 		cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 6);
 
 
 		cmdb->endRenderPass();
 		cmdb->endRenderPass();