diff --git a/src/modules/graphics/metal/Shader.h b/src/modules/graphics/metal/Shader.h index 069c56de4..7e9196191 100644 --- a/src/modules/graphics/metal/Shader.h +++ b/src/modules/graphics/metal/Shader.h @@ -39,6 +39,12 @@ namespace glslang class TProgram; } +namespace spirv_cross +{ +class CompilerMSL; +struct SPIRType; +} + namespace love { namespace graphics @@ -128,6 +134,7 @@ private: } }; + void buildLocalUniforms(const spirv_cross::CompilerMSL &msl, const spirv_cross::SPIRType &type, size_t baseoffset, const std::string &basename); void compileFromGLSLang(id device, const glslang::TProgram &program); id functions[SHADERSTAGE_MAX_ENUM]; diff --git a/src/modules/graphics/metal/Shader.mm b/src/modules/graphics/metal/Shader.mm index 33bdc1dd5..31b8f5687 100644 --- a/src/modules/graphics/metal/Shader.mm +++ b/src/modules/graphics/metal/Shader.mm @@ -376,6 +376,84 @@ Shader::Shader(id device, StrongRef stag } }} +void Shader::buildLocalUniforms(const spirv_cross::CompilerMSL &msl, const spirv_cross::SPIRType &type, size_t baseoffset, const std::string &basename) +{ + using namespace spirv_cross; + + const auto &membertypes = type.member_types; + + for (size_t uindex = 0; uindex < membertypes.size(); uindex++) + { + const auto &membertype = msl.get_type(membertypes[uindex]); + size_t membersize = msl.get_declared_struct_member_size(type, uindex); + size_t offset = baseoffset + msl.type_struct_member_offset(type, uindex); + + std::string name = basename + msl.get_member_name(type.self, uindex); + + switch (membertype.basetype) + { + case SPIRType::Struct: + name += "."; + buildLocalUniforms(msl, membertype, offset, name); + continue; + case SPIRType::Int: + case SPIRType::UInt: + case SPIRType::Float: + break; + default: + continue; + } + + if (offset + membersize > localUniformBufferSize) + throw love::Exception("Invalid uniform offset + size for '%s' (offset=%d, size=%d, buffer size=%d)", name.c_str(), (int)offset, (int)membersize, (int)localUniformBufferSize); + + UniformInfo u = {}; + u.name = name; + u.dataSize = membersize; + u.count = membertype.array.empty() ? 1 : membertype.array[0]; + u.components = 1; + + u.data = localUniformStagingData + offset; + if (membertype.columns == 1) + { + if (membertype.basetype == SPIRType::Int) + u.baseType = UNIFORM_INT; + else if (membertype.basetype == SPIRType::UInt) + u.baseType = UNIFORM_UINT; + else + u.baseType = UNIFORM_FLOAT; + u.components = membertype.vecsize; + } + else + { + u.baseType = UNIFORM_MATRIX; + u.matrix.rows = membertype.vecsize; + u.matrix.columns = membertype.columns; + } + if (validationReflection.localUniforms.find(u.name) != validationReflection.localUniforms.end()) + { + const auto &ru = validationReflection.localUniforms.find(u.name); + const auto &values = ru->second.initializerValues; + if (!values.empty()) + { + memcpy(u.data, values.data(), std::min(u.dataSize, values.size() * sizeof(LocalUniformValue))); + } + } + + uniforms[u.name] = u; + + BuiltinUniform builtin = BUILTIN_MAX_ENUM; + if (getConstant(u.name.c_str(), builtin)) + { + if (builtin == BUILTIN_UNIFORMS_PER_DRAW) + builtinUniformDataOffset = offset; + builtinUniformInfo[builtin] = &uniforms[u.name]; + } + + updateUniform(&u, u.count); + } +} + void Shader::compileFromGLSLang(id device, const glslang::TProgram &program) { using namespace glslang; @@ -513,8 +591,6 @@ void Shader::compileFromGLSLang(id device, const glslang::TProgram &p msl.add_msl_resource_binding(binding); const SPIRType &type = msl.get_type(resource.base_type_id); - const auto &membertypes = type.member_types; - size_t size = msl.get_declared_struct_size(type); if (localUniformBufferSize != 0) @@ -531,70 +607,8 @@ void Shader::compileFromGLSLang(id device, const glslang::TProgram &p memset(localUniformStagingData, 0, size); memset(localUniformBufferData, 0, size); - for (size_t uindex = 0; uindex < membertypes.size(); uindex++) - { - const auto &membertype = msl.get_type(membertypes[uindex]); - size_t membersize = msl.get_declared_struct_member_size(type, uindex); - size_t offset = msl.type_struct_member_offset(type, uindex); - - UniformInfo u = {}; - u.name = msl.get_member_name(type.self, uindex); - u.dataSize = membersize; - u.count = membertype.array.empty() ? 1 : membertype.array[0]; - u.components = 1; - - switch (membertype.basetype) - { - case SPIRType::Int: - case SPIRType::UInt: - case SPIRType::Float: - u.data = localUniformStagingData + offset; - if (membertype.columns == 1) - { - if (membertype.basetype == SPIRType::Int) - u.baseType = UNIFORM_INT; - else if (membertype.basetype == SPIRType::UInt) - u.baseType = UNIFORM_UINT; - else - u.baseType = UNIFORM_FLOAT; - u.components = membertype.vecsize; - } - else - { - u.baseType = UNIFORM_MATRIX; - u.matrix.rows = membertype.vecsize; - u.matrix.columns = membertype.columns; - } - if (validationReflection.localUniforms.find(u.name) != validationReflection.localUniforms.end()) - { - const auto &ru = validationReflection.localUniforms.find(u.name); - const auto &values = ru->second.initializerValues; - if (!values.empty()) - { - memcpy(u.data, values.data(), std::min(u.dataSize, values.size() * sizeof(LocalUniformValue))); - } - } - updateUniform(&u, u.count); - break; - case SPIRType::Struct: - // TODO - break; - default: - break; - } - - uniforms[u.name] = u; - - BuiltinUniform builtin = BUILTIN_MAX_ENUM; - if (getConstant(u.name.c_str(), builtin)) - { - if (builtin == BUILTIN_UNIFORMS_PER_DRAW) - builtinUniformDataOffset = offset; - builtinUniformInfo[builtin] = &uniforms[u.name]; - } - - - } + std::string basename(""); + buildLocalUniforms(msl, type, 0, basename); } else { diff --git a/src/modules/graphics/metal/Texture.mm b/src/modules/graphics/metal/Texture.mm index cbc2b0043..fa6c2106b 100644 --- a/src/modules/graphics/metal/Texture.mm +++ b/src/modules/graphics/metal/Texture.mm @@ -233,7 +233,6 @@ void Texture::readbackImageData(love::image::ImageData *imagedata, int slice, in options:MTLResourceStorageModeShared]; MTLBlitOption options = MTLBlitOptionNone; - if (isPixelFormatDepthStencil(format)) options = MTLBlitOptionDepthFromDepthStencil; @@ -272,7 +271,6 @@ void Texture::copyFromBuffer(love::graphics::Buffer *source, size_t sourceoffset int z = texType == TEXTURE_VOLUME ? slice : 0; MTLBlitOption options = MTLBlitOptionNone; - if (isPixelFormatDepthStencil(format)) options = MTLBlitOptionDepthFromDepthStencil; @@ -302,7 +300,6 @@ void Texture::copyToBuffer(love::graphics::Buffer *dest, int slice, int mipmap, int z = texType == TEXTURE_VOLUME ? slice : 0; MTLBlitOption options = MTLBlitOptionNone; - if (isPixelFormatDepthStencil(format)) options = MTLBlitOptionDepthFromDepthStencil;