From 21a5cf8fc00888103f97c9ea87ed8a8b4040fb2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Tue, 20 Oct 2026 22:26:20 -0700 Subject: [PATCH] Metal: Fixed sampling textures through a sampler of another type, such as a 2D texture as a 2D array. (#4076) --- src/renderer_mtl.cpp | 95 ++++++++++++++++++++++++-------------------- src/renderer_mtl.h | 10 +++-- 2 files changed, 60 insertions(+), 45 deletions(-) diff --git a/src/renderer_mtl.cpp b/src/renderer_mtl.cpp index b8c94bc12..3e34f5f2d 100644 --- a/src/renderer_mtl.cpp +++ b/src/renderer_mtl.cpp @@ -3052,11 +3052,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames : PipelineStateMtl::BindToVertexShader ; - if (MTL::TextureType2DMultisample == arg->textureType() - || MTL::TextureType2DMultisampleArray == arg->textureType() ) - { - ps->m_bindingTypes[arg->index()] |= PipelineStateMtl::BindMultisample; - } + ps->m_textureTypes[arg->index()] = uint8_t(arg->textureType() ); const UniformRegInfo* info = s_renderMtl->m_uniformReg.find(name); @@ -4815,7 +4811,23 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames ; } - void TextureMtl::commit(uint8_t _stage, bool _vertex, bool _fragment, uint32_t _flags, uint8_t _mip, uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips, uint8_t _lodMin, uint8_t _lodMax, bool _multisample) + MTL::Texture* TextureMtl::getSampledView(uint8_t _textureType, uint32_t _flags, uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips, bool _stencil) + { + if (MTL::TextureType2DMultisample == _textureType + || MTL::TextureType2DMultisampleArray == _textureType) + { + MTL::Texture* ptr = getMultisampleView(_flags); + + if (NULL != ptr) + { + return ptr; + } + } + + return getTextureView(_firstLayer, _numLayers, _firstMip, _numMips, _stencil, useAltFormat(_flags, BGFX_SAMPLER_SRGB), _textureType); + } + + void TextureMtl::commit(uint8_t _stage, bool _vertex, bool _fragment, uint32_t _flags, uint8_t _mip, uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips, uint8_t _lodMin, uint8_t _lodMax, uint8_t _textureType) { if (!_vertex && !_fragment) @@ -4829,19 +4841,11 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames ; const bool sampleStencil = 0 != (flags & BGFX_SAMPLER_SAMPLE_STENCIL); - MTL::Texture* ptr = _multisample && _mip == UINT8_MAX - ? getMultisampleView(flags) - : NULL + MTL::Texture* ptr = _mip != UINT8_MAX + ? getTextureImage(_mip, _firstLayer, _numLayers) + : getSampledView(_textureType, flags, _firstLayer, _numLayers, _firstMip, _numMips, sampleStencil) ; - if (NULL == ptr) - { - ptr = _mip != UINT8_MAX - ? getTextureImage(_mip, _firstLayer, _numLayers) - : getTextureView(_firstLayer, _numLayers, _firstMip, _numMips, sampleStencil, useAltFormat(flags, BGFX_SAMPLER_SRGB) ) - ; - } - if (_vertex) { s_renderMtl->m_renderCommandEncoder->setVertexTexture(ptr, _stage); @@ -4884,7 +4888,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames ; } - MTL::Texture* TextureMtl::getTextureView(uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips, bool _stencil, bool _alt) + MTL::Texture* TextureMtl::getTextureView(uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips, bool _stencil, bool _alt, uint8_t _textureType) { MTL::Texture* ptr = _stencil && NULL != m_ptrStencil ? m_ptrStencil @@ -4931,10 +4935,37 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames const uint32_t firstLayer = firstUnit * rangeScale; const uint32_t numLayers = numUnits * rangeScale; + MTL::TextureType type = ptr->textureType(); + + if (isCube) + { + type = 1 == numUnits + ? (MTL::TextureType)MTL::TextureTypeCube + : (MTL::TextureType)MTL::TextureTypeCubeArray + ; + } + else if (MTL::TextureType2DArray == type + && 1 == numLayers) + { + type = (MTL::TextureType)MTL::TextureType2D; + } + + const bool arrayOf2D = MTL::TextureType2D == type || MTL::TextureType2DArray == type; + const bool arrayOfCube = MTL::TextureTypeCube == type || MTL::TextureTypeCubeArray == type; + const bool wants2D = MTL::TextureType2D == _textureType || MTL::TextureType2DArray == _textureType; + const bool wantsCube = MTL::TextureTypeCube == _textureType || MTL::TextureTypeCubeArray == _textureType; + + if ( (arrayOf2D && wants2D && (MTL::TextureType2DArray == _textureType || 1 == numLayers) ) + || (arrayOfCube && wantsCube && (MTL::TextureTypeCubeArray == _textureType || 1 == numUnits ) ) ) + { + type = MTL::TextureType(_textureType); + } + const bool fullRange = 0 == firstMip && 0 == firstLayer && numMips >= m_numMips && numLayers >= totalLayers + && type == ptr->textureType() ; if (fullRange @@ -4954,6 +4985,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames | (uint64_t(numMips) << 8) | (uint64_t(firstLayer) << 16) | (uint64_t(numLayers) << 32) + | (uint64_t(type) << 48) | (uint64_t(alt) << 62) | (uint64_t(_stencil) << 63) ; @@ -4964,21 +4996,6 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames return it->second; } - MTL::TextureType type = ptr->textureType(); - - if (isCube) - { - type = 1 == numUnits - ? (MTL::TextureType)MTL::TextureTypeCube - : (MTL::TextureType)MTL::TextureTypeCubeArray - ; - } - else if (MTL::TextureType2DArray == type - && 1 == numLayers) - { - type = (MTL::TextureType)MTL::TextureType2D; - } - MTL::Texture* view = ptr->newTextureView( format , type @@ -6820,14 +6837,8 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames : uint32_t(texture.m_flags) ; - MTL::Texture* ptr = 0 != (currentPso->m_bindingTypes[stage] & PipelineStateMtl::BindMultisample) - ? texture.getMultisampleView(resolvedFlags) - : NULL - ; - - m_computeCommandEncoder->setTexture(NULL != ptr - ? ptr - : texture.getTextureView(bind.m_firstLayer, bind.m_numLayers, bind.m_firstMip, bind.m_numMips, 0 != (resolvedFlags & BGFX_SAMPLER_SAMPLE_STENCIL) ) + m_computeCommandEncoder->setTexture( + texture.getSampledView(currentPso->m_textureTypes[stage], resolvedFlags, bind.m_firstLayer, bind.m_numLayers, bind.m_firstMip, bind.m_numMips, 0 != (resolvedFlags & BGFX_SAMPLER_SAMPLE_STENCIL) ) , stage ); m_computeCommandEncoder->setSamplerState( @@ -7271,7 +7282,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames , bind.m_numMips , bind.m_lod.min , bind.m_lod.max - , 0 != (bindingTypes[stage] & PipelineStateMtl::BindMultisample) + , currentPso->m_textureTypes[stage] ); } break; diff --git a/src/renderer_mtl.h b/src/renderer_mtl.h index 7c6190e58..670fa5d38 100644 --- a/src/renderer_mtl.h +++ b/src/renderer_mtl.h @@ -397,6 +397,7 @@ namespace bgfx { namespace mtl for (uint32_t ii = 0; ii < BGFX_CONFIG_MAX_TEXTURE_SAMPLERS; ++ii) { m_bindingTypes[ii] = 0; + m_textureTypes[ii] = kTextureTypeAny; } } @@ -430,10 +431,12 @@ namespace bgfx { namespace mtl { BindToVertexShader = 1 << 0, BindToFragmentShader = 1 << 1, - BindMultisample = 1 << 2, }; uint8_t m_bindingTypes[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS]; + static constexpr uint8_t kTextureTypeAny = UINT8_MAX; + uint8_t m_textureTypes[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS]; + uint16_t m_numThreads[3]; PredefinedUniform m_predefined[PredefinedUniform::Count*2]; @@ -512,13 +515,14 @@ namespace bgfx { namespace mtl , uint8_t _numMips = UINT8_MAX , uint8_t _lodMin = 0 , uint8_t _lodMax = UINT8_MAX - , bool _multisample = false + , uint8_t _textureType = UINT8_MAX ); MTL::Texture* getMultisampleView(uint32_t _flags) const; + MTL::Texture* getSampledView(uint8_t _textureType, uint32_t _flags, uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips, bool _stencil); MTL::Texture* getTextureImage(uint8_t _mip, uint16_t _firstLayer = 0, uint16_t _numLayers = UINT16_MAX); - MTL::Texture* getTextureView(uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips, bool _stencil = false, bool _alt = false); + MTL::Texture* getTextureView(uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips, bool _stencil = false, bool _alt = false, uint8_t _textureType = UINT8_MAX); bool useAltFormat(uint32_t _flags, uint32_t _bit) const; MTL::PixelFormat getAttachmentPixelFormat(uint8_t _flags) const;