From 912e7001bb51741db4144b46e62b222a6e24a984 Mon Sep 17 00:00:00 2001 From: MikhailGorobets Date: Sun, 25 Oct 2026 11:46:43 +0600 Subject: [PATCH 1/3] WebGPU: Correct tiered texture format support --- .../src/EngineFactoryWebGPU.cpp | 8 +- .../src/RenderDeviceWebGPUImpl.cpp | 121 ++++++++++++------ 2 files changed, 81 insertions(+), 48 deletions(-) diff --git a/Graphics/GraphicsEngineWebGPU/src/EngineFactoryWebGPU.cpp b/Graphics/GraphicsEngineWebGPU/src/EngineFactoryWebGPU.cpp index 8f8ca736e..ddbddf424 100644 --- a/Graphics/GraphicsEngineWebGPU/src/EngineFactoryWebGPU.cpp +++ b/Graphics/GraphicsEngineWebGPU/src/EngineFactoryWebGPU.cpp @@ -259,14 +259,10 @@ WebGPUDeviceWrapper CreateDeviceForAdapter(const DeviceFeatures& Features, WGPUI if (wgpuAdapterHasFeature(wgpuAdapter, WGPUFeatureName_BGRA8UnormStorage)) wgpuFeatures.push_back(WGPUFeatureName_BGRA8UnormStorage); - if (wgpuAdapterHasFeature(wgpuAdapter, WGPUFeatureName_Unorm16TextureFormats)) - wgpuFeatures.push_back(WGPUFeatureName_Unorm16TextureFormats); - - if (wgpuAdapterHasFeature(wgpuAdapter, WGPUFeatureName_TextureFormatsTier1)) - wgpuFeatures.push_back(WGPUFeatureName_TextureFormatsTier1); - if (wgpuAdapterHasFeature(wgpuAdapter, WGPUFeatureName_TextureFormatsTier2)) wgpuFeatures.push_back(WGPUFeatureName_TextureFormatsTier2); + else if (wgpuAdapterHasFeature(wgpuAdapter, WGPUFeatureName_TextureFormatsTier1)) + wgpuFeatures.push_back(WGPUFeatureName_TextureFormatsTier1); } struct CallbackUserData diff --git a/Graphics/GraphicsEngineWebGPU/src/RenderDeviceWebGPUImpl.cpp b/Graphics/GraphicsEngineWebGPU/src/RenderDeviceWebGPUImpl.cpp index 5d0ea2ab2..30eb1bced 100644 --- a/Graphics/GraphicsEngineWebGPU/src/RenderDeviceWebGPUImpl.cpp +++ b/Graphics/GraphicsEngineWebGPU/src/RenderDeviceWebGPUImpl.cpp @@ -430,9 +430,11 @@ void RenderDeviceWebGPUImpl::FindSupportedTextureFormats() constexpr BIND_FLAGS BIND_SRU = BIND_SHADER_RESOURCE | BIND_RENDER_TARGET | BIND_UNORDERED_ACCESS; constexpr BIND_FLAGS BIND_SR = BIND_SHADER_RESOURCE | BIND_RENDER_TARGET; - constexpr BIND_FLAGS BIND_S = BIND_SHADER_RESOURCE; constexpr BIND_FLAGS BIND_SU = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; - constexpr BIND_FLAGS BIND_D = BIND_DEPTH_STENCIL; + constexpr BIND_FLAGS BIND_SD = BIND_SHADER_RESOURCE | BIND_DEPTH_STENCIL; + constexpr BIND_FLAGS BIND_S = BIND_SHADER_RESOURCE; + constexpr BIND_FLAGS BIND_R = BIND_RENDER_TARGET; + constexpr BIND_FLAGS BIND_U = BIND_UNORDERED_ACCESS; SAMPLE_COUNT SupportedSampleCounts = SAMPLE_COUNT_1 | SAMPLE_COUNT_4; // We can't query supported sample counts in WebGPU @@ -466,8 +468,7 @@ void RenderDeviceWebGPUImpl::FindSupportedTextureFormats() FmtInfo.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL)) { FmtInfo.Dimensions |= - RESOURCE_DIMENSION_SUPPORT_TEX_1D | - RESOURCE_DIMENSION_SUPPORT_TEX_1D_ARRAY | + RESOURCE_DIMENSION_SUPPORT_TEX_1D | RESOURCE_DIMENSION_SUPPORT_TEX_3D; } // clang-format on @@ -475,6 +476,22 @@ void RenderDeviceWebGPUImpl::FindSupportedTextureFormats() } }; + auto UpdateTexFormatInfo = [&](std::initializer_list Formats, BIND_FLAGS BindFlags, Uint32 FmtFlags) { + for (TEXTURE_FORMAT Fmt : Formats) + { + TextureFormatInfoExt& FmtInfo = m_TextureFormatsInfo[Fmt]; + VERIFY(FmtInfo.Supported, "The format hasn't been initialized"); + + FmtInfo.BindFlags |= BindFlags; + if ((FmtFlags & FMT_FLAG_MSAA) != 0) + { + VERIFY_EXPR((FmtInfo.BindFlags & (BIND_RENDER_TARGET | BIND_DEPTH_STENCIL)) != 0 || FmtInfo.IsTypeless); + FmtInfo.SampleCounts |= SupportedSampleCounts; + } + FmtInfo.Filterable |= (FmtFlags & FMT_FLAG_FILTER) != 0; + } + }; + const bool BGRA8UnormStorageSupported = wgpuDeviceHasFeature(m_wgpuDevice, WGPUFeatureName_BGRA8UnormStorage); const bool Float32FilterableSupported = wgpuDeviceHasFeature(m_wgpuDevice, WGPUFeatureName_Float32Filterable); const bool RG11B10UfloatRenderableSupported = wgpuDeviceHasFeature(m_wgpuDevice, WGPUFeatureName_RG11B10UfloatRenderable); @@ -482,41 +499,32 @@ void RenderDeviceWebGPUImpl::FindSupportedTextureFormats() const bool TextureCompressionBCSupported = wgpuDeviceHasFeature(m_wgpuDevice, WGPUFeatureName_TextureCompressionBC); const bool TextureCompressionETC2Supported = wgpuDeviceHasFeature(m_wgpuDevice, WGPUFeatureName_TextureCompressionETC2); const bool TextureFormatsTier1Supported = wgpuDeviceHasFeature(m_wgpuDevice, WGPUFeatureName_TextureFormatsTier1); - const bool Unorm16TextureFormatsSupported = wgpuDeviceHasFeature(m_wgpuDevice, WGPUFeatureName_Unorm16TextureFormats); - - // Tier 1 enables normalized 16-bit formats without guaranteeing filtering support. - bool Norm16FilterableSupported = Unorm16TextureFormatsSupported; -#if !PLATFORM_WEB - Norm16FilterableSupported = Norm16FilterableSupported || wgpuDeviceHasFeature(m_wgpuDevice, WGPUFeatureName_Unorm16Filterable); -#endif - const bool R16UnormSupported = TextureFormatsTier1Supported || Unorm16TextureFormatsSupported; - const bool R16SnormSupported = TextureFormatsTier1Supported; // https://www.w3.org/TR/webgpu/#texture-format-caps // Color formats with 8-bits per channel - SetTexFormatInfo({TEX_FORMAT_R8_TYPELESS, TEX_FORMAT_R8_UNORM}, TextureFormatsTier1Supported ? BIND_SRU : BIND_SR, FMT_FLAG_FILTER | FMT_FLAG_MSAA); - SetTexFormatInfo({TEX_FORMAT_R8_SNORM}, TextureFormatsTier1Supported ? BIND_SRU : BIND_S, TextureFormatsTier1Supported ? FMT_FLAG_FILTER | FMT_FLAG_MSAA : FMT_FLAG_FILTER); - SetTexFormatInfo({TEX_FORMAT_R8_UINT, TEX_FORMAT_R8_SINT}, TextureFormatsTier1Supported ? BIND_SRU : BIND_SR, FMT_FLAG_MSAA); + SetTexFormatInfo({TEX_FORMAT_R8_TYPELESS, TEX_FORMAT_R8_UNORM}, BIND_SR, FMT_FLAG_FILTER | FMT_FLAG_MSAA); + SetTexFormatInfo({TEX_FORMAT_R8_SNORM}, BIND_S, FMT_FLAG_FILTER); + SetTexFormatInfo({TEX_FORMAT_R8_UINT, TEX_FORMAT_R8_SINT}, BIND_SR, FMT_FLAG_MSAA); - SetTexFormatInfo({TEX_FORMAT_RG8_TYPELESS, TEX_FORMAT_RG8_UNORM}, TextureFormatsTier1Supported ? BIND_SRU : BIND_SR, FMT_FLAG_FILTER | FMT_FLAG_MSAA); - SetTexFormatInfo({TEX_FORMAT_RG8_SNORM}, TextureFormatsTier1Supported ? BIND_SRU : BIND_S, TextureFormatsTier1Supported ? FMT_FLAG_FILTER | FMT_FLAG_MSAA : FMT_FLAG_FILTER); - SetTexFormatInfo({TEX_FORMAT_RG8_UINT, TEX_FORMAT_RG8_SINT}, TextureFormatsTier1Supported ? BIND_SRU : BIND_SR, FMT_FLAG_MSAA); + SetTexFormatInfo({TEX_FORMAT_RG8_TYPELESS, TEX_FORMAT_RG8_UNORM}, BIND_SR, FMT_FLAG_FILTER | FMT_FLAG_MSAA); + SetTexFormatInfo({TEX_FORMAT_RG8_SNORM}, BIND_S, FMT_FLAG_FILTER); + SetTexFormatInfo({TEX_FORMAT_RG8_UINT, TEX_FORMAT_RG8_SINT}, BIND_SR, FMT_FLAG_MSAA); SetTexFormatInfo({TEX_FORMAT_RGBA8_TYPELESS, TEX_FORMAT_RGBA8_UNORM}, BIND_SRU, FMT_FLAG_FILTER | FMT_FLAG_MSAA); SetTexFormatInfo({TEX_FORMAT_RGBA8_UNORM_SRGB}, BIND_SR, FMT_FLAG_FILTER | FMT_FLAG_MSAA); - SetTexFormatInfo({TEX_FORMAT_RGBA8_SNORM}, TextureFormatsTier1Supported ? BIND_SRU : BIND_SU, TextureFormatsTier1Supported ? FMT_FLAG_FILTER | FMT_FLAG_MSAA : FMT_FLAG_FILTER); + SetTexFormatInfo({TEX_FORMAT_RGBA8_SNORM}, BIND_SU, FMT_FLAG_FILTER); SetTexFormatInfo({TEX_FORMAT_RGBA8_UINT, TEX_FORMAT_RGBA8_SINT}, BIND_SRU, FMT_FLAG_MSAA); SetTexFormatInfo({TEX_FORMAT_BGRA8_TYPELESS, TEX_FORMAT_BGRA8_UNORM}, BGRA8UnormStorageSupported ? BIND_SRU : BIND_SR, FMT_FLAG_FILTER | FMT_FLAG_MSAA); SetTexFormatInfo({TEX_FORMAT_BGRA8_UNORM_SRGB}, BIND_SR, FMT_FLAG_FILTER | FMT_FLAG_MSAA); // Color formats with 16-bits per channel - SetTexFormatInfo({TEX_FORMAT_R16_UINT, TEX_FORMAT_R16_SINT}, TextureFormatsTier1Supported ? BIND_SRU : BIND_SR, FMT_FLAG_MSAA); - SetTexFormatInfo({TEX_FORMAT_R16_FLOAT, TEX_FORMAT_R16_TYPELESS}, TextureFormatsTier1Supported ? BIND_SRU : BIND_SR, FMT_FLAG_FILTER | FMT_FLAG_MSAA); + SetTexFormatInfo({TEX_FORMAT_R16_UINT, TEX_FORMAT_R16_SINT}, BIND_SR, FMT_FLAG_MSAA); + SetTexFormatInfo({TEX_FORMAT_R16_FLOAT, TEX_FORMAT_R16_TYPELESS}, BIND_SR, FMT_FLAG_FILTER | FMT_FLAG_MSAA); - SetTexFormatInfo({TEX_FORMAT_RG16_UINT, TEX_FORMAT_RG16_SINT}, TextureFormatsTier1Supported ? BIND_SRU : BIND_SR, FMT_FLAG_MSAA); - SetTexFormatInfo({TEX_FORMAT_RG16_FLOAT, TEX_FORMAT_RG16_TYPELESS}, TextureFormatsTier1Supported ? BIND_SRU : BIND_SR, FMT_FLAG_FILTER | FMT_FLAG_MSAA); + SetTexFormatInfo({TEX_FORMAT_RG16_UINT, TEX_FORMAT_RG16_SINT}, BIND_SR, FMT_FLAG_MSAA); + SetTexFormatInfo({TEX_FORMAT_RG16_FLOAT, TEX_FORMAT_RG16_TYPELESS}, BIND_SR, FMT_FLAG_FILTER | FMT_FLAG_MSAA); SetTexFormatInfo({TEX_FORMAT_RGBA16_UINT, TEX_FORMAT_RGBA16_SINT}, BIND_SRU, FMT_FLAG_MSAA); SetTexFormatInfo({TEX_FORMAT_RGBA16_FLOAT, TEX_FORMAT_RGBA16_TYPELESS}, BIND_SRU, FMT_FLAG_FILTER | FMT_FLAG_MSAA); @@ -532,17 +540,17 @@ void RenderDeviceWebGPUImpl::FindSupportedTextureFormats() SetTexFormatInfo({TEX_FORMAT_RGBA32_FLOAT}, BIND_SRU, Float32FilterableSupported ? FMT_FLAG_FILTER : FMT_FLAG_NONE); // Color formats with mixed width - SetTexFormatInfo({TEX_FORMAT_RGB10A2_TYPELESS, TEX_FORMAT_RGB10A2_UNORM}, TextureFormatsTier1Supported ? BIND_SRU : BIND_SR, FMT_FLAG_FILTER | FMT_FLAG_MSAA); - SetTexFormatInfo({TEX_FORMAT_RGB10A2_UINT}, TextureFormatsTier1Supported ? BIND_SRU : BIND_SR, FMT_FLAG_MSAA); + SetTexFormatInfo({TEX_FORMAT_RGB10A2_TYPELESS, TEX_FORMAT_RGB10A2_UNORM}, BIND_SR, FMT_FLAG_FILTER | FMT_FLAG_MSAA); + SetTexFormatInfo({TEX_FORMAT_RGB10A2_UINT}, BIND_SR, FMT_FLAG_MSAA); - SetTexFormatInfo({TEX_FORMAT_R11G11B10_FLOAT}, TextureFormatsTier1Supported ? BIND_SRU : (RG11B10UfloatRenderableSupported ? BIND_SR : BIND_S), RG11B10UfloatRenderableSupported ? FMT_FLAG_FILTER | FMT_FLAG_MSAA : FMT_FLAG_FILTER); + SetTexFormatInfo({TEX_FORMAT_R11G11B10_FLOAT}, RG11B10UfloatRenderableSupported ? BIND_SR : BIND_S, RG11B10UfloatRenderableSupported ? FMT_FLAG_FILTER | FMT_FLAG_MSAA : FMT_FLAG_FILTER); // Depth-stencil formats - SetTexFormatInfo({TEX_FORMAT_D16_UNORM}, BIND_D, FMT_FLAG_FILTER | FMT_FLAG_MSAA); - SetTexFormatInfo({TEX_FORMAT_D24_UNORM_S8_UINT}, BIND_D, FMT_FLAG_FILTER | FMT_FLAG_MSAA); - SetTexFormatInfo({TEX_FORMAT_D32_FLOAT}, BIND_D, FMT_FLAG_FILTER | FMT_FLAG_MSAA); + SetTexFormatInfo({TEX_FORMAT_D16_UNORM}, BIND_SD, FMT_FLAG_FILTER | FMT_FLAG_MSAA); + SetTexFormatInfo({TEX_FORMAT_D24_UNORM_S8_UINT}, BIND_SD, FMT_FLAG_FILTER | FMT_FLAG_MSAA); + SetTexFormatInfo({TEX_FORMAT_D32_FLOAT}, BIND_SD, FMT_FLAG_FILTER | FMT_FLAG_MSAA); if (Depth32FloatStencil8Supported) - SetTexFormatInfo({TEX_FORMAT_D32_FLOAT_S8X24_UINT}, BIND_D, FMT_FLAG_FILTER | FMT_FLAG_MSAA); + SetTexFormatInfo({TEX_FORMAT_D32_FLOAT_S8X24_UINT}, BIND_SD, FMT_FLAG_FILTER | FMT_FLAG_MSAA); // Packed formats SetTexFormatInfo({TEX_FORMAT_RGB9E5_SHAREDEXP}, BIND_S, FMT_FLAG_FILTER); @@ -573,18 +581,47 @@ void RenderDeviceWebGPUImpl::FindSupportedTextureFormats() BIND_S, FMT_FLAG_FILTER); } - if (R16UnormSupported) - { - SetTexFormatInfo({TEX_FORMAT_R16_UNORM}, TextureFormatsTier1Supported ? BIND_SRU : BIND_SR, Norm16FilterableSupported ? FMT_FLAG_FILTER | FMT_FLAG_MSAA : FMT_FLAG_MSAA); - SetTexFormatInfo({TEX_FORMAT_RG16_UNORM}, TextureFormatsTier1Supported ? BIND_SRU : BIND_SR, Norm16FilterableSupported ? FMT_FLAG_FILTER | FMT_FLAG_MSAA : FMT_FLAG_MSAA); - SetTexFormatInfo({TEX_FORMAT_RGBA16_UNORM}, TextureFormatsTier1Supported ? BIND_SRU : BIND_SR, Norm16FilterableSupported ? FMT_FLAG_FILTER | FMT_FLAG_MSAA : FMT_FLAG_MSAA); - } - - if (R16SnormSupported) + if (TextureFormatsTier1Supported) { - SetTexFormatInfo({TEX_FORMAT_R16_SNORM}, BIND_SRU, Norm16FilterableSupported ? FMT_FLAG_FILTER | FMT_FLAG_MSAA : FMT_FLAG_MSAA); - SetTexFormatInfo({TEX_FORMAT_RG16_SNORM}, BIND_SRU, Norm16FilterableSupported ? FMT_FLAG_FILTER | FMT_FLAG_MSAA : FMT_FLAG_MSAA); - SetTexFormatInfo({TEX_FORMAT_RGBA16_SNORM}, BIND_SRU, Norm16FilterableSupported ? FMT_FLAG_FILTER | FMT_FLAG_MSAA : FMT_FLAG_MSAA); + SetTexFormatInfo({TEX_FORMAT_R16_UNORM, + TEX_FORMAT_R16_SNORM, + TEX_FORMAT_RG16_UNORM, + TEX_FORMAT_RG16_SNORM, + TEX_FORMAT_RGBA16_UNORM, + TEX_FORMAT_RGBA16_SNORM}, + BIND_SRU, FMT_FLAG_MSAA); + + UpdateTexFormatInfo({TEX_FORMAT_R8_SNORM, + TEX_FORMAT_RG8_SNORM, + TEX_FORMAT_RGBA8_SNORM}, + BIND_R, FMT_FLAG_MSAA); + + UpdateTexFormatInfo({TEX_FORMAT_R8_TYPELESS, + TEX_FORMAT_R8_UNORM, + TEX_FORMAT_R8_SNORM, + TEX_FORMAT_R8_UINT, + TEX_FORMAT_R8_SINT, + TEX_FORMAT_RG8_TYPELESS, + TEX_FORMAT_RG8_UNORM, + TEX_FORMAT_RG8_SNORM, + TEX_FORMAT_RG8_UINT, + TEX_FORMAT_RG8_SINT, + TEX_FORMAT_R16_TYPELESS, + TEX_FORMAT_R16_UINT, + TEX_FORMAT_R16_SINT, + TEX_FORMAT_R16_FLOAT, + TEX_FORMAT_R16_UNORM, + TEX_FORMAT_RG16_TYPELESS, + TEX_FORMAT_RG16_UINT, + TEX_FORMAT_RG16_SINT, + TEX_FORMAT_RG16_FLOAT, + TEX_FORMAT_RG16_UNORM, + TEX_FORMAT_RGBA16_UNORM, + TEX_FORMAT_RGB10A2_TYPELESS, + TEX_FORMAT_RGB10A2_UNORM, + TEX_FORMAT_RGB10A2_UINT, + TEX_FORMAT_R11G11B10_FLOAT}, + BIND_U, FMT_FLAG_NONE); } if (TextureCompressionETC2Supported) From 8ce44f5af8606c54c5ba931eaceec3a1a76387ae Mon Sep 17 00:00:00 2001 From: MikhailGorobets Date: Sun, 25 Oct 2026 11:46:48 +0600 Subject: [PATCH 2/3] WebGPU: Support extended storage image formats --- Graphics/ShaderTools/src/SPIRVUtils.cpp | 17 +++++- .../ShaderTools/src/WGSLShaderResources.cpp | 60 +++++++++++++------ .../src/ShaderTools/SPIRVUtilsTest.cpp | 2 + 3 files changed, 58 insertions(+), 21 deletions(-) diff --git a/Graphics/ShaderTools/src/SPIRVUtils.cpp b/Graphics/ShaderTools/src/SPIRVUtils.cpp index 619c80ecf..a269c52a6 100644 --- a/Graphics/ShaderTools/src/SPIRVUtils.cpp +++ b/Graphics/ShaderTools/src/SPIRVUtils.cpp @@ -108,10 +108,11 @@ std::vector PatchImageFormats(const std::vector& diligent_spirv_cross::ShaderResources resources = Compiler.get_shader_resources(); + constexpr size_t SPIRVHeaderSize = 5; std::unordered_map ImageTypeIdToFormat; + bool HasStorageImageExtendedFormatsCapability = false; // Skip the header and walk instruction boundaries: operands may have the same // low bits as OpTypeImage and must not be interpreted as instruction words. - constexpr size_t SPIRVHeaderSize = 5; for (size_t i = SPIRVHeaderSize; i < SPIRV.size();) { const uint32_t WordCount = SPIRV[i] >> 16; @@ -120,6 +121,10 @@ std::vector PatchImageFormats(const std::vector& LOG_ERROR_MESSAGE("Invalid SPIR-V instruction size at word ", i); return {}; } + // OpCapability + // 0 1 + // | OpCode | Capability | + constexpr uint32_t CapabilityOffset = 1; // OpTypeImage // 0 1 2 3 4 5 6 7 8 9 @@ -127,7 +132,9 @@ std::vector PatchImageFormats(const std::vector& constexpr uint32_t ImageFormatOffset = 8; const uint32_t OpCode = SPIRV[i] & 0xFFFF; - if (OpCode == spv::OpTypeImage && WordCount > ImageFormatOffset) + if (OpCode == spv::OpCapability && WordCount > CapabilityOffset) + HasStorageImageExtendedFormatsCapability |= SPIRV[i + CapabilityOffset] == spv::CapabilityStorageImageExtendedFormats; + else if (OpCode == spv::OpTypeImage && WordCount > ImageFormatOffset) { const uint32_t ImageTypeId = SPIRV[i + 1]; ImageTypeIdToFormat[ImageTypeId] = i + ImageFormatOffset; @@ -169,6 +176,12 @@ std::vector PatchImageFormats(const std::vector& } } + if (!HasStorageImageExtendedFormatsCapability) + { + constexpr uint32_t WordCount = 2; + PatchedSPIRV.insert(PatchedSPIRV.begin() + SPIRVHeaderSize, {(WordCount << 16) | spv::OpCapability, spv::CapabilityStorageImageExtendedFormats}); + } + return PatchedSPIRV; } diff --git a/Graphics/ShaderTools/src/WGSLShaderResources.cpp b/Graphics/ShaderTools/src/WGSLShaderResources.cpp index f49846cd1..27b7352eb 100644 --- a/Graphics/ShaderTools/src/WGSLShaderResources.cpp +++ b/Graphics/ShaderTools/src/WGSLShaderResources.cpp @@ -259,25 +259,47 @@ TEXTURE_FORMAT TintTexelFormatToTextureFormat(const tint::inspector::ResourceBin switch (TintBinding.image_format) { // clang-format off - case TintTexelFormat::kBgra8Unorm: return TEX_FORMAT_BGRA8_UNORM; - case TintTexelFormat::kRgba8Unorm: return TEX_FORMAT_RGBA8_UNORM; - case TintTexelFormat::kRgba8Snorm: return TEX_FORMAT_RGBA8_SNORM; - case TintTexelFormat::kRgba8Uint: return TEX_FORMAT_RGBA8_UINT; - case TintTexelFormat::kRgba8Sint: return TEX_FORMAT_RGBA8_SINT; - case TintTexelFormat::kRgba16Uint: return TEX_FORMAT_RGBA16_UINT; - case TintTexelFormat::kRgba16Sint: return TEX_FORMAT_RGBA16_SINT; - case TintTexelFormat::kRgba16Float: return TEX_FORMAT_RGBA16_FLOAT; - case TintTexelFormat::kR32Uint: return TEX_FORMAT_R32_UINT; - case TintTexelFormat::kR32Sint: return TEX_FORMAT_R32_SINT; - case TintTexelFormat::kR32Float: return TEX_FORMAT_R32_FLOAT; - case TintTexelFormat::kRg32Uint: return TEX_FORMAT_RG32_UINT; - case TintTexelFormat::kRg32Sint: return TEX_FORMAT_RG32_SINT; - case TintTexelFormat::kRg32Float: return TEX_FORMAT_RG32_FLOAT; - case TintTexelFormat::kRgba32Uint: return TEX_FORMAT_RGBA32_UINT; - case TintTexelFormat::kRgba32Sint: return TEX_FORMAT_RGBA32_SINT; - case TintTexelFormat::kRgba32Float: return TEX_FORMAT_RGBA32_FLOAT; - case TintTexelFormat::kR8Unorm: return TEX_FORMAT_R8_UNORM; - case TintTexelFormat::kNone: return TEX_FORMAT_UNKNOWN; + case TintTexelFormat::kBgra8Unorm: return TEX_FORMAT_BGRA8_UNORM; + case TintTexelFormat::kRgba8Unorm: return TEX_FORMAT_RGBA8_UNORM; + case TintTexelFormat::kRgba8Snorm: return TEX_FORMAT_RGBA8_SNORM; + case TintTexelFormat::kRgba8Uint: return TEX_FORMAT_RGBA8_UINT; + case TintTexelFormat::kRgba8Sint: return TEX_FORMAT_RGBA8_SINT; + case TintTexelFormat::kRgba16Uint: return TEX_FORMAT_RGBA16_UINT; + case TintTexelFormat::kRgba16Sint: return TEX_FORMAT_RGBA16_SINT; + case TintTexelFormat::kRgba16Float: return TEX_FORMAT_RGBA16_FLOAT; + case TintTexelFormat::kRgba16Unorm: return TEX_FORMAT_RGBA16_UNORM; + case TintTexelFormat::kRgba16Snorm: return TEX_FORMAT_RGBA16_SNORM; + case TintTexelFormat::kR32Uint: return TEX_FORMAT_R32_UINT; + case TintTexelFormat::kR32Sint: return TEX_FORMAT_R32_SINT; + case TintTexelFormat::kR32Float: return TEX_FORMAT_R32_FLOAT; + case TintTexelFormat::kRg32Uint: return TEX_FORMAT_RG32_UINT; + case TintTexelFormat::kRg32Sint: return TEX_FORMAT_RG32_SINT; + case TintTexelFormat::kRg32Float: return TEX_FORMAT_RG32_FLOAT; + case TintTexelFormat::kRgba32Uint: return TEX_FORMAT_RGBA32_UINT; + case TintTexelFormat::kRgba32Sint: return TEX_FORMAT_RGBA32_SINT; + case TintTexelFormat::kRgba32Float: return TEX_FORMAT_RGBA32_FLOAT; + case TintTexelFormat::kR8Unorm: return TEX_FORMAT_R8_UNORM; + case TintTexelFormat::kR8Snorm: return TEX_FORMAT_R8_SNORM; + case TintTexelFormat::kR8Uint: return TEX_FORMAT_R8_UINT; + case TintTexelFormat::kR8Sint: return TEX_FORMAT_R8_SINT; + case TintTexelFormat::kRg8Unorm: return TEX_FORMAT_RG8_UNORM; + case TintTexelFormat::kRg8Snorm: return TEX_FORMAT_RG8_SNORM; + case TintTexelFormat::kRg8Uint: return TEX_FORMAT_RG8_UINT; + case TintTexelFormat::kRg8Sint: return TEX_FORMAT_RG8_SINT; + case TintTexelFormat::kR16Uint: return TEX_FORMAT_R16_UINT; + case TintTexelFormat::kR16Sint: return TEX_FORMAT_R16_SINT; + case TintTexelFormat::kR16Float: return TEX_FORMAT_R16_FLOAT; + case TintTexelFormat::kR16Unorm: return TEX_FORMAT_R16_UNORM; + case TintTexelFormat::kR16Snorm: return TEX_FORMAT_R16_SNORM; + case TintTexelFormat::kRg16Uint: return TEX_FORMAT_RG16_UINT; + case TintTexelFormat::kRg16Sint: return TEX_FORMAT_RG16_SINT; + case TintTexelFormat::kRg16Float: return TEX_FORMAT_RG16_FLOAT; + case TintTexelFormat::kRg16Unorm: return TEX_FORMAT_RG16_UNORM; + case TintTexelFormat::kRg16Snorm: return TEX_FORMAT_RG16_SNORM; + case TintTexelFormat::kRg11B10Ufloat: return TEX_FORMAT_R11G11B10_FLOAT; + case TintTexelFormat::kRgb10A2Uint: return TEX_FORMAT_RGB10A2_UINT; + case TintTexelFormat::kRgb10A2Unorm: return TEX_FORMAT_RGB10A2_UNORM; + case TintTexelFormat::kNone: return TEX_FORMAT_UNKNOWN; // clang-format on default: UNEXPECTED("Unexpected texel format"); diff --git a/Tests/DiligentCoreTest/src/ShaderTools/SPIRVUtilsTest.cpp b/Tests/DiligentCoreTest/src/ShaderTools/SPIRVUtilsTest.cpp index 3882c89bc..9e8980c0f 100644 --- a/Tests/DiligentCoreTest/src/ShaderTools/SPIRVUtilsTest.cpp +++ b/Tests/DiligentCoreTest/src/ShaderTools/SPIRVUtilsTest.cpp @@ -72,6 +72,8 @@ TEST(SPIRVUtils, PatchImageFormatsIgnoresInstructionOperands) std::vector ExpectedSPIRV = SPIRV; ExpectedSPIRV[ImageFormatWord] = 1; // ImageFormatRgba32f + ExpectedSPIRV.insert(ExpectedSPIRV.begin() + 5, + {0x00020011, 49}); // OpCapability StorageImageExtendedFormats std::unordered_map ImageFormats; ImageFormats.emplace("Tex", TEX_FORMAT_RGBA32_FLOAT); From 1adc339675d467cf384064b2d65b981357488e7f Mon Sep 17 00:00:00 2001 From: MikhailGorobets Date: Wed, 4 Feb 2026 03:53:02 +0600 Subject: [PATCH 3/3] WebGPU: Replaced std::vector with std::unique_ptr in upload and dynamic memory managers to avoid zero-initialization overhead --- .../include/DynamicMemoryManagerWebGPU.hpp | 7 ++++--- .../include/UploadMemoryManagerWebGPU.hpp | 8 +++++--- .../src/DynamicMemoryManagerWebGPU.cpp | 4 ++-- .../src/UploadMemoryManagerWebGPU.cpp | 14 ++++++++++---- 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/Graphics/GraphicsEngineWebGPU/include/DynamicMemoryManagerWebGPU.hpp b/Graphics/GraphicsEngineWebGPU/include/DynamicMemoryManagerWebGPU.hpp index 826b37b8d..f79058054 100644 --- a/Graphics/GraphicsEngineWebGPU/include/DynamicMemoryManagerWebGPU.hpp +++ b/Graphics/GraphicsEngineWebGPU/include/DynamicMemoryManagerWebGPU.hpp @@ -30,6 +30,7 @@ /// Declaration of Diligent::DynamicMemoryManagerWebGPU class #include +#include #include #include "WebGPUObjectWrappers.hpp" @@ -111,9 +112,9 @@ class DynamicMemoryManagerWebGPU size_t m_CurrentOffset = 0; WebGPUBufferWrapper m_wgpuBuffer; - std::mutex m_AvailablePagesMtx; - std::vector m_AvailablePages; - std::vector m_MappedData; + std::mutex m_AvailablePagesMtx; + std::vector m_AvailablePages; + std::unique_ptr m_MappedData; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineWebGPU/include/UploadMemoryManagerWebGPU.hpp b/Graphics/GraphicsEngineWebGPU/include/UploadMemoryManagerWebGPU.hpp index b7ea082d7..29dc09ddf 100644 --- a/Graphics/GraphicsEngineWebGPU/include/UploadMemoryManagerWebGPU.hpp +++ b/Graphics/GraphicsEngineWebGPU/include/UploadMemoryManagerWebGPU.hpp @@ -30,8 +30,9 @@ /// Declaration of Diligent::UploadMemoryManagerWebGPU class #include -#include +#include #include +#include #include "WebGPUObjectWrappers.hpp" #include "BasicTypes.h" @@ -83,13 +84,14 @@ class UploadMemoryManagerWebGPU size_t GetSize() const { - return m_Data.size(); + return m_DataSize; } private: UploadMemoryManagerWebGPU* m_pMgr = nullptr; WebGPUBufferWrapper m_wgpuBuffer; - std::vector m_Data; + std::unique_ptr m_Data; + size_t m_DataSize = 0; size_t m_CurrOffset = 0; }; diff --git a/Graphics/GraphicsEngineWebGPU/src/DynamicMemoryManagerWebGPU.cpp b/Graphics/GraphicsEngineWebGPU/src/DynamicMemoryManagerWebGPU.cpp index e970efcd5..b5bef4e16 100644 --- a/Graphics/GraphicsEngineWebGPU/src/DynamicMemoryManagerWebGPU.cpp +++ b/Graphics/GraphicsEngineWebGPU/src/DynamicMemoryManagerWebGPU.cpp @@ -119,7 +119,8 @@ void DynamicMemoryManagerWebGPU::Page::Recycle() DynamicMemoryManagerWebGPU::DynamicMemoryManagerWebGPU(WGPUDevice wgpuDevice, size_t PageSize, size_t BufferSize) : m_PageSize{PageSize}, m_BufferSize{BufferSize}, - m_CurrentOffset{0} + m_CurrentOffset{0}, + m_MappedData{std::make_unique_for_overwrite(BufferSize)} { WGPUBufferDescriptor wgpuBufferDesc{}; wgpuBufferDesc.label = GetWGPUStringView("Dynamic buffer"); @@ -133,7 +134,6 @@ DynamicMemoryManagerWebGPU::DynamicMemoryManagerWebGPU(WGPUDevice wgpuDevice, si WGPUBufferUsage_Index | WGPUBufferUsage_Indirect; m_wgpuBuffer.Reset(wgpuDeviceCreateBuffer(wgpuDevice, &wgpuBufferDesc)); - m_MappedData.resize(BufferSize); LOG_INFO_MESSAGE("Created dynamic buffer: ", BufferSize >> 10, " KB"); } diff --git a/Graphics/GraphicsEngineWebGPU/src/UploadMemoryManagerWebGPU.cpp b/Graphics/GraphicsEngineWebGPU/src/UploadMemoryManagerWebGPU.cpp index e43e7e206..085e22ae4 100644 --- a/Graphics/GraphicsEngineWebGPU/src/UploadMemoryManagerWebGPU.cpp +++ b/Graphics/GraphicsEngineWebGPU/src/UploadMemoryManagerWebGPU.cpp @@ -36,7 +36,8 @@ namespace Diligent UploadMemoryManagerWebGPU::Page::Page(UploadMemoryManagerWebGPU& Mgr, size_t Size) : m_pMgr{&Mgr}, - m_Data(Size) + m_Data{std::make_unique_for_overwrite(Size)}, + m_DataSize{Size} { WGPUBufferDescriptor wgpuBufferDesc{}; wgpuBufferDesc.label = GetWGPUStringView("Upload memory page"); @@ -58,10 +59,13 @@ UploadMemoryManagerWebGPU::Page::Page(Page&& RHS) noexcept : m_pMgr{RHS.m_pMgr}, m_wgpuBuffer{std::move(RHS.m_wgpuBuffer)}, m_Data{std::move(RHS.m_Data)}, + m_DataSize{RHS.m_DataSize}, m_CurrOffset{RHS.m_CurrOffset} // clang-format on { - RHS = Page{}; + RHS.m_pMgr = nullptr; + RHS.m_DataSize = 0; + RHS.m_CurrOffset = 0; } UploadMemoryManagerWebGPU::Page& UploadMemoryManagerWebGPU::Page::operator=(Page&& RHS) noexcept @@ -72,9 +76,11 @@ UploadMemoryManagerWebGPU::Page& UploadMemoryManagerWebGPU::Page::operator=(Page m_pMgr = RHS.m_pMgr; m_wgpuBuffer = std::move(RHS.m_wgpuBuffer); m_Data = std::move(RHS.m_Data); + m_DataSize = RHS.m_DataSize; m_CurrOffset = RHS.m_CurrOffset; RHS.m_pMgr = nullptr; + RHS.m_DataSize = 0; RHS.m_CurrOffset = 0; return *this; @@ -91,7 +97,7 @@ UploadMemoryManagerWebGPU::Allocation UploadMemoryManagerWebGPU::Page::Allocate( Allocation Alloc; Alloc.Offset = AlignUp(m_CurrOffset, Alignment); Alloc.Size = AlignUp(Size, Alignment); - if (Alloc.Offset + Alloc.Size <= m_Data.size()) + if (Alloc.Offset + Alloc.Size <= m_DataSize) { Alloc.wgpuBuffer = m_wgpuBuffer; Alloc.pData = &m_Data[Alloc.Offset]; @@ -105,7 +111,7 @@ void UploadMemoryManagerWebGPU::Page::FlushWrites(WGPUQueue wgpuQueue) { if (m_CurrOffset > 0) { - wgpuQueueWriteBuffer(wgpuQueue, m_wgpuBuffer, 0, m_Data.data(), m_CurrOffset); + wgpuQueueWriteBuffer(wgpuQueue, m_wgpuBuffer, 0, m_Data.get(), m_CurrOffset); } }