From eea78884d35c93fe7143e344468bc1806eed48a0 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Wed, 29 Jul 2020 18:11:20 -0300 Subject: [PATCH] metal: initial barebones texture reflection in shaders --- src/modules/graphics/metal/Graphics.mm | 2 +- src/modules/graphics/metal/Shader.h | 8 +++++- src/modules/graphics/metal/Shader.mm | 40 +++++++++++++++++++++++--- 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/modules/graphics/metal/Graphics.mm b/src/modules/graphics/metal/Graphics.mm index bbb45c1d4..94c6854a3 100644 --- a/src/modules/graphics/metal/Graphics.mm +++ b/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) diff --git a/src/modules/graphics/metal/Shader.h b/src/modules/graphics/metal/Shader.h index 61126cd42..ca2e96517 100644 --- a/src/modules/graphics/metal/Shader.h +++ b/src/modules/graphics/metal/Shader.h @@ -67,7 +67,7 @@ public: } }; - Shader(love::graphics::ShaderStage *vertex, love::graphics::ShaderStage *pixel); + Shader(id 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 uniforms; + uint8 *localUniformBufferData; + size_t localUniformBufferSize; + std::map attributes; std::unordered_map cachedRenderPipelines; diff --git a/src/modules/graphics/metal/Shader.mm b/src/modules/graphics/metal/Shader.mm index 542a11bf0..2bf7ecc5d 100644 --- a/src/modules/graphics/metal/Shader.mm +++ b/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 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 library = [gfx->device newLibraryWithSource:nssource options:nil error:&err]; + id 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()