diff --git a/examples/28-wireframe/wireframe.cpp b/examples/28-wireframe/wireframe.cpp index a22e696c4..e78da8a83 100644 --- a/examples/28-wireframe/wireframe.cpp +++ b/examples/28-wireframe/wireframe.cpp @@ -566,7 +566,7 @@ public: ENTRY_IMPLEMENT_MAIN( ExampleWireframe - , "28-wirefame" + , "28-wireframe" , "Drawing wireframe mesh." , "https://bkaradzic.github.io/bgfx/examples.html#wireframe" ); diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index 4a9281ac4..aed5d062d 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -3390,8 +3390,11 @@ namespace bgfx { namespace d3d11 case TextureD3D11::TextureCube: desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY; - desc.Texture2DArray.ArraySize = 6; - desc.Texture2DArray.FirstArraySlice = 0; + desc.Texture2DArray.ArraySize = arrayed + ? bx::max(_numLayers, 1) + : uint16_t(bx::max(texture.m_numLayers, 1) * 6) + ; + desc.Texture2DArray.FirstArraySlice = _firstLayer; desc.Texture2DArray.MipSlice = _mip; break; @@ -3443,9 +3446,11 @@ namespace bgfx { namespace d3d11 const bool msaaSample = 1 < msaa.Count && 0 != (texture.m_flags&BGFX_TEXTURE_MSAA_SAMPLE); D3D11_SHADER_RESOURCE_VIEW_DESC desc; - desc.Format = _stencil - ? DXGI_FORMAT_X24_TYPELESS_G8_UINT - : texture.getSrvFormat() + desc.Format = !_stencil + ? texture.getSrvFormat() + : (DXGI_FORMAT_R32G8X24_TYPELESS == s_textureFormat[texture.m_textureFormat].m_fmt + ? DXGI_FORMAT_X32_TYPELESS_G8X24_UINT + : DXGI_FORMAT_X24_TYPELESS_G8_UINT) ; switch (texture.m_type) @@ -3689,7 +3694,13 @@ namespace bgfx { namespace d3d11 const Rect fbRect(0, 0, bx::narrowCast(width), bx::narrowCast(height) ); - if (_rect.isEqual(fbRect) ) + const bool discreteClear = true + && isValid(m_fbh) + && !m_frameBuffers[m_fbh.idx].m_needsQuadClear + ; + + if (_rect.isEqual(fbRect) + && discreteClear) { clear(_clear, _palette); } @@ -5335,14 +5346,19 @@ namespace bgfx { namespace d3d11 && numLayers == m_numLayers ; - if (0 != (_flags & BGFX_SAMPLER_SAMPLE_STENCIL) ) + const uint32_t flags = 0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & _flags) + ? _flags + : uint32_t(m_flags) + ; + + if (0 != (flags & BGFX_SAMPLER_SAMPLE_STENCIL) ) { ts.m_srv[_stage] = s_renderD3D11->getCachedSrv( TextureHandle{ uint16_t(this - s_renderD3D11->m_textures) } - , 0 - , 1 - , 0 - , UINT16_MAX + , _firstMip + , numMips + , _firstLayer + , numLayers , false , true ); @@ -5362,10 +5378,6 @@ namespace bgfx { namespace d3d11 ts.m_srv[_stage] = m_srv; } - const uint32_t flags = 0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & _flags) - ? _flags - : uint32_t(m_flags) - ; uint32_t index = (flags & BGFX_SAMPLER_BORDER_COLOR_MASK) >> BGFX_SAMPLER_BORDER_COLOR_SHIFT; ts.m_sampler[_stage] = s_renderD3D11->getSamplerState(flags, _palette[index]); } @@ -5377,10 +5389,15 @@ namespace bgfx { namespace d3d11 const bool needResolve = NULL != m_rt; if (needResolve) { + const DXGI_FORMAT resolveFormat = bimg::isDepth(bimg::TextureFormat::Enum(m_textureFormat) ) + ? s_textureFormat[m_textureFormat].m_fmt + : getSrvFormat() + ; + for (uint32_t ii = _layer, end = _layer + _numLayers; ii < end; ++ii) { const UINT resource = _mip + (ii * m_numMips); - deviceCtx->ResolveSubresource(m_texture2d, resource, m_rt, resource, s_textureFormat[m_textureFormat].m_fmt); + deviceCtx->ResolveSubresource(m_texture2d, resource, m_rt, resource, resolveFormat); } } @@ -5544,6 +5561,7 @@ namespace bgfx { namespace d3d11 { m_width = 0; m_height = 0; + m_needsQuadClear = false; if (0 < m_numTh) { @@ -5723,6 +5741,8 @@ namespace bgfx { namespace d3d11 desc.Texture3D.FirstWSlice = at.layer; desc.Texture3D.WSize = at.numLayers; + m_needsQuadClear = true; + DX_CHECK(s_renderD3D11->m_device->CreateRenderTargetView(texture.m_ptr, &desc, &m_rtv[m_num]) ); break; } diff --git a/src/renderer_d3d11.h b/src/renderer_d3d11.h index d5ac5af0c..d035aebf7 100644 --- a/src/renderer_d3d11.h +++ b/src/renderer_d3d11.h @@ -336,6 +336,7 @@ namespace bgfx { namespace d3d11 , m_numTh(0) , m_numUav(0) , m_needPresent(false) + , m_needsQuadClear(false) { bx::memSet(m_rtv, 0, sizeof(m_rtv) ); bx::memSet(m_uav, 0, sizeof(m_uav) ); @@ -367,6 +368,7 @@ namespace bgfx { namespace d3d11 uint8_t m_numTh; uint8_t m_numUav; bool m_needPresent; + bool m_needsQuadClear; }; struct TimerQueryD3D11 diff --git a/src/renderer_d3d12.cpp b/src/renderer_d3d12.cpp index 91650e301..caaf0526e 100644 --- a/src/renderer_d3d12.cpp +++ b/src/renderer_d3d12.cpp @@ -3694,7 +3694,30 @@ namespace bgfx { namespace d3d12 murmur.add(m_scd.sampleDesc); - if (!isValid(m_fbh) ) + if (isValid(m_fbh) ) + { + const FrameBufferD3D12& frameBuffer = m_frameBuffers[m_fbh.idx]; + + if (NULL == frameBuffer.m_swapChain) + { + murmur.add(frameBuffer.m_num); + + for (uint8_t ii = 0, num = frameBuffer.m_num; ii < num; ++ii) + { + murmur.add(m_textures[frameBuffer.m_texture[ii].idx].m_srvd.Format); + } + + murmur.add(isValid(frameBuffer.m_depth) + ? s_textureFormat[m_textures[frameBuffer.m_depth.idx].m_textureFormat].m_fmtDsv + : DXGI_FORMAT_UNKNOWN + ); + } + else + { + murmur.add(frameBuffer.m_swapChainFormat); + } + } + else { murmur.add(getBackBufferFormat(m_resolution) ); murmur.add(getBackBufferDepthStencilFormat(m_resolution) ); @@ -4389,7 +4412,7 @@ namespace bgfx { namespace d3d12 alloc(_gpuHandle, cpuHandle); } - void ScratchBufferD3D12::allocSrv(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle, TextureD3D12& _texture, uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips) + void ScratchBufferD3D12::allocSrv(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle, TextureD3D12& _texture, uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips, bool _stencil) { ID3D12Device* device = s_renderD3D12->m_device; @@ -4404,7 +4427,8 @@ namespace bgfx { namespace d3d12 D3D12_SHADER_RESOURCE_VIEW_DESC tmpSrvd; D3D12_SHADER_RESOURCE_VIEW_DESC* srvd = &_texture.m_srvd; - if (!fullRange) + if (!fullRange + || _stencil) { bx::memCopy(&tmpSrvd, srvd, sizeof(tmpSrvd) ); srvd = &tmpSrvd; @@ -4453,6 +4477,29 @@ namespace bgfx { namespace d3d12 srvd->Texture3D.ResourceMinLODClamp = 0; break; } + + if (_stencil) + { + srvd->Format = DXGI_FORMAT_R32G8X24_TYPELESS == s_textureFormat[_texture.m_textureFormat].m_fmt + ? DXGI_FORMAT_X32_TYPELESS_G8X24_UINT + : DXGI_FORMAT_X24_TYPELESS_G8_UINT + ; + srvd->Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + + switch (srvd->ViewDimension) + { + case D3D12_SRV_DIMENSION_TEXTURE2D: + srvd->Texture2D.PlaneSlice = 1; + break; + + case D3D12_SRV_DIMENSION_TEXTURE2DARRAY: + srvd->Texture2DArray.PlaneSlice = 1; + break; + + default: + break; + } + } } ID3D12Resource* resource = NULL != _texture.m_singleMsaa ? _texture.m_singleMsaa : _texture.m_ptr; @@ -4464,6 +4511,7 @@ namespace bgfx { namespace d3d12 } if (fullRange + && !_stencil && NULL == _texture.m_singleMsaa) { if (0 == _texture.m_srvHandle.ptr) @@ -4492,7 +4540,7 @@ namespace bgfx { namespace d3d12 const bool arrayed = UINT16_MAX != _numLayers; const bool forceArray = arrayed && D3D12_UAV_DIMENSION_TEXTURE2D == uavd->ViewDimension; - if (0 != _mip || forceArray) + if (0 != _mip || arrayed) { bx::memCopy(&tmpUavd, uavd, sizeof(tmpUavd) ); uavd = &tmpUavd; @@ -4517,6 +4565,12 @@ namespace bgfx { namespace d3d12 case D3D12_UAV_DIMENSION_TEXTURE2DARRAY: uavd->Texture2DArray.MipSlice = _mip; uavd->Texture2DArray.PlaneSlice = 0; + + if (arrayed) + { + uavd->Texture2DArray.FirstArraySlice = _firstLayer; + uavd->Texture2DArray.ArraySize = bx::max(_numLayers, 1); + } break; case D3D12_UAV_DIMENSION_TEXTURE3D: @@ -8231,13 +8285,15 @@ namespace bgfx { namespace d3d12 case Binding::Texture: { TextureD3D12& texture = m_textures[bind.m_idx]; - texture.setState(m_commandList, D3D12_RESOURCE_STATE_GENERIC_READ); - scratchBuffer.allocSrv(srvHandle[stage], texture, bind.m_firstLayer, bind.m_numLayers, bind.m_firstMip, bind.m_numMips); - samplerFlags[stage] = (0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & bind.m_samplerFlags) + const uint32_t resolvedFlags = 0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & bind.m_samplerFlags) ? bind.m_samplerFlags - : texture.m_flags - ) & (BGFX_SAMPLER_BITS_MASK | BGFX_SAMPLER_BORDER_COLOR_MASK | BGFX_SAMPLER_COMPARE_MASK) + : uint32_t(texture.m_flags) ; + texture.setState(m_commandList, D3D12_RESOURCE_STATE_GENERIC_READ); + scratchBuffer.allocSrv(srvHandle[stage], texture, bind.m_firstLayer, bind.m_numLayers, bind.m_firstMip, bind.m_numMips + , 0 != (resolvedFlags & BGFX_SAMPLER_SAMPLE_STENCIL) + ); + samplerFlags[stage] = resolvedFlags & (BGFX_SAMPLER_BITS_MASK | BGFX_SAMPLER_BORDER_COLOR_MASK | BGFX_SAMPLER_COMPARE_MASK); ++numSet; } @@ -8563,13 +8619,15 @@ namespace bgfx { namespace d3d12 case Binding::Texture: { TextureD3D12& texture = m_textures[bind.m_idx]; - texture.setState(m_commandList, D3D12_RESOURCE_STATE_GENERIC_READ); - scratchBuffer.allocSrv(srvHandle[stage], texture, bind.m_firstLayer, bind.m_numLayers, bind.m_firstMip, bind.m_numMips); - samplerFlags[stage] = (0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & bind.m_samplerFlags) + const uint32_t resolvedFlags = 0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & bind.m_samplerFlags) ? bind.m_samplerFlags - : texture.m_flags - ) & (BGFX_SAMPLER_BITS_MASK | BGFX_SAMPLER_BORDER_COLOR_MASK | BGFX_SAMPLER_COMPARE_MASK) + : uint32_t(texture.m_flags) ; + texture.setState(m_commandList, D3D12_RESOURCE_STATE_GENERIC_READ); + scratchBuffer.allocSrv(srvHandle[stage], texture, bind.m_firstLayer, bind.m_numLayers, bind.m_firstMip, bind.m_numMips + , 0 != (resolvedFlags & BGFX_SAMPLER_SAMPLE_STENCIL) + ); + samplerFlags[stage] = resolvedFlags & (BGFX_SAMPLER_BITS_MASK | BGFX_SAMPLER_BORDER_COLOR_MASK | BGFX_SAMPLER_COMPARE_MASK); ++numSet; } diff --git a/src/renderer_d3d12.h b/src/renderer_d3d12.h index 18bd1f1ac..351f08251 100644 --- a/src/renderer_d3d12.h +++ b/src/renderer_d3d12.h @@ -128,7 +128,7 @@ namespace bgfx { namespace d3d12 void allocEmpty(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle); - void allocSrv(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle, struct TextureD3D12& _texture, uint16_t _firstLayer = 0, uint16_t _numLayers = UINT16_MAX, uint8_t _firstMip = 0, uint8_t _numMips = UINT8_MAX); + void allocSrv(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle, struct TextureD3D12& _texture, uint16_t _firstLayer = 0, uint16_t _numLayers = UINT16_MAX, uint8_t _firstMip = 0, uint8_t _numMips = UINT8_MAX, bool _stencil = false); void allocSrv(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle, struct BufferD3D12& _buffer); void allocUav(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle, struct TextureD3D12& _texture, uint8_t _mip = 0, uint16_t _firstLayer = 0, uint16_t _numLayers = UINT16_MAX); diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index 187a4c28b..d48c9d59c 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -636,6 +636,7 @@ namespace bgfx { namespace gl ARB_shader_storage_buffer_object, ARB_shader_texture_lod, ARB_shader_viewport_layer_array, + ARB_stencil_texturing, ARB_texture_compression_bptc, ARB_texture_compression_rgtc, ARB_texture_cube_map_array, @@ -857,6 +858,7 @@ namespace bgfx { namespace gl { "ARB_shader_storage_buffer_object", BGFX_CONFIG_RENDERER_OPENGL >= 43, true }, { "ARB_shader_texture_lod", BGFX_CONFIG_RENDERER_OPENGL >= 30, true }, { "ARB_shader_viewport_layer_array", false, true }, + { "ARB_stencil_texturing", BGFX_CONFIG_RENDERER_OPENGL >= 43, true }, { "ARB_texture_compression_bptc", BGFX_CONFIG_RENDERER_OPENGL >= 44, true }, { "ARB_texture_compression_rgtc", BGFX_CONFIG_RENDERER_OPENGL >= 30, true }, { "ARB_texture_cube_map_array", BGFX_CONFIG_RENDERER_OPENGL >= 40, true }, @@ -2294,6 +2296,7 @@ namespace bgfx { namespace gl , m_blitSupported(false) , m_blitFboSupported(false) , m_textureViewSupported(false) + , m_depthStencilTexturingSupported(false) , m_readBackSupported(BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL) ) , m_readBackFboSupported(false) , m_vaoSupport(false) @@ -2959,6 +2962,12 @@ namespace bgfx { namespace gl m_textureViewSupported = NULL != glTextureView; } + m_depthStencilTexturingSupported = false + || s_extension[Extension::ARB_stencil_texturing].m_supported + || BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL >= 43) + || BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGLES >= 31) + ; + m_blitFboSupported = !m_blitSupported && BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGLES); m_readBackFboSupported = !m_readBackSupported; @@ -5022,6 +5031,7 @@ namespace bgfx { namespace gl bool m_blitSupported; bool m_blitFboSupported; bool m_textureViewSupported; + bool m_depthStencilTexturingSupported; bool m_readBackSupported; bool m_readBackFboSupported; bool m_vaoSupport; @@ -5144,6 +5154,13 @@ namespace bgfx { namespace gl GLSL_TYPE(GL_INT_SAMPLER_CUBE); GLSL_TYPE(GL_UNSIGNED_INT_SAMPLER_CUBE); + GLSL_TYPE(GL_SAMPLER_CUBE_SHADOW); + GLSL_TYPE(GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW); + + GLSL_TYPE(GL_SAMPLER_CUBE_MAP_ARRAY); + GLSL_TYPE(GL_INT_SAMPLER_CUBE_MAP_ARRAY); + GLSL_TYPE(GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY); + GLSL_TYPE(GL_IMAGE_1D); GLSL_TYPE(GL_INT_IMAGE_1D); GLSL_TYPE(GL_UNSIGNED_INT_IMAGE_1D); @@ -5160,6 +5177,10 @@ namespace bgfx { namespace gl GLSL_TYPE(GL_IMAGE_CUBE); GLSL_TYPE(GL_INT_IMAGE_CUBE); GLSL_TYPE(GL_UNSIGNED_INT_IMAGE_CUBE); + + GLSL_TYPE(GL_IMAGE_CUBE_MAP_ARRAY); + GLSL_TYPE(GL_INT_IMAGE_CUBE_MAP_ARRAY); + GLSL_TYPE(GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY); } #undef GLSL_TYPE @@ -5242,6 +5263,13 @@ namespace bgfx { namespace gl case GL_INT_SAMPLER_CUBE: case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: + + case GL_SAMPLER_CUBE_MAP_ARRAY: + case GL_INT_SAMPLER_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY: + case GL_IMAGE_1D: case GL_INT_IMAGE_1D: case GL_UNSIGNED_INT_IMAGE_1D: @@ -5258,6 +5286,10 @@ namespace bgfx { namespace gl case GL_IMAGE_CUBE: case GL_INT_IMAGE_CUBE: case GL_UNSIGNED_INT_IMAGE_CUBE: + + case GL_IMAGE_CUBE_MAP_ARRAY: + case GL_INT_IMAGE_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: return UniformType::Sampler; }; @@ -5497,6 +5529,13 @@ namespace bgfx { namespace gl case GL_INT_SAMPLER_CUBE: case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: + + case GL_SAMPLER_CUBE_MAP_ARRAY: + case GL_INT_SAMPLER_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY: + case GL_IMAGE_1D: case GL_INT_IMAGE_1D: case GL_UNSIGNED_INT_IMAGE_1D: @@ -5512,6 +5551,10 @@ namespace bgfx { namespace gl case GL_IMAGE_CUBE: case GL_INT_IMAGE_CUBE: case GL_UNSIGNED_INT_IMAGE_CUBE: + + case GL_IMAGE_CUBE_MAP_ARRAY: + case GL_INT_IMAGE_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: if (m_numSamplers < BX_COUNTOF(m_sampler) ) { BX_TRACE("Sampler #%d at location %d.", m_numSamplers, loc); @@ -5777,6 +5820,8 @@ namespace bgfx { namespace gl m_height = _height; m_depth = _depth; m_currentSamplerHash = UINT32_MAX; + m_baseLevel = 0; + m_maxLevel = -1; const bool writeOnly = 0 != (m_flags&BGFX_TEXTURE_RT_WRITE_ONLY); const bool computeWrite = 0 != (m_flags&BGFX_TEXTURE_COMPUTE_WRITE ); @@ -5850,7 +5895,7 @@ namespace bgfx { namespace gl , internalFmt , m_width , m_height - , _depth + , GL_TEXTURE_CUBE_MAP_ARRAY == _target ? _depth*6 : _depth ) ); m_immutableStorage = true; } @@ -6269,11 +6314,18 @@ namespace bgfx { namespace gl GL_CHECK(glBindTexture(m_target, m_id) ); GL_CHECK(glPixelStorei(GL_UNPACK_ALIGNMENT, 1) ); - GLenum target = isCubeMap() - ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + const bool cubeArray = GL_TEXTURE_CUBE_MAP_ARRAY == m_target; + + GLenum target = isCubeMap() && !cubeArray + ? GLenum(GL_TEXTURE_CUBE_MAP_POSITIVE_X + _side) : m_target ; + const uint16_t zOffset = cubeArray + ? uint16_t(_z*6 + _side) + : _z + ; + const bool swizzle = true && TextureFormat::BGRA8 == m_requestedFormat && !s_textureFormat[m_requestedFormat].m_supported @@ -6333,11 +6385,11 @@ namespace bgfx { namespace gl ? s_textureFormat[m_textureFormat].m_internalFmtSrgb : s_textureFormat[m_textureFormat].m_internalFmt ; - GL_CHECK(compressedTexSubImage(target+_side + GL_CHECK(compressedTexSubImage(target , _mip , rect.m_x , rect.m_y - , _z + , zOffset , rect.m_width , rect.m_height , _depth @@ -6365,11 +6417,11 @@ namespace bgfx { namespace gl data = temp; } - GL_CHECK(texSubImage(target+_side + GL_CHECK(texSubImage(target , _mip , rect.m_x , rect.m_y - , _z + , zOffset , rect.m_width , rect.m_height , _depth @@ -6440,6 +6492,7 @@ namespace bgfx { namespace gl && (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL) || s_renderGL->m_gles3 || s_extension[Extension::APPLE_texture_max_level].m_supported) ) { GL_CHECK(glTexParameteri(targetMsaa, GL_TEXTURE_MAX_LEVEL, numMips-1) ); + m_maxLevel = -1; } if (target == GL_TEXTURE_3D) @@ -6489,13 +6542,48 @@ namespace bgfx { namespace gl } } - GLuint TextureGL::getViewId(uint8_t _firstMip, uint8_t _numMips, uint16_t _firstLayer, uint16_t _numLayers) + GLenum TextureGL::getViewTarget(uint16_t _numLayers, bool _layered) const { - 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) ); - const uint16_t firstLayer = bx::min(_firstLayer, uint16_t(numLayers0 - 1) ); - const uint16_t numLayers = bx::min(_numLayers, uint16_t(numLayers0 - firstLayer) ); + switch (m_target) + { + case GL_TEXTURE_2D_ARRAY: + case GL_TEXTURE_CUBE_MAP: + case GL_TEXTURE_CUBE_MAP_ARRAY: + if (_layered) + { + return GL_TEXTURE_2D_ARRAY; + } + + if (1 == _numLayers) + { + return GL_TEXTURE_2D; + } + + if (!isCubeMap() ) + { + return GL_TEXTURE_2D_ARRAY; + } + + return 6 == _numLayers + ? GL_TEXTURE_CUBE_MAP + : GL_TEXTURE_CUBE_MAP_ARRAY + ; + + default: + break; + } + + return m_target; + } + + 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 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 bool fullRange = 0 == firstMip && numMips >= m_numMips @@ -6503,19 +6591,38 @@ namespace bgfx { namespace gl && numLayers >= numLayers0 ; + const GLenum target = getViewTarget(numLayers, _layered); + + const bool cubeAligned = GL_TEXTURE_2D == target + || GL_TEXTURE_2D_ARRAY == target + || (0 == firstLayer%facesPerLayer && 0 == numLayers%facesPerLayer) + ; + if (fullRange || !s_renderGL->m_textureViewSupported || !m_immutableStorage || GL_ZERO == m_internalFmt + || !cubeAligned || NULL == glTextureView) { + if (NULL != _target) + { + *_target = m_target; + } + return m_id; } + if (NULL != _target) + { + *_target = target; + } + const uint16_t parent = uint16_t(this - s_renderGL->m_textures); const uint64_t key = 0 | (uint64_t(parent) << 48) + | (uint64_t(_layered) << 47) | (uint64_t(firstMip) << 40) | (uint64_t(numMips) << 32) | (uint64_t(firstLayer) << 16) @@ -6531,7 +6638,7 @@ namespace bgfx { namespace gl GL_CHECK(glGenTextures(1, &viewId) ); s_renderGL->m_textureViewStateCache.add(key, TextureViewGL{viewId}, parent); GL_CHECK(glTextureView(viewId - , m_target + , target , m_id , m_internalFmt , firstMip @@ -6551,10 +6658,28 @@ namespace bgfx { namespace gl ; const uint32_t index = (flags & BGFX_SAMPLER_BORDER_COLOR_MASK) >> BGFX_SAMPLER_BORDER_COLOR_SHIFT; - const GLuint id = getViewId(_firstMip, _numMips, _firstLayer, _numLayers); + GLenum target = m_target; + const GLuint id = getViewId(_firstMip, _numMips, _firstLayer, _numLayers, &target); GL_CHECK(glActiveTexture(GL_TEXTURE0+_stage) ); - GL_CHECK(glBindTexture(m_target, id) ); + GL_CHECK(glBindTexture(target, id) ); + + m_depthStencilTexturing |= 0 != (flags & BGFX_SAMPLER_SAMPLE_STENCIL); + + if (m_depthStencilTexturing) + { + BX_WARN(s_renderGL->m_depthStencilTexturingSupported + , "BGFX_SAMPLER_SAMPLE_STENCIL requires OpenGL 4.3, OpenGL ES 3.1 or GL_ARB_stencil_texturing; sampling depth instead." + ); + + if (s_renderGL->m_depthStencilTexturingSupported) + { + GL_CHECK(glTexParameteri(target, GL_DEPTH_STENCIL_TEXTURE_MODE, 0 != (flags & BGFX_SAMPLER_SAMPLE_STENCIL) + ? GL_STENCIL_INDEX + : GL_DEPTH_COMPONENT + ) ); + } + } if (s_renderGL->m_samplerObjectSupport) { @@ -6564,6 +6689,26 @@ namespace bgfx { namespace gl { setSamplerState(flags, _palette[index]); } + + if (id == m_id + && 1 < m_numMips + && GL_TEXTURE_2D_MULTISAMPLE != m_target + && (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL >= 30) || s_renderGL->m_gles3) ) + { + 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 int32_t baseLevel = int32_t(firstMip); + const int32_t maxLevel = int32_t(firstMip + numMips - 1); + + if (m_baseLevel != baseLevel + || m_maxLevel != maxLevel) + { + GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_BASE_LEVEL, baseLevel) ); + GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_MAX_LEVEL, maxLevel) ); + m_baseLevel = baseLevel; + m_maxLevel = maxLevel; + } + } } void TextureGL::resolve(uint8_t _resolve) const @@ -7557,8 +7702,10 @@ namespace bgfx { namespace gl } else { - if (1 < texture.m_numLayers - && !texture.isCubeMap() ) + const bool cubeArray = GL_TEXTURE_CUBE_MAP_ARRAY == texture.m_target; + + if ( (1 < texture.m_numLayers && !texture.isCubeMap() ) + || cubeArray) { if (1 < at.numLayers) { @@ -8392,12 +8539,31 @@ namespace bgfx { namespace gl case Binding::Image: { - const TextureGL& texture = m_textures[bind.m_idx]; + TextureGL& texture = m_textures[bind.m_idx]; + + GLuint id = texture.m_id; + GLint level = bind.m_firstMip; + GLint layer = bind.m_firstLayer; + GLboolean layered = texture.isLayered() || UINT16_MAX != bind.m_numLayers ? GL_TRUE : GL_FALSE; + + if (UINT16_MAX != bind.m_numLayers + && texture.isLayered() ) + { + const GLuint viewId = texture.getViewId(bind.m_firstMip, 1, bind.m_firstLayer, bind.m_numLayers, NULL, true); + + if (viewId != texture.m_id) + { + id = viewId; + level = 0; + layer = 0; + } + } + GL_CHECK(glBindImageTexture(ii - , texture.m_id - , bind.m_firstMip - , texture.isLayered() || UINT16_MAX != bind.m_numLayers ? GL_TRUE : GL_FALSE - , bind.m_firstLayer + , id + , level + , layered + , layer , s_access[bind.m_access] , s_imageFormat[bind.m_format]) ); @@ -8920,6 +9086,10 @@ namespace bgfx { namespace gl if (current.m_idx != bind.m_idx || current.m_type != bind.m_type || current.m_samplerFlags != bind.m_samplerFlags + || current.m_firstLayer != bind.m_firstLayer + || current.m_numLayers != bind.m_numLayers + || current.m_firstMip != bind.m_firstMip + || current.m_numMips != bind.m_numMips || programChanged) { if (kInvalidHandle != bind.m_idx) @@ -8928,12 +9098,31 @@ namespace bgfx { namespace gl { case Binding::Image: { - const TextureGL& texture = m_textures[bind.m_idx]; + TextureGL& texture = m_textures[bind.m_idx]; + + GLuint id = texture.m_id; + GLint level = bind.m_firstMip; + GLint layer = bind.m_firstLayer; + GLboolean layered = texture.isLayered() || UINT16_MAX != bind.m_numLayers ? GL_TRUE : GL_FALSE; + + if (UINT16_MAX != bind.m_numLayers + && texture.isLayered() ) + { + const GLuint viewId = texture.getViewId(bind.m_firstMip, 1, bind.m_firstLayer, bind.m_numLayers, NULL, true); + + if (viewId != texture.m_id) + { + id = viewId; + level = 0; + layer = 0; + } + } + GL_CHECK(glBindImageTexture(stage - , texture.m_id - , bind.m_firstMip - , texture.isLayered() || UINT16_MAX != bind.m_numLayers ? GL_TRUE : GL_FALSE - , bind.m_firstLayer + , id + , level + , layered + , layer , s_access[bind.m_access] , s_imageFormat[bind.m_format]) ); diff --git a/src/renderer_gl.h b/src/renderer_gl.h index a69d25453..16c9eaa77 100644 --- a/src/renderer_gl.h +++ b/src/renderer_gl.h @@ -297,6 +297,10 @@ typedef uint64_t GLuint64; # define GL_STENCIL_INDEX 0x1901 #endif // GL_STENCIL_INDEX +#ifndef GL_DEPTH_STENCIL_TEXTURE_MODE +# define GL_DEPTH_STENCIL_TEXTURE_MODE 0x90EA +#endif // GL_DEPTH_STENCIL_TEXTURE_MODE + #ifndef GL_RED # define GL_RED 0x1903 #endif // GL_RED @@ -870,6 +874,26 @@ typedef uint64_t GLuint64; # define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 #endif // GL_SAMPLER_2D_ARRAY_SHADOW +#ifndef GL_SAMPLER_CUBE_SHADOW +# define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#endif // GL_SAMPLER_CUBE_SHADOW + +#ifndef GL_SAMPLER_CUBE_MAP_ARRAY +# define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C +#endif // GL_SAMPLER_CUBE_MAP_ARRAY + +#ifndef GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW +# define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D +#endif // GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW + +#ifndef GL_INT_SAMPLER_CUBE_MAP_ARRAY +# define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E +#endif // GL_INT_SAMPLER_CUBE_MAP_ARRAY + +#ifndef GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY +# define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F +#endif // GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY + #ifndef GL_TEXTURE_MAX_LEVEL # define GL_TEXTURE_MAX_LEVEL 0x813D #endif // GL_TEXTURE_MAX_LEVEL @@ -966,6 +990,18 @@ typedef uint64_t GLuint64; # define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066 #endif // GL_UNSIGNED_INT_IMAGE_CUBE +#ifndef GL_IMAGE_CUBE_MAP_ARRAY +# define GL_IMAGE_CUBE_MAP_ARRAY 0x9054 +#endif // GL_IMAGE_CUBE_MAP_ARRAY + +#ifndef GL_INT_IMAGE_CUBE_MAP_ARRAY +# define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F +#endif // GL_INT_IMAGE_CUBE_MAP_ARRAY + +#ifndef GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY +# define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A +#endif // GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY + #ifndef GL_PROGRAM_INPUT # define GL_PROGRAM_INPUT 0x92E3 #endif // GL_PROGRAM_INPUT @@ -1452,7 +1488,8 @@ namespace bgfx { namespace gl void clear(uint8_t _mip, uint8_t _numMips, uint16_t _layer, uint16_t _numLayers); void setSamplerState(uint32_t _flags, const float _rgba[4]); void commit(uint32_t _stage, uint32_t _flags, const float _palette[][4], uint8_t _firstMip, uint8_t _numMips, uint16_t _firstLayer, uint16_t _numLayers); - GLuint getViewId(uint8_t _firstMip, uint8_t _numMips, uint16_t _firstLayer, uint16_t _numLayers); + GLenum getViewTarget(uint16_t _numLayers, bool _layered = false) const; + GLuint getViewId(uint8_t _firstMip, uint8_t _numMips, uint16_t _firstLayer, uint16_t _numLayers, GLenum* _target = NULL, bool _layered = false); void resolve(uint8_t _resolve) const; bool isCubeMap() const @@ -1488,6 +1525,9 @@ namespace bgfx { namespace gl uint8_t m_requestedFormat; uint8_t m_textureFormat; bool m_immutableStorage; + int32_t m_baseLevel = 0; + int32_t m_maxLevel = -1; + bool m_depthStencilTexturing = false; }; struct ShaderGL diff --git a/src/renderer_mtl.cpp b/src/renderer_mtl.cpp index a299df724..1aec17924 100644 --- a/src/renderer_mtl.cpp +++ b/src/renderer_mtl.cpp @@ -3878,11 +3878,17 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames : MTL::StorageModeManaged ) ); + const bool packedDepthStencil = false + || TextureFormat::D24S8 == TextureFormat::Enum(m_textureFormat) + || TextureFormat::D32FS8 == TextureFormat::Enum(m_textureFormat) + ; + MTL::TextureUsage usage = 0 | MTL::TextureUsageShaderRead - | (computeWrite ? MTL::TextureUsageShaderWrite : 0) - | (isVideoDecodeDst? MTL::TextureUsageShaderWrite : 0) - | (renderTarget ? MTL::TextureUsageRenderTarget : 0) + | (computeWrite ? MTL::TextureUsageShaderWrite : 0) + | (isVideoDecodeDst? MTL::TextureUsageShaderWrite : 0) + | (renderTarget ? MTL::TextureUsageRenderTarget : 0) + | (packedDepthStencil ? MTL::TextureUsagePixelFormatView : 0) ; desc->setUsage(usage); @@ -4195,9 +4201,15 @@ 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) { + const uint32_t flags = 0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & _flags) + ? _flags + : uint32_t(m_flags) + ; + const bool sampleStencil = 0 != (flags & BGFX_SAMPLER_SAMPLE_STENCIL); + if (_vertex) { - MTL::Texture* p = _mip != UINT8_MAX ? getTextureMipLevel(_mip) : getTextureView(_firstLayer, _numLayers, _firstMip, _numMips); + MTL::Texture* p = _mip != UINT8_MAX ? getTextureMipLevel(_mip) : getTextureView(_firstLayer, _numLayers, _firstMip, _numMips, sampleStencil); s_renderMtl->m_renderCommandEncoder->setVertexTexture(p, _stage); s_renderMtl->m_renderCommandEncoder->setVertexSamplerState( 0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & _flags) @@ -4209,7 +4221,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames if (_fragment) { - MTL::Texture* p = _mip != UINT8_MAX ? getTextureMipLevel(_mip) : getTextureView(_firstLayer, _numLayers, _firstMip, _numMips); + MTL::Texture* p = _mip != UINT8_MAX ? getTextureMipLevel(_mip) : getTextureView(_firstLayer, _numLayers, _firstMip, _numMips, sampleStencil); s_renderMtl->m_renderCommandEncoder->setFragmentTexture(p, _stage); s_renderMtl->m_renderCommandEncoder->setFragmentSamplerState( 0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & _flags) @@ -4220,14 +4232,34 @@ 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) + MTL::Texture* TextureMtl::getTextureView(uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips, bool _stencil) { - if (NULL == m_ptr) + MTL::Texture* ptr = _stencil && NULL != m_ptrStencil + ? m_ptrStencil + : m_ptr + ; + + if (NULL == ptr) { return NULL; } - const uint32_t totalLayers = uint32_t(m_ptr->arrayLength() * (TextureCube == m_type ? 6 : 1) ); + MTL::PixelFormat format = ptr->pixelFormat(); + + if (_stencil + && ptr == m_ptr) + { + if (MTL::PixelFormatDepth32Float_Stencil8 == format) + { + format = (MTL::PixelFormat)MTL::PixelFormatX32_Stencil8; + } + else if (MTL::PixelFormatDepth24Unorm_Stencil8 == format) + { + format = (MTL::PixelFormat)MTL::PixelFormatX24_Stencil8; + } + } + + const uint32_t totalLayers = uint32_t(ptr->arrayLength() * (TextureCube == m_type ? 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) ); @@ -4240,9 +4272,10 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames && numLayers >= totalLayers ; - if (fullRange) + if (fullRange + && format == ptr->pixelFormat() ) { - return m_ptr; + return ptr; } const uint64_t key = 0 @@ -4250,6 +4283,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(_stencil) << 63) ; stl::unordered_map::iterator it = m_ptrViews.find(key); @@ -4258,9 +4292,9 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames return it->second; } - MTL::Texture* view = m_ptr->newTextureView( - m_ptr->pixelFormat() - , TextureCube == m_type ? (MTL::TextureType)MTL::TextureType2DArray : m_ptr->textureType() + MTL::Texture* view = ptr->newTextureView( + format + , TextureCube == m_type ? (MTL::TextureType)MTL::TextureType2DArray : ptr->textureType() , NS::Range::Make(firstMip, numMips) , NS::Range::Make(firstLayer, numLayers) ); @@ -5683,7 +5717,15 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames TextureMtl& texture = m_textures[bind.m_idx]; uint32_t flags = bind.m_samplerFlags; - m_computeCommandEncoder->setTexture(texture.m_ptr, stage); + const uint32_t resolvedFlags = 0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & flags) + ? flags + : uint32_t(texture.m_flags) + ; + + m_computeCommandEncoder->setTexture( + texture.getTextureView(0, UINT16_MAX, 0, UINT8_MAX, 0 != (resolvedFlags & BGFX_SAMPLER_SAMPLE_STENCIL) ) + , stage + ); m_computeCommandEncoder->setSamplerState( 0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & flags) ? getSamplerState(flags) diff --git a/src/renderer_mtl.h b/src/renderer_mtl.h index 6f6c89b3d..1a75b1024 100644 --- a/src/renderer_mtl.h +++ b/src/renderer_mtl.h @@ -464,7 +464,7 @@ namespace bgfx { namespace mtl ); MTL::Texture* getTextureMipLevel(uint8_t _mip, bool _array = false); - MTL::Texture* getTextureView(uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips); + MTL::Texture* getTextureView(uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips, bool _stencil = false); MTL::Texture* m_ptr; MTL::Texture* m_ptrMsaa; diff --git a/src/renderer_vk.cpp b/src/renderer_vk.cpp index 61fba36ff..35237849a 100644 --- a/src/renderer_vk.cpp +++ b/src/renderer_vk.cpp @@ -4364,6 +4364,9 @@ VK_IMPORT_DEVICE , bind.m_firstMip , bind.m_numMips , type + , false + , bind.m_firstLayer + , bind.m_numLayers ); wds[wdsCount].pImageInfo = &imageInfo[imageCount]; ++imageCount; diff --git a/src/renderer_webgpu.cpp b/src/renderer_webgpu.cpp index e43446d86..dfec4d317 100644 --- a/src/renderer_webgpu.cpp +++ b/src/renderer_webgpu.cpp @@ -2605,14 +2605,28 @@ WGPU_IMPORT case ShaderBinding::Type::Sampler: { TextureWGPU& texture = m_textures[bind.m_idx]; + + const uint32_t resolvedFlags = 0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & bind.m_samplerFlags) + ? bind.m_samplerFlags + : texture.m_flags + ; + WGPUTextureSampleType sampleType = WGPUTextureSampleType_Depth != shaderBind.sampleType ? s_textureFormat[texture.m_textureFormat].m_samplerType : shaderBind.sampleType ; + if (0 != (resolvedFlags & BGFX_SAMPLER_SAMPLE_STENCIL) ) + { + // Stencil aspect is viewed as Stencil8, which is an unsigned integer format. + sampleType = WGPUTextureSampleType_Uint; + } + WGPUSamplerBindingType samplerBindingType = WGPUSamplerBindingType_Filtering; switch (sampleType) { + case WGPUTextureSampleType_Uint: + case WGPUTextureSampleType_Sint: case WGPUTextureSampleType_UnfilterableFloat: samplerBindingType = WGPUSamplerBindingType_NonFiltering; break; case WGPUTextureSampleType_Depth: samplerBindingType = WGPUSamplerBindingType_Comparison; break; default: break; @@ -3146,6 +3160,14 @@ WGPU_IMPORT { const TextureWGPU& texture = m_textures[bind.m_idx]; + const uint32_t resolvedFlags = 0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & bind.m_samplerFlags) + ? bind.m_samplerFlags + : texture.m_flags + ; + const bool sampleStencil = Binding::Texture == bind.m_type + && 0 != (resolvedFlags & BGFX_SAMPLER_SAMPLE_STENCIL) + ; + bindGroupEntry[entryCount++] = { .nextInChain = NULL, @@ -3155,8 +3177,8 @@ WGPU_IMPORT .size = 0, .sampler = NULL, .textureView = _isCompute - ? texture.getTextureView(bind.m_firstMip, bind.m_numMips, Binding::Image == bind.m_type, 0, UINT16_MAX, Binding::Image == bind.m_type && UINT16_MAX != bind.m_numLayers) - : texture.getTextureView(bind.m_firstMip, bind.m_numMips, false, bind.m_firstLayer, bind.m_numLayers) + ? texture.getTextureView(bind.m_firstMip, bind.m_numMips, Binding::Image == bind.m_type, 0, UINT16_MAX, Binding::Image == bind.m_type && UINT16_MAX != bind.m_numLayers, sampleStencil) + : texture.getTextureView(bind.m_firstMip, bind.m_numMips, false, bind.m_firstLayer, bind.m_numLayers, false, sampleStencil) , }; @@ -4403,7 +4425,7 @@ WGPU_IMPORT return sampler; } - WGPUTextureView TextureWGPU::getTextureView(uint8_t _baseMipLevel, uint8_t _mipLevelCount, bool _storage, uint16_t _baseArrayLayer, uint16_t _arrayLayerCount, bool _force2DArray) const + WGPUTextureView TextureWGPU::getTextureView(uint8_t _baseMipLevel, uint8_t _mipLevelCount, bool _storage, uint16_t _baseArrayLayer, uint16_t _arrayLayerCount, bool _force2DArray, bool _stencil) const { bx::HashMurmur3 murmur; murmur.begin(); @@ -4414,6 +4436,7 @@ WGPU_IMPORT murmur.add(_baseArrayLayer); murmur.add(_arrayLayerCount); murmur.add(_force2DArray); + murmur.add(_stencil); const uint32_t hash = murmur.end(); WGPUTextureView textureView = s_renderWGPU->m_textureViewStateCache.find(hash); @@ -4443,13 +4466,19 @@ WGPU_IMPORT { .nextInChain = NULL, .label = WGPU_STRING_VIEW_INIT, - .format = s_textureFormat[m_textureFormat].m_fmt, + .format = _stencil + ? WGPUTextureFormat_Stencil8 + : s_textureFormat[m_textureFormat].m_fmt + , .dimension = tvd, .baseMipLevel = _baseMipLevel, .mipLevelCount = UINT8_MAX == _mipLevelCount ? WGPU_MIP_LEVEL_COUNT_UNDEFINED : _mipLevelCount, .baseArrayLayer = _baseArrayLayer, .arrayLayerCount = arrayLayerCount, - .aspect = WGPUTextureAspect_All, + .aspect = _stencil + ? WGPUTextureAspect_StencilOnly + : WGPUTextureAspect_All + , .usage = 0 | WGPUTextureUsage_TextureBinding | (_storage ? WGPUTextureUsage_StorageBinding : 0) diff --git a/src/renderer_webgpu.h b/src/renderer_webgpu.h index 6697dca7d..5c8cb0e9b 100644 --- a/src/renderer_webgpu.h +++ b/src/renderer_webgpu.h @@ -641,7 +641,7 @@ namespace wgpu { void clear(uint8_t _mip, uint8_t _numMips, uint16_t _layer, uint16_t _numLayers); WGPUSampler getSamplerState(uint32_t _samplerFlags) const; - WGPUTextureView getTextureView(uint8_t _baseMipLevel, uint8_t _mipLevelCount, bool _storage, uint16_t _baseArrayLayer = 0, uint16_t _arrayLayerCount = UINT16_MAX, bool _force2DArray = false) const; + WGPUTextureView getTextureView(uint8_t _baseMipLevel, uint8_t _mipLevelCount, bool _storage, uint16_t _baseArrayLayer = 0, uint16_t _arrayLayerCount = UINT16_MAX, bool _force2DArray = false, bool _stencil = false) const; WGPUTexture m_texture; WGPUTexture m_textureResolve;