mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-06-08 15:43:41 +00:00
Add alphaToCoverage validation aligning with WebGPU V1
Add alphaToCoverage validation regards to targets[0] has alpha channel. This change reflecting WebGPU V1 spec update is aimed to ship together with WebGPU in Chromium. Bug: dawn:1759 Change-Id: I0aef60cf8c4dc828e05d6027644ffed35b33f652 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/128061 Commit-Queue: Kai Ninomiya <kainino@chromium.org> Reviewed-by: Kai Ninomiya <kainino@chromium.org> Auto-Submit: Shrek Shao <shrekshao@google.com> Reviewed-by: Austin Eng <enga@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Loko Kung <lokokung@google.com>
This commit is contained in:
parent
ff75ab9a87
commit
a965f520f9
@ -80,6 +80,11 @@ bool Format::HasDepthOrStencil() const {
|
|||||||
return aspects & (Aspect::Depth | Aspect::Stencil);
|
return aspects & (Aspect::Depth | Aspect::Stencil);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Format::HasAlphaChannel() const {
|
||||||
|
// This is true for current formats. May need revisit if new formats and extensions are added.
|
||||||
|
return componentCount == 4 && IsColor();
|
||||||
|
}
|
||||||
|
|
||||||
bool Format::IsMultiPlanar() const {
|
bool Format::IsMultiPlanar() const {
|
||||||
return aspects & (Aspect::Plane0 | Aspect::Plane1);
|
return aspects & (Aspect::Plane0 | Aspect::Plane1);
|
||||||
}
|
}
|
||||||
|
@ -106,6 +106,7 @@ struct Format {
|
|||||||
bool HasDepth() const;
|
bool HasDepth() const;
|
||||||
bool HasStencil() const;
|
bool HasStencil() const;
|
||||||
bool HasDepthOrStencil() const;
|
bool HasDepthOrStencil() const;
|
||||||
|
bool HasAlphaChannel() const;
|
||||||
|
|
||||||
// IsMultiPlanar() returns true if the format allows selecting a plane index. This is only
|
// IsMultiPlanar() returns true if the format allows selecting a plane index. This is only
|
||||||
// allowed by multi-planar formats (ex. NV12).
|
// allowed by multi-planar formats (ex. NV12).
|
||||||
|
@ -427,11 +427,24 @@ MaybeError ValidateFragmentState(DeviceBase* device,
|
|||||||
}
|
}
|
||||||
DAWN_TRY(ValidateColorAttachmentBytesPerSample(device, colorAttachmentFormats));
|
DAWN_TRY(ValidateColorAttachmentBytesPerSample(device, colorAttachmentFormats));
|
||||||
|
|
||||||
DAWN_INVALID_IF(fragmentMetadata.usesSampleMaskOutput && alphaToCoverageEnabled,
|
if (alphaToCoverageEnabled) {
|
||||||
|
DAWN_INVALID_IF(fragmentMetadata.usesSampleMaskOutput,
|
||||||
"alphaToCoverageEnabled is true when the sample_mask builtin is a "
|
"alphaToCoverageEnabled is true when the sample_mask builtin is a "
|
||||||
"pipeline output of fragment stage of %s.",
|
"pipeline output of fragment stage of %s.",
|
||||||
descriptor->module);
|
descriptor->module);
|
||||||
|
|
||||||
|
DAWN_INVALID_IF(descriptor->targetCount == 0 ||
|
||||||
|
descriptor->targets[0].format == wgpu::TextureFormat::Undefined,
|
||||||
|
"alphaToCoverageEnabled is true when color target[0] is not present.");
|
||||||
|
|
||||||
|
const Format* format;
|
||||||
|
DAWN_TRY_ASSIGN(format, device->GetInternalFormat(descriptor->targets[0].format));
|
||||||
|
DAWN_INVALID_IF(
|
||||||
|
!format->HasAlphaChannel(),
|
||||||
|
"alphaToCoverageEnabled is true when target[0].format (%s) has no alpha channel.",
|
||||||
|
format->format);
|
||||||
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -533,6 +546,10 @@ MaybeError ValidateRenderPipelineDescriptor(DeviceBase* device,
|
|||||||
DAWN_TRY_CONTEXT(ValidateMultisampleState(&descriptor->multisample),
|
DAWN_TRY_CONTEXT(ValidateMultisampleState(&descriptor->multisample),
|
||||||
"validating multisample state.");
|
"validating multisample state.");
|
||||||
|
|
||||||
|
DAWN_INVALID_IF(
|
||||||
|
descriptor->multisample.alphaToCoverageEnabled && descriptor->fragment == nullptr,
|
||||||
|
"alphaToCoverageEnabled is true when fragment state is not present.");
|
||||||
|
|
||||||
if (descriptor->fragment != nullptr) {
|
if (descriptor->fragment != nullptr) {
|
||||||
DAWN_TRY_CONTEXT(ValidateFragmentState(device, descriptor->fragment, descriptor->layout,
|
DAWN_TRY_CONTEXT(ValidateFragmentState(device, descriptor->fragment, descriptor->layout,
|
||||||
descriptor->depthStencil,
|
descriptor->depthStencil,
|
||||||
|
@ -848,7 +848,7 @@ TEST_F(RenderPipelineValidationTest, AlphaToCoverageAndSampleCount) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Tests if the sample_mask builtin is a pipeline output of fragment shader,
|
// Tests if the sample_mask builtin is a pipeline output of fragment shader,
|
||||||
// then alphaToCoverageEnabled must be false
|
// then alphaToCoverageEnabled must be false.
|
||||||
TEST_F(RenderPipelineValidationTest, AlphaToCoverageAndSampleMaskOutput) {
|
TEST_F(RenderPipelineValidationTest, AlphaToCoverageAndSampleMaskOutput) {
|
||||||
wgpu::ShaderModule fsModuleSampleMaskOutput = utils::CreateShaderModule(device, R"(
|
wgpu::ShaderModule fsModuleSampleMaskOutput = utils::CreateShaderModule(device, R"(
|
||||||
struct Output {
|
struct Output {
|
||||||
@ -897,6 +897,84 @@ TEST_F(RenderPipelineValidationTest, AlphaToCoverageAndSampleMaskOutput) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests when alphaToCoverageEnabled is true, targets[0] must exist and have alpha channel.
|
||||||
|
TEST_F(RenderPipelineValidationTest, AlphaToCoverageAndColorTargetAlpha) {
|
||||||
|
{
|
||||||
|
// Control case
|
||||||
|
utils::ComboRenderPipelineDescriptor descriptor;
|
||||||
|
descriptor.vertex.module = vsModule;
|
||||||
|
descriptor.cFragment.module = fsModule;
|
||||||
|
descriptor.cTargets[0].format = wgpu::TextureFormat::RGBA8Unorm;
|
||||||
|
descriptor.multisample.count = 4;
|
||||||
|
descriptor.multisample.alphaToCoverageEnabled = true;
|
||||||
|
|
||||||
|
device.CreateRenderPipeline(&descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Fragment state must exist
|
||||||
|
utils::ComboRenderPipelineDescriptor descriptor;
|
||||||
|
descriptor.vertex.module = vsModule;
|
||||||
|
descriptor.fragment = nullptr;
|
||||||
|
descriptor.multisample.count = 4;
|
||||||
|
descriptor.multisample.alphaToCoverageEnabled = true;
|
||||||
|
|
||||||
|
ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Fragment targets[0] must exist
|
||||||
|
utils::ComboRenderPipelineDescriptor descriptor;
|
||||||
|
descriptor.vertex.module = vsModule;
|
||||||
|
descriptor.cFragment.module = fsModule;
|
||||||
|
descriptor.cFragment.targetCount = 0;
|
||||||
|
descriptor.cFragment.targets = nullptr;
|
||||||
|
descriptor.multisample.count = 4;
|
||||||
|
descriptor.multisample.alphaToCoverageEnabled = true;
|
||||||
|
descriptor.EnableDepthStencil(wgpu::TextureFormat::Depth32Float);
|
||||||
|
|
||||||
|
ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Fragment targets[0].format must have alpha channel (only 1 target)
|
||||||
|
utils::ComboRenderPipelineDescriptor descriptor;
|
||||||
|
descriptor.vertex.module = vsModule;
|
||||||
|
descriptor.cFragment.module = fsModule;
|
||||||
|
descriptor.cTargets[0].format = wgpu::TextureFormat::R8Unorm;
|
||||||
|
descriptor.multisample.count = 4;
|
||||||
|
descriptor.multisample.alphaToCoverageEnabled = true;
|
||||||
|
|
||||||
|
ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor));
|
||||||
|
}
|
||||||
|
|
||||||
|
wgpu::ShaderModule fsModule2 = utils::CreateShaderModule(device, R"(
|
||||||
|
struct FragmentOut {
|
||||||
|
@location(0) target0 : vec4f,
|
||||||
|
@location(1) target1 : vec4f,
|
||||||
|
}
|
||||||
|
@fragment fn main() -> FragmentOut {
|
||||||
|
var out: FragmentOut;
|
||||||
|
out.target0 = vec4f(0, 0, 0, 1);
|
||||||
|
out.target1 = vec4f(1, 0, 0, 0);
|
||||||
|
return out;
|
||||||
|
})");
|
||||||
|
|
||||||
|
{
|
||||||
|
// Fragment targets[0].format must have alpha channel (2 targets)
|
||||||
|
utils::ComboRenderPipelineDescriptor descriptor;
|
||||||
|
descriptor.vertex.module = vsModule;
|
||||||
|
descriptor.cFragment.module = fsModule2;
|
||||||
|
descriptor.cFragment.targetCount = 2;
|
||||||
|
descriptor.cTargets[0].format = wgpu::TextureFormat::R8Unorm;
|
||||||
|
descriptor.cTargets[1].format = wgpu::TextureFormat::RGBA8Unorm;
|
||||||
|
descriptor.multisample.count = 4;
|
||||||
|
descriptor.multisample.alphaToCoverageEnabled = true;
|
||||||
|
|
||||||
|
ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Tests that the texture component type in shader must match the bind group layout.
|
// Tests that the texture component type in shader must match the bind group layout.
|
||||||
TEST_F(RenderPipelineValidationTest, TextureComponentTypeCompatibility) {
|
TEST_F(RenderPipelineValidationTest, TextureComponentTypeCompatibility) {
|
||||||
constexpr uint32_t kNumTextureComponentType = 3u;
|
constexpr uint32_t kNumTextureComponentType = 3u;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user