From bd856535462ee6346f912e521ca46ef2a8dbc15a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Sun, 13 Sep 2026 17:54:40 -0700 Subject: [PATCH] Added cube array samplers. (#3979) --- src/bgfx_shader.sh | 26 ++++++++++++++++++++++++++ src/renderer_d3d12.cpp | 2 +- src/renderer_gl.cpp | 5 +++-- src/renderer_mtl.cpp | 18 +++++++++++++----- src/renderer_vk.cpp | 15 +++++++++++---- src/renderer_webgpu.cpp | 15 ++++++++++++++- tools/shaderc/shaderc_metal.cpp | 1 + tools/shaderc/shaderc_spirv.cpp | 1 + tools/shaderc/shaderc_wgsl.cpp | 1 + 9 files changed, 71 insertions(+), 13 deletions(-) diff --git a/src/bgfx_shader.sh b/src/bgfx_shader.sh index 3a29dc719..a79075c90 100644 --- a/src/bgfx_shader.sh +++ b/src/bgfx_shader.sh @@ -182,6 +182,12 @@ struct BgfxSamplerCube TextureCube m_texture; }; +struct BgfxSamplerCubeArray +{ + SamplerState m_sampler; + TextureCubeArray m_texture; +}; + struct BgfxSamplerCubeShadow { SamplerComparisonState m_sampler; @@ -312,6 +318,16 @@ vec4 bgfxTextureCubeBias(BgfxSamplerCube _sampler, vec3 _coord, float _bias) return _sampler.m_texture.SampleBias(_sampler.m_sampler, _coord, _bias); } +vec4 bgfxTextureCubeArray(BgfxSamplerCubeArray _sampler, vec4 _coord) +{ + return _sampler.m_texture.Sample(_sampler.m_sampler, _coord); +} + +vec4 bgfxTextureCubeArrayLod(BgfxSamplerCubeArray _sampler, vec4 _coord, float _level) +{ + return _sampler.m_texture.SampleLevel(_sampler.m_sampler, _coord, _level); +} + vec4 bgfxTextureCubeLod(BgfxSamplerCube _sampler, vec3 _coord, float _level) { return _sampler.m_texture.SampleLevel(_sampler.m_sampler, _coord, _level); @@ -519,6 +535,14 @@ vec3 bgfxTextureSize(BgfxSampler3D _sampler, int _lod) # define textureCubeBias(_sampler, _coord, _bias) bgfxTextureCubeBias(_sampler, _coord, _bias) # define textureCubeLod(_sampler, _coord, _level) bgfxTextureCubeLod(_sampler, _coord, _level) +# define SAMPLERCUBEARRAY(_name, _reg) \ + uniform SamplerState _name ## Sampler : REGISTER(s, _reg); \ + uniform TextureCubeArray _name ## Texture : REGISTER(t, _reg); \ + static BgfxSamplerCubeArray _name = { _name ## Sampler, _name ## Texture } +# define samplerCubeArray BgfxSamplerCubeArray +# define textureCubeArray(_sampler, _coord) bgfxTextureCubeArray(_sampler, _coord) +# define textureCubeArrayLod(_sampler, _coord, _level) bgfxTextureCubeArrayLod(_sampler, _coord, _level) + # define SAMPLERCUBESHADOW(_name, _reg) \ uniform SamplerComparisonState _name ## SamplerComparison : REGISTER(s, _reg); \ uniform TextureCube _name ## Texture : REGISTER(t, _reg); \ @@ -650,6 +674,7 @@ vec4 mod(vec4 _a, vec4 _b) { return _a - _b * floor(_a / _b); } # define texture2DArray(_sampler, _coord) texture(_sampler, _coord) # define texture3D(_sampler, _coord) texture(_sampler, _coord) # define textureCube(_sampler, _coord) texture(_sampler, _coord) +# define textureCubeArray(_sampler, _coord) texture(_sampler, _coord) # define texture2DLod(_sampler, _coord, _lod) textureLod(_sampler, _coord, _lod) # define texture2DLodOffset(_sampler, _coord, _lod, _offset) textureLodOffset(_sampler, _coord, _lod, _offset) # define texture2DArrayLod(_sampler, _coord, _lod) textureLod(_sampler, _coord, _lod) @@ -657,6 +682,7 @@ vec4 mod(vec4 _a, vec4 _b) { return _a - _b * floor(_a / _b); } # define texture3DLod(_sampler, _coord, _lod) textureLod(_sampler, _coord, _lod) # define texture3DLodOffset(_sampler, _coord, _lod, _offset) textureLodOffset(_sampler, _coord, _lod, _offset) # define textureCubeLod(_sampler, _coord, _lod) textureLod(_sampler, _coord, _lod) +# define textureCubeArrayLod(_sampler, _coord, _lod) textureLod(_sampler, _coord, _lod) # define texture2DGrad(_sampler, _coord, _dPdx, _dPdy) textureGrad(_sampler, _coord, _dPdx, _dPdy) # define texture3DGrad(_sampler, _coord, _dPdx, _dPdy) textureGrad(_sampler, _coord, _dPdx, _dPdy) # define textureCubeGrad(_sampler, _coord, _dPdx, _dPdy) textureGrad(_sampler, _coord, _dPdx, _dPdy) diff --git a/src/renderer_d3d12.cpp b/src/renderer_d3d12.cpp index f32f16062..b02a038e2 100644 --- a/src/renderer_d3d12.cpp +++ b/src/renderer_d3d12.cpp @@ -4787,7 +4787,7 @@ namespace bgfx { namespace d3d12 case D3D12_SRV_DIMENSION_TEXTURECUBEARRAY: srvd->TextureCubeArray.MostDetailedMip = _firstMip; srvd->TextureCubeArray.MipLevels = numMips; - srvd->TextureCubeArray.First2DArrayFace = _firstLayer; + srvd->TextureCubeArray.First2DArrayFace = _firstLayer * 6; srvd->TextureCubeArray.NumCubes = numLayers; srvd->TextureCubeArray.ResourceMinLODClamp = 0; break; diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index 21a7ce016..4de67c98f 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -6754,11 +6754,12 @@ namespace bgfx { namespace gl GLuint TextureGL::getViewId(uint8_t _firstMip, uint8_t _numMips, uint16_t _firstLayer, uint16_t _numLayers, GLenum* _target, bool _layered) { const uint16_t facesPerLayer = isCubeMap() ? 6 : 1; + const uint32_t rangeScale = isCubeMap() && !_layered ? 6 : 1; const uint8_t firstMip = bx::min(_firstMip, uint8_t(m_numMips - 1) ); const uint8_t numMips = bx::min(_numMips, uint8_t(m_numMips - firstMip) ); const uint16_t numLayers0 = uint16_t(bx::max(m_numLayers, 1) * facesPerLayer); - const uint16_t firstLayer = bx::min(_firstLayer, uint16_t(numLayers0 - 1) ); - const uint16_t numLayers = bx::min(_numLayers, uint16_t(numLayers0 - firstLayer) ); + const uint16_t firstLayer = uint16_t(bx::min(uint32_t(_firstLayer) * rangeScale, numLayers0 - 1) ); + const uint16_t numLayers = uint16_t(bx::min(uint32_t(_numLayers) * rangeScale, numLayers0 - firstLayer) ); const bool fullRange = 0 == firstMip && numMips >= m_numMips diff --git a/src/renderer_mtl.cpp b/src/renderer_mtl.cpp index f758e733b..ee2d06650 100644 --- a/src/renderer_mtl.cpp +++ b/src/renderer_mtl.cpp @@ -4705,12 +4705,17 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames } } - const uint32_t totalLayers = uint32_t(ptr->arrayLength() * (TextureCube == m_type ? 6 : 1) ); + const bool isCube = TextureCube == m_type; + const uint32_t rangeScale = isCube ? 6 : 1; + const uint32_t totalUnits = uint32_t(ptr->arrayLength() ); + const uint32_t totalLayers = totalUnits * rangeScale; const uint8_t firstMip = bx::min(_firstMip, uint8_t(m_numMips - 1) ); const uint8_t numMips = bx::min(_numMips, uint8_t(m_numMips - firstMip) ); - const uint32_t firstLayer = bx::min(_firstLayer, totalLayers - 1); - const uint32_t numLayers = bx::min(_numLayers, totalLayers - firstLayer); + const uint32_t firstUnit = bx::min(_firstLayer, totalUnits - 1); + const uint32_t numUnits = bx::min(_numLayers, totalUnits - firstUnit); + const uint32_t firstLayer = firstUnit * rangeScale; + const uint32_t numLayers = numUnits * rangeScale; const bool fullRange = 0 == firstMip && 0 == firstLayer @@ -4747,9 +4752,12 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames MTL::TextureType type = ptr->textureType(); - if (TextureCube == m_type) + if (isCube) { - type = (MTL::TextureType)MTL::TextureType2DArray; + type = 1 == numUnits + ? (MTL::TextureType)MTL::TextureTypeCube + : (MTL::TextureType)MTL::TextureTypeCubeArray + ; } else if (MTL::TextureType2DArray == type && 1 == numLayers) diff --git a/src/renderer_vk.cpp b/src/renderer_vk.cpp index 89c588637..a5f2d9950 100644 --- a/src/renderer_vk.cpp +++ b/src/renderer_vk.cpp @@ -4068,8 +4068,12 @@ VK_IMPORT_DEVICE _stencil = _stencil && !!(texture.m_aspectFlags & VK_IMAGE_ASPECT_STENCIL_BIT); - const uint32_t firstLayer = bx::min(_firstLayer, texture.m_numSides); - const uint32_t numLayers = bx::min(_numLayers, texture.m_numSides - firstLayer); + const uint32_t units = (VK_IMAGE_VIEW_TYPE_CUBE == _type || VK_IMAGE_VIEW_TYPE_CUBE_ARRAY == _type) + ? bx::max(1, texture.m_numSides / 6) + : texture.m_numSides + ; + const uint32_t firstLayer = bx::min(_firstLayer, units); + const uint32_t numLayers = bx::min(_numLayers, units - firstLayer); const uint32_t firstMip = bx::min(_mip, texture.m_numMips); const uint32_t numMips = bx::min(_numMips, texture.m_numMips - firstMip); @@ -8018,10 +8022,13 @@ VK_DESTROY ? VkComponentMapping{ VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY } : m_components ; + const bool cubeView = VK_IMAGE_VIEW_TYPE_CUBE == _type + || VK_IMAGE_VIEW_TYPE_CUBE_ARRAY == _type + ; viewInfo.subresourceRange.aspectMask = m_aspectFlags & _aspectMask; viewInfo.subresourceRange.baseMipLevel = _mip; viewInfo.subresourceRange.levelCount = _numMips; - viewInfo.subresourceRange.baseArrayLayer = _layer; + viewInfo.subresourceRange.baseArrayLayer = cubeView ? _layer * 6 : _layer; viewInfo.subresourceRange.layerCount = 1; if (VK_IMAGE_VIEW_TYPE_2D != _type @@ -8029,7 +8036,7 @@ VK_DESTROY { viewInfo.subresourceRange.layerCount = VK_IMAGE_VIEW_TYPE_CUBE == _type ? 6 - : _numLayers + : cubeView ? _numLayers * 6 : _numLayers ; } diff --git a/src/renderer_webgpu.cpp b/src/renderer_webgpu.cpp index 4bb23f4d4..9643b3ca7 100644 --- a/src/renderer_webgpu.cpp +++ b/src/renderer_webgpu.cpp @@ -5135,6 +5135,19 @@ WGPU_IMPORT arrayLayerCount = 1; } + uint32_t baseArrayLayer = _baseArrayLayer; + + if (WGPUTextureViewDimension_Cube == tvd + || WGPUTextureViewDimension_CubeArray == tvd) + { + baseArrayLayer *= 6; + + if (WGPU_ARRAY_LAYER_COUNT_UNDEFINED != arrayLayerCount) + { + arrayLayerCount *= 6; + } + } + WGPUTextureViewDescriptor textureViewDesc = { .nextInChain = NULL, @@ -5143,7 +5156,7 @@ WGPU_IMPORT .dimension = tvd, .baseMipLevel = _baseMipLevel, .mipLevelCount = UINT8_MAX == _mipLevelCount ? WGPU_MIP_LEVEL_COUNT_UNDEFINED : _mipLevelCount, - .baseArrayLayer = _baseArrayLayer, + .baseArrayLayer = baseArrayLayer, .arrayLayerCount = arrayLayerCount, .aspect = _stencil ? WGPUTextureAspect_StencilOnly diff --git a/tools/shaderc/shaderc_metal.cpp b/tools/shaderc/shaderc_metal.cpp index 632a95d42..edc75025b 100644 --- a/tools/shaderc/shaderc_metal.cpp +++ b/tools/shaderc/shaderc_metal.cpp @@ -235,6 +235,7 @@ namespace bgfx { namespace metal "BgfxISampler3D", "BgfxUSampler3D", "BgfxSamplerCube", + "BgfxSamplerCubeArray", "BgfxSamplerCubeShadow", "BgfxSampler2DMS", }; diff --git a/tools/shaderc/shaderc_spirv.cpp b/tools/shaderc/shaderc_spirv.cpp index 1049416a2..7bbfb574b 100644 --- a/tools/shaderc/shaderc_spirv.cpp +++ b/tools/shaderc/shaderc_spirv.cpp @@ -338,6 +338,7 @@ namespace bgfx { namespace spirv "BgfxISampler3D", "BgfxUSampler3D", "BgfxSamplerCube", + "BgfxSamplerCubeArray", "BgfxSamplerCubeShadow", "BgfxSampler2DMS", }; diff --git a/tools/shaderc/shaderc_wgsl.cpp b/tools/shaderc/shaderc_wgsl.cpp index 5fe9cb166..80e065a9d 100644 --- a/tools/shaderc/shaderc_wgsl.cpp +++ b/tools/shaderc/shaderc_wgsl.cpp @@ -328,6 +328,7 @@ namespace bgfx { namespace wgsl "BgfxISampler3D", "BgfxUSampler3D", "BgfxSamplerCube", + "BgfxSamplerCubeArray", "BgfxSamplerCubeShadow", "BgfxSampler2DMS", };