Browse Source

metal: initial barebones texture reflection in shaders

Alex Szpakowski 5 years ago
parent
commit
eea78884d3

+ 1 - 1
src/modules/graphics/metal/Graphics.mm

@@ -231,7 +231,7 @@ love::graphics::ShaderStage *Graphics::newShaderStageInternal(ShaderStage::Stage
 
 love::graphics::Shader *Graphics::newShaderInternal(love::graphics::ShaderStage *vertex, love::graphics::ShaderStage *pixel)
 {
-	return new Shader(vertex, pixel);
+	return new Shader(device, vertex, pixel);
 }
 
 love::graphics::Buffer *Graphics::newBuffer(size_t size, const void *data, BufferType type, vertex::Usage usage, uint32 mapflags)

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

@@ -67,7 +67,7 @@ public:
 		}
 	};
 
-	Shader(love::graphics::ShaderStage *vertex, love::graphics::ShaderStage *pixel);
+	Shader(id<MTLDevice> device, love::graphics::ShaderStage *vertex, love::graphics::ShaderStage *pixel);
 	virtual ~Shader();
 
 	// Implements Shader.
@@ -86,6 +86,9 @@ public:
 
 	static int getUniformBufferBinding();
 
+	uint8 *getLocalUniformBufferData() { return localUniformBufferData; }
+	size_t getLocalUniformBufferSize() const { return localUniformBufferSize; }
+
 private:
 
 	struct RenderPipelineHasher
@@ -101,6 +104,9 @@ private:
 	UniformInfo *builtinUniformInfo[BUILTIN_MAX_ENUM];
 	std::map<std::string, UniformInfo> uniforms;
 
+	uint8 *localUniformBufferData;
+	size_t localUniformBufferSize;
+
 	std::map<std::string, int> attributes;
 
 	std::unordered_map<RenderPipelineKey, const void *, RenderPipelineHasher> cachedRenderPipelines;

+ 36 - 4
src/modules/graphics/metal/Shader.mm

@@ -121,13 +121,13 @@ static EShLanguage getGLSLangStage(ShaderStage::StageType stage)
 	return EShLangCount;
 }
 
-Shader::Shader(love::graphics::ShaderStage *vertex, love::graphics::ShaderStage *pixel)
+Shader::Shader(id<MTLDevice> device, love::graphics::ShaderStage *vertex, love::graphics::ShaderStage *pixel)
 	: love::graphics::Shader(vertex, pixel)
 	, functions()
 	, builtinUniformInfo()
+	, localUniformBufferData(nullptr)
+	, localUniformBufferSize(0)
 { @autoreleasepool {
-	auto gfx = Graphics::getInstance();
-
 	using namespace glslang;
 	using namespace spirv_cross;
 
@@ -186,11 +186,34 @@ Shader::Shader(love::graphics::ShaderStage *vertex, love::graphics::ShaderStage
 
 			for (const auto &resource : resources.sampled_images)
 			{
+				int binding = msl.get_decoration(resource.id, spv::DecorationBinding);
+
 				BuiltinUniform builtin = BUILTIN_MAX_ENUM;
 				if (getConstant(resource.name.c_str(), builtin))
 				{
 					// TODO
 				}
+
+				auto it = uniforms.find(resource.name);
+				if (it != uniforms.end())
+				{
+					if (it->second.ints[0] != binding)
+						throw love::Exception("texture binding mismatch for %s: %d vs %d", resource.name.c_str(), it->second.ints[0], binding);
+				}
+				else
+				{
+					UniformInfo u = {};
+					u.baseType = UNIFORM_SAMPLER;
+					u.name = resource.name;
+					u.location = 0;
+					u.textures = new love::graphics::Texture*[1];
+					u.textures[0] = nullptr;
+					u.data = malloc(sizeof(int) * 1);
+					u.ints[0] = binding;
+//					printf("binding for %s: %d\n", u.name.c_str(), binding);
+
+					uniforms[u.name] = u;
+				}
 			}
 
 			for (const auto &resource : resources.uniform_buffers)
@@ -240,7 +263,7 @@ Shader::Shader(love::graphics::ShaderStage *vertex, love::graphics::ShaderStage
 														encoding:NSUTF8StringEncoding];
 
 			NSError *err = nil;
-			id<MTLLibrary> library = [gfx->device newLibraryWithSource:nssource options:nil error:&err];
+			id<MTLLibrary> library = [device newLibraryWithSource:nssource options:nil error:&err];
 			if (library == nil && err != nil)
 			{
 				NSLog(@"errors: %@", err);
@@ -274,6 +297,15 @@ Shader::~Shader()
 		CFBridgingRelease(kvp.second);
 
 	cachedRenderPipelines.clear();
+
+	for (const auto &it : uniforms)
+	{
+		free(it.second.data);
+		if (it.second.textures != nullptr)
+			delete[] it.second.textures;
+	}
+
+	delete[] localUniformBufferData;
 }}
 
 void Shader::attach()