diff --git a/src/dawn/native/CommandEncoder.cpp b/src/dawn/native/CommandEncoder.cpp index 33961bfba9..823e04729d 100644 --- a/src/dawn/native/CommandEncoder.cpp +++ b/src/dawn/native/CommandEncoder.cpp @@ -214,6 +214,10 @@ namespace dawn::native { "The resolve target %s format (%s) does not match the color attachment %s format " "(%s).", resolveTarget, resolveTargetFormat, attachment, attachment->GetFormat().format); + DAWN_INVALID_IF( + !resolveTarget->GetFormat().supportsResolveTarget, + "The resolve target %s format (%s) does not support being used as resolve target.", + resolveTarget, resolveTargetFormat); return {}; } diff --git a/src/dawn/native/Format.cpp b/src/dawn/native/Format.cpp index 403291d1cf..bad5643ea4 100644 --- a/src/dawn/native/Format.cpp +++ b/src/dawn/native/Format.cpp @@ -158,8 +158,8 @@ namespace dawn::native { auto AddColorFormat = [&AddFormat](wgpu::TextureFormat format, bool renderable, bool supportsStorageUsage, - bool supportsMultisample, uint32_t byteSize, SampleTypeBit sampleTypes, - uint8_t componentCount, + bool supportsMultisample, bool supportsResolveTarget, uint32_t byteSize, + SampleTypeBit sampleTypes, uint8_t componentCount, wgpu::TextureFormat baseFormat = wgpu::TextureFormat::Undefined) { Format internalFormat; internalFormat.format = format; @@ -168,6 +168,7 @@ namespace dawn::native { internalFormat.isSupported = true; internalFormat.supportsStorageUsage = supportsStorageUsage; internalFormat.supportsMultisample = supportsMultisample; + internalFormat.supportsResolveTarget = supportsResolveTarget; internalFormat.aspects = Aspect::Color; internalFormat.componentCount = componentCount; @@ -216,6 +217,7 @@ namespace dawn::native { internalFormat.isSupported = isSupported; internalFormat.supportsStorageUsage = false; internalFormat.supportsMultisample = true; + internalFormat.supportsResolveTarget = false; internalFormat.aspects = Aspect::Depth; internalFormat.componentCount = 1; @@ -246,6 +248,7 @@ namespace dawn::native { internalFormat.isSupported = isSupported; internalFormat.supportsStorageUsage = false; internalFormat.supportsMultisample = true; + internalFormat.supportsResolveTarget = false; internalFormat.aspects = Aspect::Stencil; internalFormat.componentCount = 1; internalFormat.baseFormat = baseFormat; @@ -278,6 +281,7 @@ namespace dawn::native { internalFormat.isSupported = isSupported; internalFormat.supportsStorageUsage = false; internalFormat.supportsMultisample = false; + internalFormat.supportsResolveTarget = false; internalFormat.aspects = Aspect::Color; internalFormat.componentCount = componentCount; @@ -311,6 +315,7 @@ namespace dawn::native { internalFormat.isSupported = isSupported; internalFormat.supportsStorageUsage = false; internalFormat.supportsMultisample = supportsMultisample; + internalFormat.supportsResolveTarget = false; internalFormat.aspects = aspects; internalFormat.componentCount = componentCount; @@ -332,51 +337,51 @@ namespace dawn::native { // clang-format off // 1 byte color formats - AddColorFormat(wgpu::TextureFormat::R8Unorm, true, false, true, 1, kAnyFloat, 1); - AddColorFormat(wgpu::TextureFormat::R8Snorm, false, false, true, 1, kAnyFloat, 1); - AddColorFormat(wgpu::TextureFormat::R8Uint, true, false, true, 1, SampleTypeBit::Uint, 1); - AddColorFormat(wgpu::TextureFormat::R8Sint, true, false, true, 1, SampleTypeBit::Sint, 1); + AddColorFormat(wgpu::TextureFormat::R8Unorm, true, false, true, true, 1, kAnyFloat, 1); + AddColorFormat(wgpu::TextureFormat::R8Snorm, false, false, true, false, 1, kAnyFloat, 1); + AddColorFormat(wgpu::TextureFormat::R8Uint, true, false, true, false, 1, SampleTypeBit::Uint, 1); + AddColorFormat(wgpu::TextureFormat::R8Sint, true, false, true, false, 1, SampleTypeBit::Sint, 1); // 2 bytes color formats - AddColorFormat(wgpu::TextureFormat::R16Uint, true, false, true, 2, SampleTypeBit::Uint, 1); - AddColorFormat(wgpu::TextureFormat::R16Sint, true, false, true, 2, SampleTypeBit::Sint, 1); - AddColorFormat(wgpu::TextureFormat::R16Float, true, false, true, 2, kAnyFloat, 1); - AddColorFormat(wgpu::TextureFormat::RG8Unorm, true, false, true, 2, kAnyFloat, 2); - AddColorFormat(wgpu::TextureFormat::RG8Snorm, false, false, true, 2, kAnyFloat, 2); - AddColorFormat(wgpu::TextureFormat::RG8Uint, true, false, true, 2, SampleTypeBit::Uint, 2); - AddColorFormat(wgpu::TextureFormat::RG8Sint, true, false, true, 2, SampleTypeBit::Sint, 2); + AddColorFormat(wgpu::TextureFormat::R16Uint, true, false, true, false, 2, SampleTypeBit::Uint, 1); + AddColorFormat(wgpu::TextureFormat::R16Sint, true, false, true, false, 2, SampleTypeBit::Sint, 1); + AddColorFormat(wgpu::TextureFormat::R16Float, true, false, true, true, 2, kAnyFloat, 1); + AddColorFormat(wgpu::TextureFormat::RG8Unorm, true, false, true, true, 2, kAnyFloat, 2); + AddColorFormat(wgpu::TextureFormat::RG8Snorm, false, false, true, false, 2, kAnyFloat, 2); + AddColorFormat(wgpu::TextureFormat::RG8Uint, true, false, true, false, 2, SampleTypeBit::Uint, 2); + AddColorFormat(wgpu::TextureFormat::RG8Sint, true, false, true, false, 2, SampleTypeBit::Sint, 2); // 4 bytes color formats - AddColorFormat(wgpu::TextureFormat::R32Uint, true, true, false, 4, SampleTypeBit::Uint, 1); - AddColorFormat(wgpu::TextureFormat::R32Sint, true, true, false, 4, SampleTypeBit::Sint, 1); - AddColorFormat(wgpu::TextureFormat::R32Float, true, true, true, 4, SampleTypeBit::UnfilterableFloat, 1); - AddColorFormat(wgpu::TextureFormat::RG16Uint, true, false, true, 4, SampleTypeBit::Uint, 2); - AddColorFormat(wgpu::TextureFormat::RG16Sint, true, false, true, 4, SampleTypeBit::Sint, 2); - AddColorFormat(wgpu::TextureFormat::RG16Float, true, false, true, 4, kAnyFloat, 2); - AddColorFormat(wgpu::TextureFormat::RGBA8Unorm, true, true, true, 4, kAnyFloat, 4); - AddColorFormat(wgpu::TextureFormat::RGBA8UnormSrgb, true, false, true, 4, kAnyFloat, 4, wgpu::TextureFormat::RGBA8Unorm); - AddColorFormat(wgpu::TextureFormat::RGBA8Snorm, false, true, true, 4, kAnyFloat, 4); - AddColorFormat(wgpu::TextureFormat::RGBA8Uint, true, true, true, 4, SampleTypeBit::Uint, 4); - AddColorFormat(wgpu::TextureFormat::RGBA8Sint, true, true, true, 4, SampleTypeBit::Sint, 4); - AddColorFormat(wgpu::TextureFormat::BGRA8Unorm, true, false, true, 4, kAnyFloat, 4); - AddColorFormat(wgpu::TextureFormat::BGRA8UnormSrgb, true, false, true, 4, kAnyFloat, 4, wgpu::TextureFormat::BGRA8Unorm); - AddColorFormat(wgpu::TextureFormat::RGB10A2Unorm, true, false, true, 4, kAnyFloat, 4); + AddColorFormat(wgpu::TextureFormat::R32Uint, true, true, false, false, 4, SampleTypeBit::Uint, 1); + AddColorFormat(wgpu::TextureFormat::R32Sint, true, true, false, false, 4, SampleTypeBit::Sint, 1); + AddColorFormat(wgpu::TextureFormat::R32Float, true, true, true, false, 4, SampleTypeBit::UnfilterableFloat, 1); + AddColorFormat(wgpu::TextureFormat::RG16Uint, true, false, true, false, 4, SampleTypeBit::Uint, 2); + AddColorFormat(wgpu::TextureFormat::RG16Sint, true, false, true, false, 4, SampleTypeBit::Sint, 2); + AddColorFormat(wgpu::TextureFormat::RG16Float, true, false, true, true, 4, kAnyFloat, 2); + AddColorFormat(wgpu::TextureFormat::RGBA8Unorm, true, true, true, true, 4, kAnyFloat, 4); + AddColorFormat(wgpu::TextureFormat::RGBA8UnormSrgb, true, false, true, true, 4, kAnyFloat, 4, wgpu::TextureFormat::RGBA8Unorm); + AddColorFormat(wgpu::TextureFormat::RGBA8Snorm, false, true, true, false, 4, kAnyFloat, 4); + AddColorFormat(wgpu::TextureFormat::RGBA8Uint, true, true, true, false, 4, SampleTypeBit::Uint, 4); + AddColorFormat(wgpu::TextureFormat::RGBA8Sint, true, true, true, false, 4, SampleTypeBit::Sint, 4); + AddColorFormat(wgpu::TextureFormat::BGRA8Unorm, true, false, true, true, 4, kAnyFloat, 4); + AddColorFormat(wgpu::TextureFormat::BGRA8UnormSrgb, true, false, true, true, 4, kAnyFloat, 4, wgpu::TextureFormat::BGRA8Unorm); + AddColorFormat(wgpu::TextureFormat::RGB10A2Unorm, true, false, true, true, 4, kAnyFloat, 4); - AddColorFormat(wgpu::TextureFormat::RG11B10Ufloat, false, false, true, 4, kAnyFloat, 3); - AddColorFormat(wgpu::TextureFormat::RGB9E5Ufloat, false, false, false, 4, kAnyFloat, 3); + AddColorFormat(wgpu::TextureFormat::RG11B10Ufloat, false, false, true, false, 4, kAnyFloat, 3); + AddColorFormat(wgpu::TextureFormat::RGB9E5Ufloat, false, false, false, false, 4, kAnyFloat, 3); // 8 bytes color formats - AddColorFormat(wgpu::TextureFormat::RG32Uint, true, true, false, 8, SampleTypeBit::Uint, 2); - AddColorFormat(wgpu::TextureFormat::RG32Sint, true, true, false, 8, SampleTypeBit::Sint, 2); - AddColorFormat(wgpu::TextureFormat::RG32Float, true, true, false, 8, SampleTypeBit::UnfilterableFloat, 2); - AddColorFormat(wgpu::TextureFormat::RGBA16Uint, true, true, true, 8, SampleTypeBit::Uint, 4); - AddColorFormat(wgpu::TextureFormat::RGBA16Sint, true, true, true, 8, SampleTypeBit::Sint, 4); - AddColorFormat(wgpu::TextureFormat::RGBA16Float, true, true, true, 8, kAnyFloat, 4); + AddColorFormat(wgpu::TextureFormat::RG32Uint, true, true, false, false, 8, SampleTypeBit::Uint, 2); + AddColorFormat(wgpu::TextureFormat::RG32Sint, true, true, false, false, 8, SampleTypeBit::Sint, 2); + AddColorFormat(wgpu::TextureFormat::RG32Float, true, true, false, false, 8, SampleTypeBit::UnfilterableFloat, 2); + AddColorFormat(wgpu::TextureFormat::RGBA16Uint, true, true, true, false, 8, SampleTypeBit::Uint, 4); + AddColorFormat(wgpu::TextureFormat::RGBA16Sint, true, true, true, false, 8, SampleTypeBit::Sint, 4); + AddColorFormat(wgpu::TextureFormat::RGBA16Float, true, true, true, true, 8, kAnyFloat, 4); // 16 bytes color formats - AddColorFormat(wgpu::TextureFormat::RGBA32Uint, true, true, false, 16, SampleTypeBit::Uint, 4); - AddColorFormat(wgpu::TextureFormat::RGBA32Sint, true, true, false, 16, SampleTypeBit::Sint, 4); - AddColorFormat(wgpu::TextureFormat::RGBA32Float, true, true, false, 16, SampleTypeBit::UnfilterableFloat, 4); + AddColorFormat(wgpu::TextureFormat::RGBA32Uint, true, true, false, false, 16, SampleTypeBit::Uint, 4); + AddColorFormat(wgpu::TextureFormat::RGBA32Sint, true, true, false, false, 16, SampleTypeBit::Sint, 4); + AddColorFormat(wgpu::TextureFormat::RGBA32Float, true, true, false, false, 16, SampleTypeBit::UnfilterableFloat, 4); // Depth-stencil formats // TODO(dawn:666): Implement the stencil8 format diff --git a/src/dawn/native/Format.h b/src/dawn/native/Format.h index 228913ca2d..441794734d 100644 --- a/src/dawn/native/Format.h +++ b/src/dawn/native/Format.h @@ -92,6 +92,7 @@ namespace dawn::native { bool isSupported; bool supportsStorageUsage; bool supportsMultisample; + bool supportsResolveTarget; Aspect aspects; // Only used for renderable color formats, number of color channels. uint8_t componentCount; diff --git a/src/dawn/tests/unittests/validation/RenderPassDescriptorValidationTests.cpp b/src/dawn/tests/unittests/validation/RenderPassDescriptorValidationTests.cpp index 9af93f6b85..b687fed0d5 100644 --- a/src/dawn/tests/unittests/validation/RenderPassDescriptorValidationTests.cpp +++ b/src/dawn/tests/unittests/validation/RenderPassDescriptorValidationTests.cpp @@ -676,6 +676,30 @@ namespace { } } + // Tests the texture format of the resolve target must support being used as resolve target. + TEST_F(MultisampledRenderPassDescriptorValidationTest, ResolveTargetFormat) { + for (wgpu::TextureFormat format : utils::kAllTextureFormats) { + if (!utils::TextureFormatSupportsMultisampling(format) || + !utils::TextureFormatSupportsRendering(format)) { + continue; + } + + wgpu::Texture colorTexture = + CreateTexture(device, wgpu::TextureDimension::e2D, format, kSize, kSize, + kArrayLayers, kLevelCount, kSampleCount); + wgpu::Texture resolveTarget = CreateTexture(device, wgpu::TextureDimension::e2D, format, + kSize, kSize, kArrayLayers, kLevelCount, 1); + + utils::ComboRenderPassDescriptor renderPass({colorTexture.CreateView()}); + renderPass.cColorAttachments[0].resolveTarget = resolveTarget.CreateView(); + if (utils::TextureFormatSupportsResolveTarget(format)) { + AssertBeginRenderPassSuccess(&renderPass); + } else { + AssertBeginRenderPassError(&renderPass); + } + } + } + // Tests on the sample count of depth stencil attachment. TEST_F(MultisampledRenderPassDescriptorValidationTest, DepthStencilAttachmentSampleCount) { constexpr wgpu::TextureFormat kDepthStencilFormat = diff --git a/src/dawn/utils/TextureUtils.cpp b/src/dawn/utils/TextureUtils.cpp index 099cad24b8..0e816ff8c9 100644 --- a/src/dawn/utils/TextureUtils.cpp +++ b/src/dawn/utils/TextureUtils.cpp @@ -153,6 +153,64 @@ namespace utils { } } + bool TextureFormatSupportsRendering(wgpu::TextureFormat textureFormat) { + switch (textureFormat) { + case wgpu::TextureFormat::R8Unorm: + case wgpu::TextureFormat::R8Uint: + case wgpu::TextureFormat::R8Sint: + case wgpu::TextureFormat::RG8Unorm: + case wgpu::TextureFormat::RG8Uint: + case wgpu::TextureFormat::RG8Sint: + case wgpu::TextureFormat::RGBA8Unorm: + case wgpu::TextureFormat::RGBA8Uint: + case wgpu::TextureFormat::RGBA8Sint: + case wgpu::TextureFormat::BGRA8Unorm: + case wgpu::TextureFormat::BGRA8UnormSrgb: + case wgpu::TextureFormat::R16Uint: + case wgpu::TextureFormat::R16Sint: + case wgpu::TextureFormat::R16Float: + case wgpu::TextureFormat::RG16Uint: + case wgpu::TextureFormat::RG16Sint: + case wgpu::TextureFormat::RG16Float: + case wgpu::TextureFormat::RGBA16Uint: + case wgpu::TextureFormat::RGBA16Sint: + case wgpu::TextureFormat::RGBA16Float: + case wgpu::TextureFormat::R32Uint: + case wgpu::TextureFormat::R32Sint: + case wgpu::TextureFormat::R32Float: + case wgpu::TextureFormat::RG32Uint: + case wgpu::TextureFormat::RG32Sint: + case wgpu::TextureFormat::RG32Float: + case wgpu::TextureFormat::RGBA32Uint: + case wgpu::TextureFormat::RGBA32Sint: + case wgpu::TextureFormat::RGBA32Float: + case wgpu::TextureFormat::RGB10A2Unorm: + return true; + + default: + return false; + } + } + + bool TextureFormatSupportsResolveTarget(wgpu::TextureFormat textureFormat) { + switch (textureFormat) { + case wgpu::TextureFormat::R8Unorm: + case wgpu::TextureFormat::RG8Unorm: + case wgpu::TextureFormat::RGBA8Unorm: + case wgpu::TextureFormat::RGBA8UnormSrgb: + case wgpu::TextureFormat::BGRA8Unorm: + case wgpu::TextureFormat::BGRA8UnormSrgb: + case wgpu::TextureFormat::R16Float: + case wgpu::TextureFormat::RG16Float: + case wgpu::TextureFormat::RGBA16Float: + case wgpu::TextureFormat::RGB10A2Unorm: + return true; + + default: + return false; + } + } + uint32_t GetTexelBlockSizeInBytes(wgpu::TextureFormat textureFormat) { switch (textureFormat) { case wgpu::TextureFormat::R8Unorm: diff --git a/src/dawn/utils/TextureUtils.h b/src/dawn/utils/TextureUtils.h index b75903b7e3..8472bc9de6 100644 --- a/src/dawn/utils/TextureUtils.h +++ b/src/dawn/utils/TextureUtils.h @@ -232,6 +232,8 @@ namespace utils { bool IsDepthOnlyFormat(wgpu::TextureFormat textureFormat); bool TextureFormatSupportsMultisampling(wgpu::TextureFormat textureFormat); + bool TextureFormatSupportsResolveTarget(wgpu::TextureFormat textureFormat); + bool TextureFormatSupportsRendering(wgpu::TextureFormat textureFormat); uint32_t GetTexelBlockSizeInBytes(wgpu::TextureFormat textureFormat); uint32_t GetTextureFormatBlockWidth(wgpu::TextureFormat textureFormat);