From 0d1856c8baf6932dfea82a570cfcc20466569e3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Wed, 28 Oct 2026 22:54:10 -0700 Subject: [PATCH] Metal: Resolve user uniforms when the shader is created. (#4105) Co-authored-by: Branimir Karadzic --- src/renderer_mtl.cpp | 60 +++++++++++++++++++++++++++++++++++++------- src/renderer_mtl.h | 5 ++++ 2 files changed, 56 insertions(+), 9 deletions(-) diff --git a/src/renderer_mtl.cpp b/src/renderer_mtl.cpp index 36a15ee35..5b168c27e 100644 --- a/src/renderer_mtl.cpp +++ b/src/renderer_mtl.cpp @@ -2892,6 +2892,8 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames void processArguments( PipelineStateMtl* ps + , const ShaderMtl* _vsh + , const ShaderMtl* _fsh , NS::Array* _vertexArgs , NS::Array* _fragmentArgs ) @@ -2905,6 +2907,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames : ps->m_fshConstantBuffer ; const int8_t fragmentBit = (1 == shaderType ? kUniformFragmentBit : 0); + const ShaderMtl* shader = shaderType == 0 ? _vsh : _fsh; NS::Array* args = shaderType == 0 ? _vertexArgs : _fragmentArgs; if (NULL == args) @@ -2993,10 +2996,26 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames } else { - const UniformRegInfo* info = s_renderMtl->m_uniformReg.find(name); - BX_WARN(NULL != info, "User defined uniform '%s' is not found, it won't be set.", name); + UniformHandle handle = BGFX_INVALID_HANDLE; - if (NULL != info) + if (NULL != shader) + { + handle = shader->findUniform(name); + } + + if (!isValid(handle) ) + { + const UniformRegInfo* info = s_renderMtl->m_uniformReg.find(name); + + if (NULL != info) + { + handle = info->m_handle; + } + } + + BX_WARN(isValid(handle), "User defined uniform '%s' is not found, it won't be set.", name); + + if (isValid(handle) ) { if (NULL == constantBuffer) { @@ -3004,8 +3023,8 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames } UniformType::Enum type = convertMtlType(dataType); - constantBuffer->writeUniformHandle(type|fragmentBit, uint32_t(uniform->offset() ), info->m_handle, uint16_t(num) ); - BX_TRACE("store %s %d offset:%d", name, info->m_handle, uint32_t(uniform->offset() ) ); + constantBuffer->writeUniformHandle(type|fragmentBit, uint32_t(uniform->offset() ), handle, uint16_t(num) ); + BX_TRACE("store %s %d offset:%d", name, handle.idx, uint32_t(uniform->offset() ) ); } } } @@ -3477,11 +3496,11 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames { if (m_usesMTLBindings) { - processArguments(pso, reflection->vertexBindings(), reflection->fragmentBindings() ); + processArguments(pso, program.m_vsh, program.m_fsh, reflection->vertexBindings(), reflection->fragmentBindings() ); } else { - processArguments(pso, reflection->vertexArguments(), reflection->fragmentArguments() ); + processArguments(pso, program.m_vsh, program.m_fsh, reflection->vertexArguments(), reflection->fragmentArguments() ); } } } @@ -3535,11 +3554,11 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames if (m_usesMTLBindings) { - processArguments(pso, reflection->bindings(), NULL); + processArguments(pso, program.m_vsh, NULL, reflection->bindings(), NULL); } else { - processArguments(pso, reflection->arguments(), NULL); + processArguments(pso, program.m_vsh, NULL, reflection->arguments(), NULL); } for (uint32_t ii = 0; ii < 3; ++ii) @@ -3960,6 +3979,19 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames bx::write(_writer, _str, (int32_t)bx::strLen(_str), bx::ErrorAssert{}); } + UniformHandle ShaderMtl::findUniform(const char* _name) const + { + UniformHandle handle = BGFX_INVALID_HANDLE; + + UniformMap::const_iterator it = m_uniforms.find(bx::hash(_name) ); + if (m_uniforms.end() != it) + { + handle = it->second; + } + + return handle; + } + void ShaderMtl::create(const Memory* _mem) { bx::MemoryReader reader(_mem->data, _mem->size); @@ -4017,6 +4049,16 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames uint16_t regCount; bx::read(&reader, regCount, &err); + if (PredefinedUniform::Count == nameToPredefinedUniformEnum(name) ) + { + const UniformRegInfo* info = s_renderMtl->m_uniformReg.find(name); + + if (NULL != info) + { + m_uniforms[bx::hash(bx::StringView(name) )] = info->m_handle; + } + } + if (!isShaderVerLess(magic, 8) ) { uint16_t texInfo = 0; diff --git a/src/renderer_mtl.h b/src/renderer_mtl.h index b80cec650..63c61c618 100644 --- a/src/renderer_mtl.h +++ b/src/renderer_mtl.h @@ -338,6 +338,8 @@ namespace bgfx { namespace mtl MTL::Function* getFunction(uint32_t _sampleMask) const; + UniformHandle findUniform(const char* _name) const; + void destroy() { for (FunctionMap::iterator it = m_functions.begin(), itEnd = m_functions.end(); it != itEnd; ++it) @@ -347,15 +349,18 @@ namespace bgfx { namespace mtl m_functions.clear(); m_function = NULL; + m_uniforms.clear(); MTL_RELEASE_DEFERRED(m_lib); } typedef stl::unordered_map FunctionMap; + typedef stl::unordered_map UniformMap; MTL::Library* m_lib; MTL::Function* m_function; mutable FunctionMap m_functions; + UniformMap m_uniforms; uint32_t m_hash; uint16_t m_numThreads[3]; };