Browse Source

metal: fix texture sampler changes not affecting draws using shaders.

Alex Szpakowski 3 years ago
parent
commit
6e49b1f901

+ 13 - 10
src/modules/graphics/metal/Graphics.mm

@@ -210,13 +210,14 @@ static inline void setTexture(id<MTLComputeCommandEncoder> encoder, Graphics::Re
 	}
 }
 
-static inline void setSampler(id<MTLRenderCommandEncoder> encoder, Graphics::RenderEncoderBindings &bindings, ShaderStageType stage, int index, id<MTLSamplerState> sampler)
+static inline void setSampler(id<MTLRenderCommandEncoder> encoder, Graphics::RenderEncoderBindings &bindings, ShaderStageType stage, int index, love::graphics::Texture *samplertex)
 {
-	void *s = (__bridge void *)sampler;
+	void *s = samplertex != nullptr ? (void *)samplertex->getSamplerHandle() : nullptr;
 	auto &binding = bindings.samplers[index][stage];
 	if (binding != s)
 	{
 		binding = s;
+		id<MTLSamplerState> sampler = (__bridge id<MTLSamplerState>) s;
 		if (stage == SHADERSTAGE_VERTEX)
 			[encoder setVertexSamplerState:sampler atIndex:index];
 		else if (stage == SHADERSTAGE_PIXEL)
@@ -224,13 +225,14 @@ static inline void setSampler(id<MTLRenderCommandEncoder> encoder, Graphics::Ren
 	}
 }
 
-static inline void setSampler(id<MTLComputeCommandEncoder> encoder, Graphics::RenderEncoderBindings &bindings, int index, id<MTLSamplerState> sampler)
+static inline void setSampler(id<MTLComputeCommandEncoder> encoder, Graphics::RenderEncoderBindings &bindings, int index, love::graphics::Texture *samplertex)
 {
-	void *s = (__bridge void *)sampler;
+	void *s = samplertex != nullptr ? (void *)samplertex->getSamplerHandle() : nullptr;
 	auto &binding = bindings.samplers[index][SHADERSTAGE_COMPUTE];
 	if (binding != s)
 	{
 		binding = s;
+		id<MTLSamplerState> sampler = (__bridge id<MTLSamplerState>) s;
 		[encoder setSamplerState:sampler atIndex:index];
 	}
 }
@@ -777,6 +779,7 @@ id<MTLSamplerState> Graphics::getCachedSampler(const SamplerState &s)
 	desc.lodMinClamp = s.minLod;
 	desc.lodMaxClamp = s.maxLod;
 
+	// TODO: This isn't supported on some older iOS devices...
 	if (s.depthSampleMode.hasValue)
 		desc.compareFunction = getMTLCompareFunction(s.depthSampleMode.value);
 
@@ -984,7 +987,7 @@ void Graphics::applyShaderUniforms(id<MTLComputeCommandEncoder> encoder, love::g
 	for (const Shader::TextureBinding &b : s->getTextureBindings())
 	{
 		id<MTLTexture> texture = b.texture;
-		id<MTLSamplerState> sampler = b.sampler;
+		auto samplertex = b.samplerTexture;
 
 		uint8 texindex = b.textureStages[SHADERSTAGE_COMPUTE];
 		uint8 sampindex = b.samplerStages[SHADERSTAGE_COMPUTE];
@@ -992,7 +995,7 @@ void Graphics::applyShaderUniforms(id<MTLComputeCommandEncoder> encoder, love::g
 		if (texindex != LOVE_UINT8_MAX)
 			setTexture(encoder, bindings, texindex, texture);
 		if (sampindex != LOVE_UINT8_MAX)
-			setSampler(encoder, bindings, sampindex, sampler);
+			setSampler(encoder, bindings, sampindex, samplertex);
 	}
 
 	for (const Shader::BufferBinding &b : s->getBufferBindings())
@@ -1078,7 +1081,7 @@ void Graphics::applyShaderUniforms(id<MTLRenderCommandEncoder> renderEncoder, lo
 	for (const Shader::TextureBinding &b : s->getTextureBindings())
 	{
 		id<MTLTexture> texture = b.texture;
-		id<MTLSamplerState> sampler = b.sampler;
+		auto samplertex = b.samplerTexture;
 
 		if (b.isMainTexture)
 		{
@@ -1090,7 +1093,7 @@ void Graphics::applyShaderUniforms(id<MTLRenderCommandEncoder> renderEncoder, lo
 			}
 
 			texture = getMTLTexture(maintex);
-			sampler = getMTLSampler(maintex);
+			samplertex = maintex;
 		}
 
 		uint8 texindex = b.textureStages[SHADERSTAGE_VERTEX];
@@ -1099,7 +1102,7 @@ void Graphics::applyShaderUniforms(id<MTLRenderCommandEncoder> renderEncoder, lo
 		if (texindex != LOVE_UINT8_MAX)
 			setTexture(renderEncoder, bindings, SHADERSTAGE_VERTEX, texindex, texture);
 		if (sampindex != LOVE_UINT8_MAX)
-			setSampler(renderEncoder, bindings, SHADERSTAGE_VERTEX, sampindex, sampler);
+			setSampler(renderEncoder, bindings, SHADERSTAGE_VERTEX, sampindex, samplertex);
 
 		texindex = b.textureStages[SHADERSTAGE_PIXEL];
 		sampindex = b.samplerStages[SHADERSTAGE_PIXEL];
@@ -1107,7 +1110,7 @@ void Graphics::applyShaderUniforms(id<MTLRenderCommandEncoder> renderEncoder, lo
 		if (texindex != LOVE_UINT8_MAX)
 			setTexture(renderEncoder, bindings, SHADERSTAGE_PIXEL, texindex, texture);
 		if (sampindex != LOVE_UINT8_MAX)
-			setSampler(renderEncoder, bindings, SHADERSTAGE_PIXEL, sampindex, sampler);
+			setSampler(renderEncoder, bindings, SHADERSTAGE_PIXEL, sampindex, samplertex);
 	}
 
 	for (const Shader::BufferBinding &b : s->getBufferBindings())

+ 3 - 1
src/modules/graphics/metal/Shader.h

@@ -81,7 +81,9 @@ public:
 	struct TextureBinding
 	{
 		id<MTLTexture> texture;
-		id<MTLSamplerState> sampler;
+
+		// Indirect sampler ref in case Texture's sampler state changes.
+		Texture *samplerTexture;
 
 		bool isMainTexture;
 

+ 2 - 3
src/modules/graphics/metal/Shader.mm

@@ -768,7 +768,7 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
 						else
 						{
 							b.texture = getMTLTexture(u.textures[i]);
-							b.sampler = getMTLSampler(u.textures[i]);
+							b.samplerTexture = u.textures[i];
 
 							BuiltinUniform builtin = BUILTIN_MAX_ENUM;
 							if (getConstant(u.name.c_str(), builtin) && builtin == BUILTIN_TEXTURE_MAIN)
@@ -969,9 +969,8 @@ void Shader::sendTextures(const UniformInfo *info, love::graphics::Texture **tex
 
 		info->textures[i] = tex;
 
-		// TODO: handle changing a sampler after Shader:send(texture)...
 		textureBindings[info->ints[i]].texture = getMTLTexture(tex);
-		textureBindings[info->ints[i]].sampler = getMTLSampler(tex);
+		textureBindings[info->ints[i]].samplerTexture = tex;
 	}
 }}