mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-07-04 04:06:01 +00:00
Enabling alphaToCoverage
Added the alphaToCoverage functionality with some end2end tests. There is no validation for disabling alphaToCoverage mode if SV_Coverage is statically used by the shader yet. Bug: dawn:494 Change-Id: I9df15b35697ea05a064b092edae9d5d20f73c4d8 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/25761 Commit-Queue: Tomek Ponitka <tommek@google.com> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
parent
9ecb99344f
commit
ab04da48f4
@ -366,8 +366,8 @@ namespace dawn_native {
|
|||||||
DAWN_TRY(ValidateDepthStencilStateDescriptor(device, descriptor->depthStencilState));
|
DAWN_TRY(ValidateDepthStencilStateDescriptor(device, descriptor->depthStencilState));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor->alphaToCoverageEnabled) {
|
if (descriptor->alphaToCoverageEnabled && descriptor->sampleCount <= 1) {
|
||||||
return DAWN_VALIDATION_ERROR("alphaToCoverageEnabled isn't supported (yet)");
|
return DAWN_VALIDATION_ERROR("Enabling alphaToCoverage requires sampleCount > 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
@ -572,6 +572,11 @@ namespace dawn_native {
|
|||||||
return mSampleMask;
|
return mSampleMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RenderPipelineBase::IsAlphaToCoverageEnabled() const {
|
||||||
|
ASSERT(!IsError());
|
||||||
|
return mAlphaToCoverageEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
const AttachmentState* RenderPipelineBase::GetAttachmentState() const {
|
const AttachmentState* RenderPipelineBase::GetAttachmentState() const {
|
||||||
ASSERT(!IsError());
|
ASSERT(!IsError());
|
||||||
|
|
||||||
|
@ -77,6 +77,7 @@ namespace dawn_native {
|
|||||||
wgpu::TextureFormat GetDepthStencilFormat() const;
|
wgpu::TextureFormat GetDepthStencilFormat() const;
|
||||||
uint32_t GetSampleCount() const;
|
uint32_t GetSampleCount() const;
|
||||||
uint32_t GetSampleMask() const;
|
uint32_t GetSampleMask() const;
|
||||||
|
bool IsAlphaToCoverageEnabled() const;
|
||||||
|
|
||||||
const AttachmentState* GetAttachmentState() const;
|
const AttachmentState* GetAttachmentState() const;
|
||||||
|
|
||||||
|
@ -383,7 +383,7 @@ namespace dawn_native { namespace d3d12 {
|
|||||||
}
|
}
|
||||||
descriptorD3D12.NumRenderTargets = static_cast<uint32_t>(GetColorAttachmentsMask().count());
|
descriptorD3D12.NumRenderTargets = static_cast<uint32_t>(GetColorAttachmentsMask().count());
|
||||||
|
|
||||||
descriptorD3D12.BlendState.AlphaToCoverageEnable = FALSE;
|
descriptorD3D12.BlendState.AlphaToCoverageEnable = descriptor->alphaToCoverageEnabled;
|
||||||
descriptorD3D12.BlendState.IndependentBlendEnable = TRUE;
|
descriptorD3D12.BlendState.IndependentBlendEnable = TRUE;
|
||||||
|
|
||||||
descriptorD3D12.DepthStencilState =
|
descriptorD3D12.DepthStencilState =
|
||||||
|
@ -383,6 +383,7 @@ namespace dawn_native { namespace metal {
|
|||||||
[vertexDesc release];
|
[vertexDesc release];
|
||||||
|
|
||||||
descriptorMTL.sampleCount = GetSampleCount();
|
descriptorMTL.sampleCount = GetSampleCount();
|
||||||
|
descriptorMTL.alphaToCoverageEnabled = descriptor->alphaToCoverageEnabled;
|
||||||
|
|
||||||
{
|
{
|
||||||
NSError* error = nil;
|
NSError* error = nil;
|
||||||
|
@ -258,6 +258,11 @@ namespace dawn_native { namespace opengl {
|
|||||||
ApplyDepthStencilState(gl, GetDepthStencilStateDescriptor(), &persistentPipelineState);
|
ApplyDepthStencilState(gl, GetDepthStencilStateDescriptor(), &persistentPipelineState);
|
||||||
|
|
||||||
gl.SampleMaski(0, GetSampleMask());
|
gl.SampleMaski(0, GetSampleMask());
|
||||||
|
if (IsAlphaToCoverageEnabled()) {
|
||||||
|
gl.Enable(GL_SAMPLE_ALPHA_TO_COVERAGE);
|
||||||
|
} else {
|
||||||
|
gl.Disable(GL_SAMPLE_ALPHA_TO_COVERAGE);
|
||||||
|
}
|
||||||
|
|
||||||
for (uint32_t attachmentSlot : IterateBitSet(GetColorAttachmentsMask())) {
|
for (uint32_t attachmentSlot : IterateBitSet(GetColorAttachmentsMask())) {
|
||||||
ApplyColorState(gl, attachmentSlot, GetColorStateDescriptor(attachmentSlot));
|
ApplyColorState(gl, attachmentSlot, GetColorStateDescriptor(attachmentSlot));
|
||||||
|
@ -416,7 +416,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
ASSERT(multisample.rasterizationSamples <= 32);
|
ASSERT(multisample.rasterizationSamples <= 32);
|
||||||
VkSampleMask sampleMask = GetSampleMask();
|
VkSampleMask sampleMask = GetSampleMask();
|
||||||
multisample.pSampleMask = &sampleMask;
|
multisample.pSampleMask = &sampleMask;
|
||||||
multisample.alphaToCoverageEnable = VK_FALSE;
|
multisample.alphaToCoverageEnable = descriptor->alphaToCoverageEnabled;
|
||||||
multisample.alphaToOneEnable = VK_FALSE;
|
multisample.alphaToOneEnable = VK_FALSE;
|
||||||
|
|
||||||
VkPipelineDepthStencilStateCreateInfo depthStencilState =
|
VkPipelineDepthStencilStateCreateInfo depthStencilState =
|
||||||
|
@ -38,7 +38,9 @@ class MultisampledRenderingTest : public DawnTest {
|
|||||||
|
|
||||||
wgpu::RenderPipeline CreateRenderPipelineWithOneOutputForTest(
|
wgpu::RenderPipeline CreateRenderPipelineWithOneOutputForTest(
|
||||||
bool testDepth,
|
bool testDepth,
|
||||||
uint32_t sampleMask = 0xFFFFFFFF) {
|
uint32_t sampleMask = 0xFFFFFFFF,
|
||||||
|
bool alphaToCoverageEnabled = false,
|
||||||
|
bool flipTriangle = false) {
|
||||||
const char* kFsOneOutputWithDepth =
|
const char* kFsOneOutputWithDepth =
|
||||||
R"(#version 450
|
R"(#version 450
|
||||||
layout(location = 0) out vec4 fragColor;
|
layout(location = 0) out vec4 fragColor;
|
||||||
@ -63,11 +65,13 @@ class MultisampledRenderingTest : public DawnTest {
|
|||||||
|
|
||||||
const char* fs = testDepth ? kFsOneOutputWithDepth : kFsOneOutputWithoutDepth;
|
const char* fs = testDepth ? kFsOneOutputWithDepth : kFsOneOutputWithoutDepth;
|
||||||
|
|
||||||
return CreateRenderPipelineForTest(fs, 1, testDepth, sampleMask);
|
return CreateRenderPipelineForTest(fs, 1, testDepth, sampleMask, alphaToCoverageEnabled,
|
||||||
|
flipTriangle);
|
||||||
}
|
}
|
||||||
|
|
||||||
wgpu::RenderPipeline CreateRenderPipelineWithTwoOutputsForTest(
|
wgpu::RenderPipeline CreateRenderPipelineWithTwoOutputsForTest(
|
||||||
uint32_t sampleMask = 0xFFFFFFFF) {
|
uint32_t sampleMask = 0xFFFFFFFF,
|
||||||
|
bool alphaToCoverageEnabled = false) {
|
||||||
const char* kFsTwoOutputs =
|
const char* kFsTwoOutputs =
|
||||||
R"(#version 450
|
R"(#version 450
|
||||||
layout(location = 0) out vec4 fragColor1;
|
layout(location = 0) out vec4 fragColor1;
|
||||||
@ -81,7 +85,8 @@ class MultisampledRenderingTest : public DawnTest {
|
|||||||
fragColor2 = color2;
|
fragColor2 = color2;
|
||||||
})";
|
})";
|
||||||
|
|
||||||
return CreateRenderPipelineForTest(kFsTwoOutputs, 2, false, sampleMask);
|
return CreateRenderPipelineForTest(kFsTwoOutputs, 2, false, sampleMask,
|
||||||
|
alphaToCoverageEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
wgpu::Texture CreateTextureForOutputAttachment(wgpu::TextureFormat format,
|
wgpu::Texture CreateTextureForOutputAttachment(wgpu::TextureFormat format,
|
||||||
@ -117,6 +122,13 @@ class MultisampledRenderingTest : public DawnTest {
|
|||||||
renderPassEncoder.EndPass();
|
renderPassEncoder.EndPass();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EncodeRenderPassForTest(wgpu::CommandEncoder commandEncoder,
|
||||||
|
const wgpu::RenderPassDescriptor& renderPass,
|
||||||
|
const wgpu::RenderPipeline& pipeline,
|
||||||
|
const wgpu::Color& color) {
|
||||||
|
EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, &color.r, sizeof(color));
|
||||||
|
}
|
||||||
|
|
||||||
utils::ComboRenderPassDescriptor CreateComboRenderPassDescriptorForTest(
|
utils::ComboRenderPassDescriptor CreateComboRenderPassDescriptorForTest(
|
||||||
std::initializer_list<wgpu::TextureView> colorViews,
|
std::initializer_list<wgpu::TextureView> colorViews,
|
||||||
std::initializer_list<wgpu::TextureView> resolveTargetViews,
|
std::initializer_list<wgpu::TextureView> resolveTargetViews,
|
||||||
@ -152,17 +164,12 @@ class MultisampledRenderingTest : public DawnTest {
|
|||||||
wgpu::Texture resolveTexture,
|
wgpu::Texture resolveTexture,
|
||||||
uint32_t mipmapLevel = 0,
|
uint32_t mipmapLevel = 0,
|
||||||
uint32_t arrayLayer = 0,
|
uint32_t arrayLayer = 0,
|
||||||
const float MSAACoverage = 0.5f) {
|
const float msaaCoverage = 0.5f) {
|
||||||
// In this test we only check the pixel in the middle of the texture.
|
// In this test we only check the pixel in the middle of the texture.
|
||||||
constexpr uint32_t kMiddleX = (kWidth - 1) / 2;
|
constexpr uint32_t kMiddleX = (kWidth - 1) / 2;
|
||||||
constexpr uint32_t kMiddleY = (kHeight - 1) / 2;
|
constexpr uint32_t kMiddleY = (kHeight - 1) / 2;
|
||||||
|
|
||||||
RGBA8 expectedColor;
|
RGBA8 expectedColor = ExpectedMSAAColor(inputColor, msaaCoverage);
|
||||||
expectedColor.r = static_cast<uint8_t>(0xFF * inputColor.r * MSAACoverage);
|
|
||||||
expectedColor.g = static_cast<uint8_t>(0xFF * inputColor.g * MSAACoverage);
|
|
||||||
expectedColor.b = static_cast<uint8_t>(0xFF * inputColor.b * MSAACoverage);
|
|
||||||
expectedColor.a = static_cast<uint8_t>(0xFF * inputColor.a * MSAACoverage);
|
|
||||||
|
|
||||||
EXPECT_TEXTURE_RGBA8_EQ(&expectedColor, resolveTexture, kMiddleX, kMiddleY, 1, 1,
|
EXPECT_TEXTURE_RGBA8_EQ(&expectedColor, resolveTexture, kMiddleX, kMiddleY, 1, 1,
|
||||||
mipmapLevel, arrayLayer);
|
mipmapLevel, arrayLayer);
|
||||||
}
|
}
|
||||||
@ -189,7 +196,9 @@ class MultisampledRenderingTest : public DawnTest {
|
|||||||
wgpu::RenderPipeline CreateRenderPipelineForTest(const char* fs,
|
wgpu::RenderPipeline CreateRenderPipelineForTest(const char* fs,
|
||||||
uint32_t numColorAttachments,
|
uint32_t numColorAttachments,
|
||||||
bool hasDepthStencilAttachment,
|
bool hasDepthStencilAttachment,
|
||||||
uint32_t sampleMask = 0xFFFFFFFF) {
|
uint32_t sampleMask = 0xFFFFFFFF,
|
||||||
|
bool alphaToCoverageEnabled = false,
|
||||||
|
bool flipTriangle = false) {
|
||||||
utils::ComboRenderPipelineDescriptor pipelineDescriptor(device);
|
utils::ComboRenderPipelineDescriptor pipelineDescriptor(device);
|
||||||
|
|
||||||
// Draw a bottom-right triangle. In standard 4xMSAA pattern, for the pixels on diagonal,
|
// Draw a bottom-right triangle. In standard 4xMSAA pattern, for the pixels on diagonal,
|
||||||
@ -200,8 +209,22 @@ class MultisampledRenderingTest : public DawnTest {
|
|||||||
void main() {
|
void main() {
|
||||||
gl_Position = vec4(pos[gl_VertexIndex], 0.0, 1.0);
|
gl_Position = vec4(pos[gl_VertexIndex], 0.0, 1.0);
|
||||||
})";
|
})";
|
||||||
|
|
||||||
|
// Draw a bottom-left triangle.
|
||||||
|
const char* vsFlipped =
|
||||||
|
R"(#version 450
|
||||||
|
const vec2 pos[3] = vec2[3](vec2(-1.f, 1.f), vec2(1.f, 1.f), vec2(-1.f, -1.f));
|
||||||
|
void main() {
|
||||||
|
gl_Position = vec4(pos[gl_VertexIndex], 0.0, 1.0);
|
||||||
|
})";
|
||||||
|
|
||||||
|
if (flipTriangle) {
|
||||||
|
pipelineDescriptor.vertexStage.module =
|
||||||
|
utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, vsFlipped);
|
||||||
|
} else {
|
||||||
pipelineDescriptor.vertexStage.module =
|
pipelineDescriptor.vertexStage.module =
|
||||||
utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, vs);
|
utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, vs);
|
||||||
|
}
|
||||||
|
|
||||||
pipelineDescriptor.cFragmentStage.module =
|
pipelineDescriptor.cFragmentStage.module =
|
||||||
utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, fs);
|
utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, fs);
|
||||||
@ -215,6 +238,7 @@ class MultisampledRenderingTest : public DawnTest {
|
|||||||
|
|
||||||
pipelineDescriptor.sampleCount = kSampleCount;
|
pipelineDescriptor.sampleCount = kSampleCount;
|
||||||
pipelineDescriptor.sampleMask = sampleMask;
|
pipelineDescriptor.sampleMask = sampleMask;
|
||||||
|
pipelineDescriptor.alphaToCoverageEnabled = alphaToCoverageEnabled;
|
||||||
|
|
||||||
pipelineDescriptor.colorStateCount = numColorAttachments;
|
pipelineDescriptor.colorStateCount = numColorAttachments;
|
||||||
for (uint32_t i = 0; i < numColorAttachments; ++i) {
|
for (uint32_t i = 0; i < numColorAttachments; ++i) {
|
||||||
@ -224,6 +248,15 @@ class MultisampledRenderingTest : public DawnTest {
|
|||||||
wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pipelineDescriptor);
|
wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pipelineDescriptor);
|
||||||
return pipeline;
|
return pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RGBA8 ExpectedMSAAColor(const wgpu::Color color, const float msaaCoverage) {
|
||||||
|
RGBA8 result;
|
||||||
|
result.r = static_cast<uint8_t>(std::min(255.0f, 256 * color.r * msaaCoverage));
|
||||||
|
result.g = static_cast<uint8_t>(std::min(255.0f, 256 * color.g * msaaCoverage));
|
||||||
|
result.b = static_cast<uint8_t>(std::min(255.0f, 256 * color.b * msaaCoverage));
|
||||||
|
result.a = static_cast<uint8_t>(std::min(255.0f, 256 * color.a * msaaCoverage));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Test using one multisampled color attachment with resolve target can render correctly.
|
// Test using one multisampled color attachment with resolve target can render correctly.
|
||||||
@ -233,7 +266,6 @@ TEST_P(MultisampledRenderingTest, ResolveInto2DTexture) {
|
|||||||
wgpu::RenderPipeline pipeline = CreateRenderPipelineWithOneOutputForTest(kTestDepth);
|
wgpu::RenderPipeline pipeline = CreateRenderPipelineWithOneOutputForTest(kTestDepth);
|
||||||
|
|
||||||
constexpr wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, 0.8f};
|
constexpr wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, 0.8f};
|
||||||
constexpr uint32_t kSize = sizeof(kGreen);
|
|
||||||
|
|
||||||
// Draw a green triangle.
|
// Draw a green triangle.
|
||||||
{
|
{
|
||||||
@ -241,7 +273,7 @@ TEST_P(MultisampledRenderingTest, ResolveInto2DTexture) {
|
|||||||
{mMultisampledColorView}, {mResolveView}, wgpu::LoadOp::Clear, wgpu::LoadOp::Clear,
|
{mMultisampledColorView}, {mResolveView}, wgpu::LoadOp::Clear, wgpu::LoadOp::Clear,
|
||||||
kTestDepth);
|
kTestDepth);
|
||||||
|
|
||||||
EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, &kGreen.r, kSize);
|
EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, kGreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
wgpu::CommandBuffer commandBuffer = commandEncoder.Finish();
|
wgpu::CommandBuffer commandBuffer = commandEncoder.Finish();
|
||||||
@ -257,7 +289,6 @@ TEST_P(MultisampledRenderingTest, ResolveFromSingleLayerArrayInto2DTexture) {
|
|||||||
wgpu::RenderPipeline pipeline = CreateRenderPipelineWithOneOutputForTest(kTestDepth);
|
wgpu::RenderPipeline pipeline = CreateRenderPipelineWithOneOutputForTest(kTestDepth);
|
||||||
|
|
||||||
constexpr wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, 0.8f};
|
constexpr wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, 0.8f};
|
||||||
constexpr uint32_t kSize = sizeof(kGreen);
|
|
||||||
|
|
||||||
// Draw a green triangle.
|
// Draw a green triangle.
|
||||||
{
|
{
|
||||||
@ -269,7 +300,7 @@ TEST_P(MultisampledRenderingTest, ResolveFromSingleLayerArrayInto2DTexture) {
|
|||||||
{mMultisampledColorTexture.CreateView(&desc)}, {mResolveView}, wgpu::LoadOp::Clear,
|
{mMultisampledColorTexture.CreateView(&desc)}, {mResolveView}, wgpu::LoadOp::Clear,
|
||||||
wgpu::LoadOp::Clear, kTestDepth);
|
wgpu::LoadOp::Clear, kTestDepth);
|
||||||
|
|
||||||
EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, &kGreen.r, kSize);
|
EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, kGreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
wgpu::CommandBuffer commandBuffer = commandEncoder.Finish();
|
wgpu::CommandBuffer commandBuffer = commandEncoder.Finish();
|
||||||
@ -306,7 +337,7 @@ TEST_P(MultisampledRenderingTest, MultisampledRenderingWithDepthTest) {
|
|||||||
{mMultisampledColorView}, {mResolveView}, wgpu::LoadOp::Load, wgpu::LoadOp::Load,
|
{mMultisampledColorView}, {mResolveView}, wgpu::LoadOp::Load, wgpu::LoadOp::Load,
|
||||||
kTestDepth);
|
kTestDepth);
|
||||||
|
|
||||||
std::array<float, 8> kUniformData = {kRed.r, kRed.g, kRed.b, kRed.a, // color
|
std::array<float, 5> kUniformData = {kRed.r, kRed.g, kRed.b, kRed.a, // color
|
||||||
0.5f}; // depth
|
0.5f}; // depth
|
||||||
constexpr uint32_t kSize = sizeof(kUniformData);
|
constexpr uint32_t kSize = sizeof(kUniformData);
|
||||||
EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, kUniformData.data(), kSize);
|
EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, kUniformData.data(), kSize);
|
||||||
@ -328,7 +359,6 @@ TEST_P(MultisampledRenderingTest, ResolveInAnotherRenderPass) {
|
|||||||
wgpu::RenderPipeline pipeline = CreateRenderPipelineWithOneOutputForTest(kTestDepth);
|
wgpu::RenderPipeline pipeline = CreateRenderPipelineWithOneOutputForTest(kTestDepth);
|
||||||
|
|
||||||
constexpr wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, 0.8f};
|
constexpr wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, 0.8f};
|
||||||
constexpr uint32_t kSize = sizeof(kGreen);
|
|
||||||
|
|
||||||
// In first render pass we draw a green triangle and do not set the resolve target.
|
// In first render pass we draw a green triangle and do not set the resolve target.
|
||||||
{
|
{
|
||||||
@ -336,7 +366,7 @@ TEST_P(MultisampledRenderingTest, ResolveInAnotherRenderPass) {
|
|||||||
{mMultisampledColorView}, {nullptr}, wgpu::LoadOp::Clear, wgpu::LoadOp::Clear,
|
{mMultisampledColorView}, {nullptr}, wgpu::LoadOp::Clear, wgpu::LoadOp::Clear,
|
||||||
kTestDepth);
|
kTestDepth);
|
||||||
|
|
||||||
EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, &kGreen.r, kSize);
|
EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, kGreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
// In second render pass we ony do MSAA resolve with no draw call.
|
// In second render pass we ony do MSAA resolve with no draw call.
|
||||||
@ -398,7 +428,6 @@ TEST_P(MultisampledRenderingTest, ResolveOneMultisampledTextureTwice) {
|
|||||||
wgpu::RenderPipeline pipeline = CreateRenderPipelineWithOneOutputForTest(kTestDepth);
|
wgpu::RenderPipeline pipeline = CreateRenderPipelineWithOneOutputForTest(kTestDepth);
|
||||||
|
|
||||||
constexpr wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, 0.8f};
|
constexpr wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, 0.8f};
|
||||||
constexpr uint32_t kSize = sizeof(kGreen);
|
|
||||||
|
|
||||||
wgpu::Texture resolveTexture2 = CreateTextureForOutputAttachment(kColorFormat, 1);
|
wgpu::Texture resolveTexture2 = CreateTextureForOutputAttachment(kColorFormat, 1);
|
||||||
|
|
||||||
@ -408,7 +437,7 @@ TEST_P(MultisampledRenderingTest, ResolveOneMultisampledTextureTwice) {
|
|||||||
{mMultisampledColorView}, {mResolveView}, wgpu::LoadOp::Clear, wgpu::LoadOp::Clear,
|
{mMultisampledColorView}, {mResolveView}, wgpu::LoadOp::Clear, wgpu::LoadOp::Clear,
|
||||||
kTestDepth);
|
kTestDepth);
|
||||||
|
|
||||||
EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, &kGreen.r, kSize);
|
EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, kGreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
// In second render pass we do MSAA resolve into resolveTexture2.
|
// In second render pass we do MSAA resolve into resolveTexture2.
|
||||||
@ -450,7 +479,6 @@ TEST_P(MultisampledRenderingTest, ResolveIntoOneMipmapLevelOf2DTexture) {
|
|||||||
|
|
||||||
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
||||||
constexpr wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, 0.8f};
|
constexpr wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, 0.8f};
|
||||||
constexpr uint32_t kSize = sizeof(kGreen);
|
|
||||||
constexpr bool kTestDepth = false;
|
constexpr bool kTestDepth = false;
|
||||||
|
|
||||||
// Draw a green triangle and do MSAA resolve.
|
// Draw a green triangle and do MSAA resolve.
|
||||||
@ -460,7 +488,7 @@ TEST_P(MultisampledRenderingTest, ResolveIntoOneMipmapLevelOf2DTexture) {
|
|||||||
kTestDepth);
|
kTestDepth);
|
||||||
wgpu::RenderPipeline pipeline = CreateRenderPipelineWithOneOutputForTest(kTestDepth);
|
wgpu::RenderPipeline pipeline = CreateRenderPipelineWithOneOutputForTest(kTestDepth);
|
||||||
|
|
||||||
EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, &kGreen.r, kSize);
|
EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, kGreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
wgpu::CommandBuffer commandBuffer = commandEncoder.Finish();
|
wgpu::CommandBuffer commandBuffer = commandEncoder.Finish();
|
||||||
@ -544,7 +572,6 @@ TEST_P(MultisampledRenderingTest, ResolveInto2DTextureWithSampleMask) {
|
|||||||
CreateRenderPipelineWithOneOutputForTest(kTestDepth, kSampleMask);
|
CreateRenderPipelineWithOneOutputForTest(kTestDepth, kSampleMask);
|
||||||
|
|
||||||
constexpr wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, 0.8f};
|
constexpr wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, 0.8f};
|
||||||
constexpr uint32_t kSize = sizeof(kGreen);
|
|
||||||
|
|
||||||
// Draw a green triangle.
|
// Draw a green triangle.
|
||||||
{
|
{
|
||||||
@ -552,7 +579,7 @@ TEST_P(MultisampledRenderingTest, ResolveInto2DTextureWithSampleMask) {
|
|||||||
{mMultisampledColorView}, {mResolveView}, wgpu::LoadOp::Clear, wgpu::LoadOp::Clear,
|
{mMultisampledColorView}, {mResolveView}, wgpu::LoadOp::Clear, wgpu::LoadOp::Clear,
|
||||||
kTestDepth);
|
kTestDepth);
|
||||||
|
|
||||||
EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, &kGreen.r, kSize);
|
EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, kGreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
wgpu::CommandBuffer commandBuffer = commandEncoder.Finish();
|
wgpu::CommandBuffer commandBuffer = commandEncoder.Finish();
|
||||||
@ -574,7 +601,6 @@ TEST_P(MultisampledRenderingTest, ResolveInto2DTextureWithEmptyFinalSampleMask)
|
|||||||
CreateRenderPipelineWithOneOutputForTest(kTestDepth, kSampleMask);
|
CreateRenderPipelineWithOneOutputForTest(kTestDepth, kSampleMask);
|
||||||
|
|
||||||
constexpr wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, 0.8f};
|
constexpr wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, 0.8f};
|
||||||
constexpr uint32_t kSize = sizeof(kGreen);
|
|
||||||
|
|
||||||
// Draw a green triangle.
|
// Draw a green triangle.
|
||||||
{
|
{
|
||||||
@ -582,7 +608,7 @@ TEST_P(MultisampledRenderingTest, ResolveInto2DTextureWithEmptyFinalSampleMask)
|
|||||||
{mMultisampledColorView}, {mResolveView}, wgpu::LoadOp::Clear, wgpu::LoadOp::Clear,
|
{mMultisampledColorView}, {mResolveView}, wgpu::LoadOp::Clear, wgpu::LoadOp::Clear,
|
||||||
kTestDepth);
|
kTestDepth);
|
||||||
|
|
||||||
EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, &kGreen.r, kSize);
|
EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, kGreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
wgpu::CommandBuffer commandBuffer = commandEncoder.Finish();
|
wgpu::CommandBuffer commandBuffer = commandEncoder.Finish();
|
||||||
@ -673,7 +699,7 @@ TEST_P(MultisampledRenderingTest, MultisampledRenderingWithDepthTestAndSampleMas
|
|||||||
{mMultisampledColorView}, {mResolveView}, wgpu::LoadOp::Load, wgpu::LoadOp::Load,
|
{mMultisampledColorView}, {mResolveView}, wgpu::LoadOp::Load, wgpu::LoadOp::Load,
|
||||||
kTestDepth);
|
kTestDepth);
|
||||||
|
|
||||||
std::array<float, 8> kUniformData = {kRed.r, kRed.g, kRed.b, kRed.a, // color
|
std::array<float, 5> kUniformData = {kRed.r, kRed.g, kRed.b, kRed.a, // color
|
||||||
0.5f}; // depth
|
0.5f}; // depth
|
||||||
constexpr uint32_t kSize = sizeof(kUniformData);
|
constexpr uint32_t kSize = sizeof(kUniformData);
|
||||||
EncodeRenderPassForTest(commandEncoder, renderPass, pipelineRed, kUniformData.data(),
|
EncodeRenderPassForTest(commandEncoder, renderPass, pipelineRed, kUniformData.data(),
|
||||||
@ -718,7 +744,6 @@ TEST_P(MultisampledRenderingTest, ResolveInto2DTextureWithSampleMaskAndShaderOut
|
|||||||
|
|
||||||
wgpu::RenderPipeline pipeline = CreateRenderPipelineForTest(fs, 1, false, kSampleMask);
|
wgpu::RenderPipeline pipeline = CreateRenderPipelineForTest(fs, 1, false, kSampleMask);
|
||||||
constexpr wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, 0.8f};
|
constexpr wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, 0.8f};
|
||||||
constexpr uint32_t kSize = sizeof(kGreen);
|
|
||||||
|
|
||||||
// Draw a green triangle.
|
// Draw a green triangle.
|
||||||
{
|
{
|
||||||
@ -726,18 +751,13 @@ TEST_P(MultisampledRenderingTest, ResolveInto2DTextureWithSampleMaskAndShaderOut
|
|||||||
{mMultisampledColorView}, {mResolveView}, wgpu::LoadOp::Clear, wgpu::LoadOp::Clear,
|
{mMultisampledColorView}, {mResolveView}, wgpu::LoadOp::Clear, wgpu::LoadOp::Clear,
|
||||||
kTestDepth);
|
kTestDepth);
|
||||||
|
|
||||||
EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, &kGreen.r, kSize);
|
EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, kGreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
wgpu::CommandBuffer commandBuffer = commandEncoder.Finish();
|
wgpu::CommandBuffer commandBuffer = commandEncoder.Finish();
|
||||||
queue.Submit(1, &commandBuffer);
|
queue.Submit(1, &commandBuffer);
|
||||||
|
|
||||||
RGBA8 expectedColor;
|
RGBA8 expectedColor = ExpectedMSAAColor(kGreen, kMSAACoverage);
|
||||||
expectedColor.r = static_cast<uint8_t>(0xFF * kGreen.r * kMSAACoverage);
|
|
||||||
expectedColor.g = static_cast<uint8_t>(0xFF * kGreen.g * kMSAACoverage);
|
|
||||||
expectedColor.b = static_cast<uint8_t>(0xFF * kGreen.b * kMSAACoverage);
|
|
||||||
expectedColor.a = static_cast<uint8_t>(0xFF * kGreen.a * kMSAACoverage);
|
|
||||||
|
|
||||||
EXPECT_TEXTURE_RGBA8_EQ(&expectedColor, mResolveTexture, 1, 0, 1, 1, 0, 0);
|
EXPECT_TEXTURE_RGBA8_EQ(&expectedColor, mResolveTexture, 1, 0, 1, 1, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -791,6 +811,235 @@ TEST_P(MultisampledRenderingTest, ResolveIntoMultipleResolveTargetsWithShaderOut
|
|||||||
VerifyResolveTarget(kGreen, resolveTexture2, 0, 0, kMSAACoverage);
|
VerifyResolveTarget(kGreen, resolveTexture2, 0, 0, kMSAACoverage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test using one multisampled color attachment with resolve target can render correctly
|
||||||
|
// with alphaToCoverageEnabled.
|
||||||
|
TEST_P(MultisampledRenderingTest, ResolveInto2DTextureWithAlphaToCoverage) {
|
||||||
|
constexpr bool kTestDepth = false;
|
||||||
|
constexpr uint32_t kSampleMask = 0xFFFFFFFF;
|
||||||
|
constexpr bool kAlphaToCoverageEnabled = true;
|
||||||
|
|
||||||
|
// Setting alpha <= 0 must result in alpha-to-coverage mask being empty.
|
||||||
|
// Setting alpha = 0.5f should result in alpha-to-coverage mask including half the samples,
|
||||||
|
// but this is not guaranteed by the spec. The Metal spec seems to guarantee that this is
|
||||||
|
// indeed the case.
|
||||||
|
// Setting alpha >= 1 must result in alpha-to-coverage mask being full.
|
||||||
|
for (float alpha : {-1.0f, 0.0f, 0.5f, 1.0f, 2.0f}) {
|
||||||
|
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
||||||
|
wgpu::RenderPipeline pipeline = CreateRenderPipelineWithOneOutputForTest(
|
||||||
|
kTestDepth, kSampleMask, kAlphaToCoverageEnabled);
|
||||||
|
|
||||||
|
const wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, alpha};
|
||||||
|
|
||||||
|
// Draw a green triangle.
|
||||||
|
{
|
||||||
|
utils::ComboRenderPassDescriptor renderPass = CreateComboRenderPassDescriptorForTest(
|
||||||
|
{mMultisampledColorView}, {mResolveView}, wgpu::LoadOp::Clear, wgpu::LoadOp::Clear,
|
||||||
|
kTestDepth);
|
||||||
|
|
||||||
|
EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, kGreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
wgpu::CommandBuffer commandBuffer = commandEncoder.Finish();
|
||||||
|
queue.Submit(1, &commandBuffer);
|
||||||
|
|
||||||
|
// For alpha = {0, 0.5, 1} we expect msaaCoverage to correspond to the value of alpha.
|
||||||
|
float msaaCoverage = alpha;
|
||||||
|
if (alpha < 0.0f) {
|
||||||
|
msaaCoverage = 0.0f;
|
||||||
|
}
|
||||||
|
if (alpha > 1.0f) {
|
||||||
|
msaaCoverage = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
RGBA8 expectedColor = ExpectedMSAAColor(kGreen, msaaCoverage);
|
||||||
|
EXPECT_TEXTURE_RGBA8_EQ(&expectedColor, mResolveTexture, 1, 0, 1, 1, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test doing MSAA resolve into multiple resolve targets works correctly with
|
||||||
|
// alphaToCoverage. The alphaToCoverage mask is computed based on the alpha
|
||||||
|
// component of the first color output attachment.
|
||||||
|
TEST_P(MultisampledRenderingTest, ResolveIntoMultipleResolveTargetsWithAlphaToCoverage) {
|
||||||
|
wgpu::TextureView multisampledColorView2 =
|
||||||
|
CreateTextureForOutputAttachment(kColorFormat, kSampleCount).CreateView();
|
||||||
|
wgpu::Texture resolveTexture2 = CreateTextureForOutputAttachment(kColorFormat, 1);
|
||||||
|
wgpu::TextureView resolveView2 = resolveTexture2.CreateView();
|
||||||
|
constexpr uint32_t kSampleMask = 0xFFFFFFFF;
|
||||||
|
constexpr float kMSAACoverage = 0.50f;
|
||||||
|
constexpr bool kAlphaToCoverageEnabled = true;
|
||||||
|
|
||||||
|
// The alpha-to-coverage mask should not depend on the alpha component of the
|
||||||
|
// second color output attachment.
|
||||||
|
// We test alpha = 0.51f and 0.99f instead of 0.50f and 1.00f because there are some rounding
|
||||||
|
// differences on QuadroP400 devices in that case.
|
||||||
|
for (float alpha : {0.0f, 0.51f, 0.99f}) {
|
||||||
|
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
||||||
|
wgpu::RenderPipeline pipeline =
|
||||||
|
CreateRenderPipelineWithTwoOutputsForTest(kSampleMask, kAlphaToCoverageEnabled);
|
||||||
|
|
||||||
|
constexpr wgpu::Color kRed = {0.8f, 0.0f, 0.0f, 0.51f};
|
||||||
|
const wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, alpha};
|
||||||
|
constexpr bool kTestDepth = false;
|
||||||
|
|
||||||
|
// Draw a red triangle to the first color attachment, and a blue triangle to the second
|
||||||
|
// color attachment, and do MSAA resolve on two render targets in one render pass.
|
||||||
|
{
|
||||||
|
utils::ComboRenderPassDescriptor renderPass = CreateComboRenderPassDescriptorForTest(
|
||||||
|
{mMultisampledColorView, multisampledColorView2}, {mResolveView, resolveView2},
|
||||||
|
wgpu::LoadOp::Clear, wgpu::LoadOp::Clear, kTestDepth);
|
||||||
|
|
||||||
|
std::array<wgpu::Color, 2> kUniformData = {kRed, kGreen};
|
||||||
|
constexpr uint32_t kSize = sizeof(kUniformData);
|
||||||
|
EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, &kUniformData[0].r,
|
||||||
|
kSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
wgpu::CommandBuffer commandBuffer = commandEncoder.Finish();
|
||||||
|
queue.Submit(1, &commandBuffer);
|
||||||
|
|
||||||
|
// Alpha to coverage affects both the color outputs, but the mask is computed
|
||||||
|
// using only the first one.
|
||||||
|
RGBA8 expectedRed = ExpectedMSAAColor(kRed, kMSAACoverage);
|
||||||
|
RGBA8 expectedGreen = ExpectedMSAAColor(kGreen, kMSAACoverage);
|
||||||
|
EXPECT_TEXTURE_RGBA8_EQ(&expectedRed, mResolveTexture, 1, 0, 1, 1, 0, 0);
|
||||||
|
EXPECT_TEXTURE_RGBA8_EQ(&expectedGreen, resolveTexture2, 1, 0, 1, 1, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test multisampled rendering with depth test works correctly with alphaToCoverage.
|
||||||
|
TEST_P(MultisampledRenderingTest, MultisampledRenderingWithDepthTestAndAlphaToCoverage) {
|
||||||
|
constexpr bool kTestDepth = true;
|
||||||
|
constexpr uint32_t kSampleMask = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
||||||
|
wgpu::RenderPipeline pipelineGreen =
|
||||||
|
CreateRenderPipelineWithOneOutputForTest(kTestDepth, kSampleMask, true);
|
||||||
|
wgpu::RenderPipeline pipelineRed =
|
||||||
|
CreateRenderPipelineWithOneOutputForTest(kTestDepth, kSampleMask, false);
|
||||||
|
|
||||||
|
// We test alpha = 0.51f and 0.81f instead of 0.50f and 0.80f because there are some
|
||||||
|
// rounding differences on QuadroP400 devices in that case.
|
||||||
|
constexpr wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, 0.51f};
|
||||||
|
constexpr wgpu::Color kRed = {0.8f, 0.0f, 0.0f, 0.81f};
|
||||||
|
|
||||||
|
// In first render pass we draw a green triangle with depth value == 0.2f.
|
||||||
|
// We will only write to half the samples since the alphaToCoverage mode
|
||||||
|
// is enabled for that render pass.
|
||||||
|
{
|
||||||
|
utils::ComboRenderPassDescriptor renderPass = CreateComboRenderPassDescriptorForTest(
|
||||||
|
{mMultisampledColorView}, {mResolveView}, wgpu::LoadOp::Clear, wgpu::LoadOp::Clear,
|
||||||
|
kTestDepth);
|
||||||
|
std::array<float, 5> kUniformData = {kGreen.r, kGreen.g, kGreen.b, kGreen.a, // Color
|
||||||
|
0.2f}; // depth
|
||||||
|
constexpr uint32_t kSize = sizeof(kUniformData);
|
||||||
|
EncodeRenderPassForTest(commandEncoder, renderPass, pipelineGreen, kUniformData.data(),
|
||||||
|
kSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// In second render pass we draw a red triangle with depth value == 0.5f.
|
||||||
|
// We will write to all the samples since the alphaToCoverageMode is diabled for
|
||||||
|
// that render pass.
|
||||||
|
{
|
||||||
|
utils::ComboRenderPassDescriptor renderPass = CreateComboRenderPassDescriptorForTest(
|
||||||
|
{mMultisampledColorView}, {mResolveView}, wgpu::LoadOp::Load, wgpu::LoadOp::Load,
|
||||||
|
kTestDepth);
|
||||||
|
|
||||||
|
std::array<float, 5> kUniformData = {kRed.r, kRed.g, kRed.b, kRed.a, // color
|
||||||
|
0.5f}; // depth
|
||||||
|
constexpr uint32_t kSize = sizeof(kUniformData);
|
||||||
|
EncodeRenderPassForTest(commandEncoder, renderPass, pipelineRed, kUniformData.data(),
|
||||||
|
kSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
wgpu::CommandBuffer commandBuffer = commandEncoder.Finish();
|
||||||
|
queue.Submit(1, &commandBuffer);
|
||||||
|
|
||||||
|
constexpr wgpu::Color kHalfGreenHalfRed = {(kGreen.r + kRed.r) / 2.0, (kGreen.g + kRed.g) / 2.0,
|
||||||
|
(kGreen.b + kRed.b) / 2.0,
|
||||||
|
(kGreen.a + kRed.a) / 2.0};
|
||||||
|
RGBA8 expectedColor = ExpectedMSAAColor(kHalfGreenHalfRed, 1.0f);
|
||||||
|
|
||||||
|
EXPECT_TEXTURE_RGBA8_EQ(&expectedColor, mResolveTexture, 1, 0, 1, 1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test using one multisampled color attachment with resolve target can render correctly
|
||||||
|
// with alphaToCoverageEnabled and a sample mask.
|
||||||
|
TEST_P(MultisampledRenderingTest, ResolveInto2DTextureWithAlphaToCoverageAndSampleMask) {
|
||||||
|
// TODO(dawn:491): This doesn't work on Metal, because we're using both the shader-output
|
||||||
|
// mask (emulting the sampleMask from RenderPipeline) and alpha-to-coverage at the same
|
||||||
|
// time. See the issue: https://github.com/gpuweb/gpuweb/issues/959.
|
||||||
|
DAWN_SKIP_TEST_IF(IsMetal());
|
||||||
|
|
||||||
|
constexpr bool kTestDepth = false;
|
||||||
|
constexpr float kMSAACoverage = 0.50f;
|
||||||
|
constexpr uint32_t kSampleMask = kFirstSampleMaskBit | kThirdSampleMaskBit;
|
||||||
|
constexpr bool kAlphaToCoverageEnabled = true;
|
||||||
|
|
||||||
|
// For those values of alpha we expect the proportion of samples to be covered
|
||||||
|
// to correspond to the value of alpha.
|
||||||
|
// We're assuming in the case of alpha = 0.50f that the implementation
|
||||||
|
// dependendent algorithm will choose exactly one of the first and third samples.
|
||||||
|
for (float alpha : {0.0f, 0.50f, 1.00f}) {
|
||||||
|
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
||||||
|
wgpu::RenderPipeline pipeline = CreateRenderPipelineWithOneOutputForTest(
|
||||||
|
kTestDepth, kSampleMask, kAlphaToCoverageEnabled);
|
||||||
|
|
||||||
|
const wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, alpha - 0.01f};
|
||||||
|
|
||||||
|
// Draw a green triangle.
|
||||||
|
{
|
||||||
|
utils::ComboRenderPassDescriptor renderPass = CreateComboRenderPassDescriptorForTest(
|
||||||
|
{mMultisampledColorView}, {mResolveView}, wgpu::LoadOp::Clear, wgpu::LoadOp::Clear,
|
||||||
|
kTestDepth);
|
||||||
|
|
||||||
|
EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, kGreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
wgpu::CommandBuffer commandBuffer = commandEncoder.Finish();
|
||||||
|
queue.Submit(1, &commandBuffer);
|
||||||
|
|
||||||
|
RGBA8 expectedColor = ExpectedMSAAColor(kGreen, kMSAACoverage * alpha);
|
||||||
|
EXPECT_TEXTURE_RGBA8_EQ(&expectedColor, mResolveTexture, 1, 0, 1, 1, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test using one multisampled color attachment with resolve target can render correctly
|
||||||
|
// with alphaToCoverageEnabled and a rasterization mask.
|
||||||
|
TEST_P(MultisampledRenderingTest, ResolveInto2DTextureWithAlphaToCoverageAndRasterizationMask) {
|
||||||
|
constexpr bool kTestDepth = false;
|
||||||
|
constexpr float kMSAACoverage = 0.50f;
|
||||||
|
constexpr uint32_t kSampleMask = 0xFFFFFFFF;
|
||||||
|
constexpr bool kAlphaToCoverageEnabled = true;
|
||||||
|
constexpr bool kFlipTriangle = true;
|
||||||
|
|
||||||
|
// For those values of alpha we expect the proportion of samples to be covered
|
||||||
|
// to correspond to the value of alpha.
|
||||||
|
// We're assuming in the case of alpha = 0.50f that the implementation
|
||||||
|
// dependendent algorithm will choose exactly one of the samples covered by the
|
||||||
|
// triangle.
|
||||||
|
for (float alpha : {0.0f, 0.50f, 1.00f}) {
|
||||||
|
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
||||||
|
wgpu::RenderPipeline pipeline = CreateRenderPipelineWithOneOutputForTest(
|
||||||
|
kTestDepth, kSampleMask, kAlphaToCoverageEnabled, kFlipTriangle);
|
||||||
|
|
||||||
|
const wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, alpha - 0.01f};
|
||||||
|
|
||||||
|
// Draw a green triangle.
|
||||||
|
{
|
||||||
|
utils::ComboRenderPassDescriptor renderPass = CreateComboRenderPassDescriptorForTest(
|
||||||
|
{mMultisampledColorView}, {mResolveView}, wgpu::LoadOp::Clear, wgpu::LoadOp::Clear,
|
||||||
|
kTestDepth);
|
||||||
|
|
||||||
|
EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, kGreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
wgpu::CommandBuffer commandBuffer = commandEncoder.Finish();
|
||||||
|
queue.Submit(1, &commandBuffer);
|
||||||
|
|
||||||
|
VerifyResolveTarget(kGreen, mResolveTexture, 0, 0, kMSAACoverage * alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DAWN_INSTANTIATE_TEST(MultisampledRenderingTest,
|
DAWN_INSTANTIATE_TEST(MultisampledRenderingTest,
|
||||||
D3D12Backend(),
|
D3D12Backend(),
|
||||||
D3D12Backend({}, {"use_d3d12_resource_heap_tier2"}),
|
D3D12Backend({}, {"use_d3d12_resource_heap_tier2"}),
|
||||||
|
@ -367,6 +367,30 @@ TEST_F(RenderPipelineValidationTest, SampleCountCompatibilityWithRenderPass) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests that the sample count of the render pipeline must be valid
|
||||||
|
// when the alphaToCoverage mode is enabled.
|
||||||
|
TEST_F(RenderPipelineValidationTest, AlphaToCoverageAndSampleCount) {
|
||||||
|
{
|
||||||
|
utils::ComboRenderPipelineDescriptor descriptor(device);
|
||||||
|
descriptor.vertexStage.module = vsModule;
|
||||||
|
descriptor.cFragmentStage.module = fsModule;
|
||||||
|
descriptor.sampleCount = 4;
|
||||||
|
descriptor.alphaToCoverageEnabled = true;
|
||||||
|
|
||||||
|
device.CreateRenderPipeline(&descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
utils::ComboRenderPipelineDescriptor descriptor(device);
|
||||||
|
descriptor.vertexStage.module = vsModule;
|
||||||
|
descriptor.cFragmentStage.module = fsModule;
|
||||||
|
descriptor.sampleCount = 1;
|
||||||
|
descriptor.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