Add MultisampleStateExpandResolveTextureDawn chained struct.
This chained struct is used to indicate that a render pipeline will be
compatible with the render pass using `ExpandResolveTexture` load op.
This is needed for vulkan backend where `ExpandResolveTexture` is
implemented using 2 subpasses. And as such every render pipeline used in
that render pass must operate in 2nd subpass.
Deprecated DawnMultisampleStateRenderToSingleSampled chained struct
since we are not going to implement MSAARenderToSingleSampled using 2
subpasses anymore.
Bug: dawn:1710
Change-Id: I15a7dbddcc4575a63d656aae8f2738a3e85311d9
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/187561
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Quyen Le <lehoangquyen@chromium.org>
diff --git a/docs/dawn/features/dawn_load_resolve_texture.md b/docs/dawn/features/dawn_load_resolve_texture.md
index 62dc2b3..e962e9d 100644
--- a/docs/dawn/features/dawn_load_resolve_texture.md
+++ b/docs/dawn/features/dawn_load_resolve_texture.md
@@ -4,6 +4,7 @@
Additional functionalities:
- Adds `wgpu::LoadOp::ExpandResolveTexture` enum value to specify that the MSAA attachment will load the pixels from its corresponding resolve texture. This is cheaper than `wgpu::LoadOp::Load` which will load the existing pixels of the MSAA attachment itself.
+ - Adds `wgpu::MultisampleStateExpandResolveTextureDawn` as chained struct for `wgpu::RenderPipelineDescriptor::MultisampleState`. It has `enabled` flag to indicate that the render pipeline is going to be used in a render pass with `ExpandResolveTexture` load op.
Example Usage:
```
@@ -33,6 +34,15 @@
renderPassEncoder.Draw(3);
renderPassEncoder.End();
+// Create a render pipeline with wgpu::MultisampleStateExpandResolveTextureDawn.
+wgpu::MultisampleStateExpandResolveTextureDawn pipelineExpandResolveTextureState;
+pipelineExpandResolveTextureState.enabled = true;
+
+wgpu::RenderPipelineDescriptor pipelineDesc = ...;
+pipelineDesc.multisample.count = 4;
+pipelineDesc.multisample.nextInChain = &pipelineExpandResolveTextureState;
+
+auto pipeline = device.CreateRenderPipeline(&pipelineDesc);
// Create another render pass with "ExpandResolveTexture" LoadOp.
// Even though we discard the previous content of the MSAA texture,
@@ -46,6 +56,7 @@
= wgpu::LoadOp::ExpandResolveTexture;
auto renderPassEncoder2 = encoder.BeginRenderPass(&renderPassDesc2);
+renderPassEncoder2.SetPipeline(pipeline);
renderPassEncoder2.Draw(3);
renderPassEncoder2.End();
@@ -53,5 +64,7 @@
Notes:
- If a resolve texture is used in a `wgpu::LoadOp::ExpandResolveTexture` operation, it must have `wgpu::TextureUsage::TextureBinding` usage.
+ - If `wgpu::MultisampleStateExpandResolveTextureDawn` chained struct is not included in a `wgpu::RenderPipelineDescriptor::MultisampleState` or if it is included but `enabled` boolean flag is false, then the result render pipeline cannot be used in a render pass using `ExpandResolveTexture` load op.
+ - Similarly, a render pipeline created with `wgpu::MultisampleStateExpandResolveTextureDawn`'s `enabled` flag = `true` won't be able to be used in normal render passes.
- Currently only one color attachment is supported and the `ExpandResolveTexture` LoadOp only works on color attachment, this could be changed in future.
- The texture is not supported if it is not resolvable by WebGPU standard. This means this feature currently doesn't work with integer textures.
diff --git a/docs/dawn/features/msaa_render_to_single_samples.md b/docs/dawn/features/msaa_render_to_single_samples.md
index a03c12d..7c13f17 100644
--- a/docs/dawn/features/msaa_render_to_single_samples.md
+++ b/docs/dawn/features/msaa_render_to_single_samples.md
@@ -14,14 +14,8 @@
auto texture = device.CreateTexture(&desc);
-// Create a render pipeline to be used in a "implicit multi-sampled" render pass.
-wgpu::DawnMultisampleStateRenderToSingleSampled pipelineMSAARenderToSingleSampledDesc;
-pipelineMSAARenderToSingleSampledDesc.enabled = true;
-
+// Create a render pipeline
wgpu::RenderPipelineDescriptor pipelineDesc = ...;
-pipelineDesc.multisample.count = 4;
-pipelineDesc.multisample.nextInChain = &pipelineMSAARenderToSingleSampledDesc;
-
auto pipeline = device.CreateRenderPipeline(&pipelineDesc);
// Create a render pass with "implicit multi-sampled" enabled.
@@ -43,8 +37,6 @@
Notes:
- If a texture needs to be used as an attachment in a "implicit multi-sampled" render pass, it must have `wgpu::TextureUsage::TextureBinding` usage.
- - If `wgpu::DawnMultisampleStateRenderToSingleSampled` chained struct is not included in a `wgpu::RenderPipelineDescriptor::MultisampleState` or if it is included but `enabled` boolean flag is false, then the result render pipeline cannot be used in a "implicit multi-sampled" render pass.
- - Similarly, a render pipeline created with `wgpu::DawnMultisampleStateRenderToSingleSampled`'s `enabled` flag = `true` won't be able to be used in normal render passes.
- If a texture is attached to a "implicit multi-sampled" render pass. It must be single-sampled. It mustn't be assigned to the `resolveTarget` field of the the render pass' color attachment.
- Depth stencil textures can be attached to a "implicit multi-sampled" render pass. But its sample count must match the number specified in one color attachment's `wgpu::DawnRenderPassColorAttachmentRenderToSingleSampled`'s `implicitSampleCount` field.
- Currently only one color attachment is supported, this could be changed in future.
diff --git a/src/dawn/dawn.json b/src/dawn/dawn.json
index 761f46f..2acb36d 100644
--- a/src/dawn/dawn.json
+++ b/src/dawn/dawn.json
@@ -3337,6 +3337,16 @@
},
"dawn multisample state render to single sampled": {
+ "tags": ["dawn", "deprecated"],
+ "category": "structure",
+ "chained": "in",
+ "chain roots": ["multisample state"],
+ "members": [
+ {"name": "enabled", "type": "bool", "default": "false"}
+ ]
+ },
+
+ "multisample state expand resolve texture dawn": {
"tags": ["dawn"],
"category": "structure",
"chained": "in",
@@ -3740,7 +3750,7 @@
{"value": 1010, "name": "request adapter options LUID", "tags": ["dawn", "native"]},
{"value": 1011, "name": "request adapter options get GL proc", "tags": ["dawn", "native"]},
{"value": 1012, "name": "request adapter options D3D11 device", "tags": ["dawn", "native"]},
- {"value": 1013, "name": "dawn multisample state render to single sampled", "tags": ["dawn"]},
+ {"value": 1013, "name": "dawn multisample state render to single sampled", "tags": ["dawn", "deprecated"]},
{"value": 1014, "name": "dawn render pass color attachment render to single sampled", "tags": ["dawn"]},
{"value": 1015, "name": "render pass pixel local storage", "tags": ["dawn"]},
{"value": 1016, "name": "pipeline layout pixel local storage", "tags": ["dawn"]},
@@ -3754,6 +3764,7 @@
{"value": 1024, "name": "dawn WGSL blocklist", "tags": ["dawn", "native"]},
{"value": 1025, "name": "drm format capabilities", "tags": ["dawn"]},
{"value": 1026, "name": "shader module compilation options", "tags": ["dawn"]},
+ {"value": 1027, "name": "multisample state expand resolve texture dawn", "tags": ["dawn"]},
{"value": 1100, "name": "shared texture memory vk image descriptor", "tags": ["dawn", "native"]},
{"value": 1101, "name": "shared texture memory vk dedicated allocation descriptor", "tags": ["dawn", "native"]},
diff --git a/src/dawn/native/AttachmentState.cpp b/src/dawn/native/AttachmentState.cpp
index 099c70d..18bae63 100644
--- a/src/dawn/native/AttachmentState.cpp
+++ b/src/dawn/native/AttachmentState.cpp
@@ -64,9 +64,9 @@
const PipelineLayoutBase* layout)
: ObjectBase(device), mSampleCount(descriptor->multisample.count) {
UnpackedPtr<MultisampleState> unpackedMultisampleState = Unpack(&descriptor->multisample);
- if (auto* msaaRenderToSingleSampledDesc =
- unpackedMultisampleState.Get<DawnMultisampleStateRenderToSingleSampled>()) {
- mIsMSAARenderToSingleSampledEnabled = msaaRenderToSingleSampledDesc->enabled;
+ if (auto* msaaExpandResolveState =
+ unpackedMultisampleState.Get<MultisampleStateExpandResolveTextureDawn>()) {
+ mHasExpandResolveLoadOp = msaaExpandResolveState->enabled;
}
if (descriptor->fragment != nullptr) {
@@ -112,7 +112,6 @@
if (msaaRenderToSingleSampledDesc != nullptr &&
msaaRenderToSingleSampledDesc->implicitSampleCount > 1) {
attachmentSampleCount = msaaRenderToSingleSampledDesc->implicitSampleCount;
- mIsMSAARenderToSingleSampledEnabled = true;
} else {
attachmentSampleCount = attachment->GetTexture()->GetSampleCount();
}
@@ -122,6 +121,10 @@
} else {
DAWN_ASSERT(mSampleCount == attachmentSampleCount);
}
+
+ if (colorAttachment.loadOp == wgpu::LoadOp::ExpandResolveTexture) {
+ mHasExpandResolveLoadOp = true;
+ }
}
// Gather the depth-stencil information.
@@ -163,7 +166,7 @@
mColorFormats = blueprint.mColorFormats;
mDepthStencilFormat = blueprint.mDepthStencilFormat;
mSampleCount = blueprint.mSampleCount;
- mIsMSAARenderToSingleSampledEnabled = blueprint.mIsMSAARenderToSingleSampledEnabled;
+ mHasExpandResolveLoadOp = blueprint.mHasExpandResolveLoadOp;
mHasPLS = blueprint.mHasPLS;
mStorageAttachmentSlots = blueprint.mStorageAttachmentSlots;
SetContentHash(blueprint.GetContentHash());
@@ -199,7 +202,7 @@
}
// Both attachment state must either enable MSAA render to single sampled or disable it.
- if (a->mIsMSAARenderToSingleSampledEnabled != b->mIsMSAARenderToSingleSampledEnabled) {
+ if (a->mHasExpandResolveLoadOp != b->mHasExpandResolveLoadOp) {
return false;
}
@@ -235,7 +238,7 @@
HashCombine(&hash, mSampleCount);
// Hash MSAA render to single sampled flag
- HashCombine(&hash, mIsMSAARenderToSingleSampledEnabled);
+ HashCombine(&hash, mHasExpandResolveLoadOp);
// Hash the PLS state
HashCombine(&hash, mHasPLS);
@@ -268,8 +271,8 @@
return mSampleCount;
}
-bool AttachmentState::IsMSAARenderToSingleSampledEnabled() const {
- return mIsMSAARenderToSingleSampledEnabled;
+bool AttachmentState::HasExpandResolveLoadOp() const {
+ return mHasExpandResolveLoadOp;
}
bool AttachmentState::HasPixelLocalStorage() const {
diff --git a/src/dawn/native/AttachmentState.h b/src/dawn/native/AttachmentState.h
index 5513ad3..7f66669 100644
--- a/src/dawn/native/AttachmentState.h
+++ b/src/dawn/native/AttachmentState.h
@@ -66,7 +66,7 @@
bool HasDepthStencilAttachment() const;
wgpu::TextureFormat GetDepthStencilFormat() const;
uint32_t GetSampleCount() const;
- bool IsMSAARenderToSingleSampledEnabled() const;
+ bool HasExpandResolveLoadOp() const;
bool HasPixelLocalStorage() const;
const std::vector<wgpu::TextureFormat>& GetStorageAttachmentSlots() const;
std::vector<ColorAttachmentIndex> ComputeStorageAttachmentPackingInColorAttachments() const;
@@ -86,11 +86,7 @@
wgpu::TextureFormat mDepthStencilFormat = wgpu::TextureFormat::Undefined;
uint32_t mSampleCount = 0;
- // TODO(dawn:1710): This flag needs to be revised. Either remove MSAARenderToSingleSampled
- // feature or implement it using native extension such as
- // VK_EXT_multisampled_render_to_single_sampled. The native implementation doesn't need graphics
- // pipeline and render pass to be strictly compatible.
- bool mIsMSAARenderToSingleSampledEnabled = false;
+ bool mHasExpandResolveLoadOp = false;
bool mHasPLS = false;
std::vector<wgpu::TextureFormat> mStorageAttachmentSlots;
};
diff --git a/src/dawn/native/BlitColorToColorWithDraw.cpp b/src/dawn/native/BlitColorToColorWithDraw.cpp
index 920562e..dca0223 100644
--- a/src/dawn/native/BlitColorToColorWithDraw.cpp
+++ b/src/dawn/native/BlitColorToColorWithDraw.cpp
@@ -134,6 +134,9 @@
// Multisample state.
DAWN_ASSERT(sampleCount > 1);
renderPipelineDesc.multisample.count = sampleCount;
+ wgpu::MultisampleStateExpandResolveTextureDawn msaaExpandResolveState;
+ msaaExpandResolveState.enabled = true;
+ renderPipelineDesc.multisample.nextInChain = &msaaExpandResolveState;
// Bind group layout.
Ref<BindGroupLayoutBase> bindGroupLayout;
diff --git a/src/dawn/native/RenderPipeline.cpp b/src/dawn/native/RenderPipeline.cpp
index 5a49efc..eff2434 100644
--- a/src/dawn/native/RenderPipeline.cpp
+++ b/src/dawn/native/RenderPipeline.cpp
@@ -353,15 +353,17 @@
MaybeError ValidateMultisampleState(const DeviceBase* device, const MultisampleState* descriptor) {
UnpackedPtr<MultisampleState> unpacked;
DAWN_TRY_ASSIGN(unpacked, ValidateAndUnpack(descriptor));
- if (unpacked.Get<DawnMultisampleStateRenderToSingleSampled>()) {
- DAWN_INVALID_IF(!device->HasFeature(Feature::MSAARenderToSingleSampled),
- "The msaaRenderToSingleSampledDesc is not empty while the "
- "msaa-render-to-single-sampled feature is not enabled.");
+ if (unpacked.Get<MultisampleStateExpandResolveTextureDawn>()) {
+ DAWN_INVALID_IF(!device->HasFeature(Feature::DawnLoadResolveTexture),
+ "The MultisampleStateExpandResolveTextureDawn struct is used while the "
+ "%s feature is not enabled.",
+ ToAPI(Feature::DawnLoadResolveTexture));
- DAWN_INVALID_IF(descriptor->count <= 1,
- "The msaaRenderToSingleSampledDesc is not empty while multisample count "
- "(%u) is not > 1.",
- descriptor->count);
+ DAWN_INVALID_IF(
+ descriptor->count <= 1,
+ "The MultisampleStateExpandResolveTextureDawn struct is used while multisample count "
+ "(%u) is not > 1.",
+ descriptor->count);
}
DAWN_INVALID_IF(!IsValidSampleCount(descriptor->count),
diff --git a/src/dawn/native/webgpu_absl_format.cpp b/src/dawn/native/webgpu_absl_format.cpp
index dfe7353..4a7febf 100644
--- a/src/dawn/native/webgpu_absl_format.cpp
+++ b/src/dawn/native/webgpu_absl_format.cpp
@@ -355,9 +355,8 @@
s->Append(absl::StrFormat("sampleCount: %u", value->GetSampleCount()));
- if (value->GetDevice()->HasFeature(Feature::MSAARenderToSingleSampled)) {
- s->Append(absl::StrFormat(", msaaRenderToSingleSampled: %d",
- value->IsMSAARenderToSingleSampledEnabled()));
+ if (value->GetDevice()->HasFeature(Feature::DawnLoadResolveTexture)) {
+ s->Append(absl::StrFormat(", hasExpandResolveLoadOp: %d", value->HasExpandResolveLoadOp()));
}
if (value->HasPixelLocalStorage()) {
diff --git a/src/dawn/tests/end2end/MultisampledRenderingTests.cpp b/src/dawn/tests/end2end/MultisampledRenderingTests.cpp
index f7ecf3c..b6675cc 100644
--- a/src/dawn/tests/end2end/MultisampledRenderingTests.cpp
+++ b/src/dawn/tests/end2end/MultisampledRenderingTests.cpp
@@ -62,7 +62,7 @@
uint32_t sampleMask = 0xFFFFFFFF,
bool alphaToCoverageEnabled = false,
bool flipTriangle = false,
- bool enableMSAARenderToSingleSampled = false) {
+ bool enableExpandResolveLoadOp = false) {
const char* kFsOneOutputWithDepth = R"(
struct U {
color : vec4f,
@@ -95,13 +95,13 @@
const char* fs = testDepth ? kFsOneOutputWithDepth : kFsOneOutputWithoutDepth;
return CreateRenderPipelineForTest(fs, 1, testDepth, sampleMask, alphaToCoverageEnabled,
- flipTriangle, enableMSAARenderToSingleSampled);
+ flipTriangle, enableExpandResolveLoadOp);
}
wgpu::RenderPipeline CreateRenderPipelineWithTwoOutputsForTest(
uint32_t sampleMask = 0xFFFFFFFF,
bool alphaToCoverageEnabled = false,
- bool enableMSAARenderToSingleSampled = false) {
+ bool enableExpandResolveLoadOp = false) {
const char* kFsTwoOutputs = R"(
struct U {
color0 : vec4f,
@@ -123,13 +123,13 @@
return CreateRenderPipelineForTest(kFsTwoOutputs, 2, false, sampleMask,
alphaToCoverageEnabled, /*flipTriangle=*/false,
- enableMSAARenderToSingleSampled);
+ enableExpandResolveLoadOp);
}
wgpu::RenderPipeline CreateRenderPipelineWithNonZeroLocationOutputForTest(
uint32_t sampleMask = 0xFFFFFFFF,
bool alphaToCoverageEnabled = false,
- bool enableMSAARenderToSingleSampled = false) {
+ bool enableExpandResolveLoadOp = false) {
const char* kFsNonZeroLocationOutputs = R"(
struct U {
color : vec4f
@@ -142,7 +142,7 @@
return CreateRenderPipelineForTest(kFsNonZeroLocationOutputs, 1, false, sampleMask,
alphaToCoverageEnabled, /*flipTriangle=*/false,
- enableMSAARenderToSingleSampled, 1);
+ enableExpandResolveLoadOp, 1);
}
wgpu::Texture CreateTextureForRenderAttachment(wgpu::TextureFormat format,
@@ -271,7 +271,7 @@
uint32_t sampleMask = 0xFFFFFFFF,
bool alphaToCoverageEnabled = false,
bool flipTriangle = false,
- bool enableMSAARenderToSingleSampled = false,
+ bool enableExpandResolveLoadOp = false,
uint32_t firstAttachmentLocation = 0) {
utils::ComboRenderPipelineDescriptor pipelineDescriptor;
@@ -319,10 +319,10 @@
pipelineDescriptor.multisample.mask = sampleMask;
pipelineDescriptor.multisample.alphaToCoverageEnabled = alphaToCoverageEnabled;
- wgpu::DawnMultisampleStateRenderToSingleSampled msaaRenderToSingleSampledDesc;
- if (enableMSAARenderToSingleSampled) {
- msaaRenderToSingleSampledDesc.enabled = true;
- pipelineDescriptor.multisample.nextInChain = &msaaRenderToSingleSampledDesc;
+ wgpu::MultisampleStateExpandResolveTextureDawn msaaExpandResolveDesc;
+ if (enableExpandResolveLoadOp) {
+ msaaExpandResolveDesc.enabled = true;
+ pipelineDescriptor.multisample.nextInChain = &msaaExpandResolveDesc;
}
pipelineDescriptor.cFragment.targetCount = numColorAttachments + firstAttachmentLocation;
@@ -1373,7 +1373,7 @@
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
wgpu::RenderPipeline pipeline = CreateRenderPipelineWithOneOutputForTest(
/*testDepth=*/false, /*sampleMask=*/0xFFFFFFFF, /*alphaToCoverageEnabled=*/false,
- /*flipTriangle=*/false, /*enableMSAARenderToSingleSampled=*/true);
+ /*flipTriangle=*/false, /*enableExpandResolveLoadOp=*/false);
constexpr wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, 0.8f};
@@ -1420,7 +1420,7 @@
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
wgpu::RenderPipeline pipeline = CreateRenderPipelineWithOneOutputForTest(
/*testDepth=*/false, /*sampleMask=*/0xFFFFFFFF, /*alphaToCoverageEnabled=*/false,
- /*flipTriangle=*/false, /*enableMSAARenderToSingleSampled=*/true);
+ /*flipTriangle=*/false, /*enableExpandResolveLoadOp=*/false);
constexpr wgpu::Color kRed = {1.0f, 0.0f, 0.0f, 1.0f};
constexpr wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, 0.8f};
@@ -1474,7 +1474,7 @@
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
wgpu::RenderPipeline pipeline = CreateRenderPipelineWithOneOutputForTest(
/*testDepth=*/true, /*sampleMask=*/0xFFFFFFFF, /*alphaToCoverageEnabled=*/false,
- /*flipTriangle=*/false, /*enableMSAARenderToSingleSampled=*/true);
+ /*flipTriangle=*/false, /*enableExpandResolveLoadOp=*/false);
constexpr wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, 0.8f};
constexpr wgpu::Color kRed = {0.8f, 0.0f, 0.0f, 0.8f};
@@ -1555,7 +1555,7 @@
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
wgpu::RenderPipeline pipeline = CreateRenderPipelineWithOneOutputForTest(
/*testDepth=*/false, /*sampleMask=*/0xFFFFFFFF, /*alphaToCoverageEnabled=*/false,
- /*flipTriangle=*/false, /*enableMSAARenderToSingleSampled=*/false);
+ /*flipTriangle=*/false, /*enableExpandResolveLoadOp=*/false);
constexpr wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, 0.8f};
@@ -1587,6 +1587,79 @@
VerifyResolveTarget(kGreen, singleSampledTexture);
}
+// Test ExpandResolveTexture load op rendering with depth test works correctly.
+TEST_P(DawnLoadResolveTextureTest, DrawWithDepthTest) {
+ auto multiSampledTexture = CreateTextureForRenderAttachment(
+ kColorFormat, 4, 1, 1,
+ /*transientAttachment=*/device.HasFeature(wgpu::FeatureName::TransientAttachments),
+ /*supportsTextureBinding=*/false);
+ auto multiSampledTextureView = multiSampledTexture.CreateView();
+
+ auto singleSampledTexture =
+ CreateTextureForRenderAttachment(kColorFormat, 1, 1, 1, /*transientAttachment=*/false,
+ /*supportsTextureBinding=*/true);
+
+ auto singleSampledTextureView = singleSampledTexture.CreateView();
+
+ wgpu::RenderPipeline pipeline = CreateRenderPipelineWithOneOutputForTest(
+ /*testDepth=*/true, /*sampleMask=*/0xFFFFFFFF, /*alphaToCoverageEnabled=*/false,
+ /*flipTriangle=*/false, /*enableExpandResolveLoadOp=*/true);
+
+ wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
+
+ constexpr wgpu::Color kGreen = {0.0f, 0.8f, 0.0f, 0.8f};
+ constexpr wgpu::Color kRed = {0.8f, 0.0f, 0.0f, 0.8f};
+
+ // In first render pass we clear the render pass without drawing anything
+ {
+ utils::ComboRenderPassDescriptor renderPass = CreateComboRenderPassDescriptorForTest(
+ {multiSampledTextureView}, {singleSampledTextureView}, wgpu::LoadOp::Clear,
+ wgpu::LoadOp::Clear,
+ /*testDepth=*/true);
+ renderPass.cColorAttachments[0].storeOp = wgpu::StoreOp::Discard;
+
+ wgpu::RenderPassEncoder renderPassEncoder = commandEncoder.BeginRenderPass(&renderPass);
+ renderPassEncoder.End();
+ }
+
+ // In 2nd render pass we draw a green triangle with depth value == 0.2f.
+ {
+ utils::ComboRenderPassDescriptor renderPass = CreateComboRenderPassDescriptorForTest(
+ {multiSampledTextureView}, {singleSampledTextureView},
+ wgpu::LoadOp::ExpandResolveTexture, wgpu::LoadOp::Clear,
+ /*testDepth=*/true);
+ renderPass.cColorAttachments[0].storeOp = wgpu::StoreOp::Discard;
+
+ std::array<float, 8> kUniformData = {kGreen.r, kGreen.g, kGreen.b, kGreen.a, // Color
+ 0.2f}; // depth
+ constexpr uint32_t kSize = sizeof(kUniformData);
+ EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, kUniformData.data(), kSize);
+ }
+
+ // In 3rd render pass we draw a red triangle with depth value == 0.5f.
+ // This red triangle should not be displayed because it is behind the green one that is drawn in
+ // the last render pass.
+ {
+ utils::ComboRenderPassDescriptor renderPass = CreateComboRenderPassDescriptorForTest(
+ {multiSampledTextureView}, {singleSampledTextureView},
+ wgpu::LoadOp::ExpandResolveTexture, wgpu::LoadOp::Load,
+ /*testDepth=*/true);
+ renderPass.cColorAttachments[0].storeOp = wgpu::StoreOp::Discard;
+
+ std::array<float, 8> kUniformData = {kRed.r, kRed.g, kRed.b, kRed.a, // color
+ 0.5f}; // depth
+ constexpr uint32_t kSize = sizeof(kUniformData);
+ EncodeRenderPassForTest(commandEncoder, renderPass, pipeline, kUniformData.data(), kSize);
+ }
+
+ wgpu::CommandBuffer commandBuffer = commandEncoder.Finish();
+ queue.Submit(1, &commandBuffer);
+
+ // The color of the pixel in the middle of mResolveTexture should be green if MSAA resolve runs
+ // correctly with depth test.
+ VerifyResolveTarget(kGreen, singleSampledTexture);
+}
+
DAWN_INSTANTIATE_TEST(MultisampledRenderingTest,
D3D11Backend(),
D3D12Backend(),
diff --git a/src/dawn/tests/unittests/validation/RenderPipelineValidationTests.cpp b/src/dawn/tests/unittests/validation/RenderPipelineValidationTests.cpp
index 4d67aac..a43dbe4 100644
--- a/src/dawn/tests/unittests/validation/RenderPipelineValidationTests.cpp
+++ b/src/dawn/tests/unittests/validation/RenderPipelineValidationTests.cpp
@@ -1866,16 +1866,16 @@
}
}
-// Creating render pipeline with DawnMultisampleStateRenderToSingleSampled without enabling
-// MSAARenderToSingleSampled feature should result in error.
-TEST_F(RenderPipelineValidationTest, MSAARenderToSingleSampledOnUnsupportedDevice) {
+// Creating render pipeline with MultisampleStateExpandResolveTextureDawn without enabling
+// LoadResolveTexture feature should result in error.
+TEST_F(RenderPipelineValidationTest, LoadResolveTextureOnUnsupportedDevice) {
utils::ComboRenderPipelineDescriptor pipelineDescriptor;
pipelineDescriptor.vertex.module = vsModule;
pipelineDescriptor.cFragment.module = fsModule;
- wgpu::DawnMultisampleStateRenderToSingleSampled pipelineMSAARenderToSingleSampledDesc;
- pipelineMSAARenderToSingleSampledDesc.enabled = true;
- pipelineDescriptor.multisample.nextInChain = &pipelineMSAARenderToSingleSampledDesc;
+ wgpu::MultisampleStateExpandResolveTextureDawn pipelineMSAAExpandResolveDesc;
+ pipelineMSAAExpandResolveDesc.enabled = true;
+ pipelineDescriptor.multisample.nextInChain = &pipelineMSAAExpandResolveDesc;
pipelineDescriptor.multisample.count = 4;
ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&pipelineDescriptor),
@@ -2289,8 +2289,7 @@
ASSERT_DEVICE_ERROR(encoder.Finish());
}
-class MSAARenderToSingleSampledPipelineDescriptorValidationTest
- : public RenderPipelineValidationTest {
+class LoadResolveTexturePipelineDescriptorValidationTest : public RenderPipelineValidationTest {
protected:
void SetUp() override {
RenderPipelineValidationTest::SetUp();
@@ -2305,7 +2304,7 @@
WGPUDevice CreateTestDevice(dawn::native::Adapter dawnAdapter,
wgpu::DeviceDescriptor descriptor) override {
- wgpu::FeatureName requiredFeatures[1] = {wgpu::FeatureName::MSAARenderToSingleSampled};
+ wgpu::FeatureName requiredFeatures[1] = {wgpu::FeatureName::DawnLoadResolveTexture};
descriptor.requiredFeatures = requiredFeatures;
descriptor.requiredFeatureCount = 1;
return dawnAdapter.CreateDevice(&descriptor);
@@ -2326,22 +2325,21 @@
wgpu::ShaderModule fsWithTextureModule;
};
-// Test that creating and using a render pipeline with DawnMultisampleStateRenderToSingleSampled
+// Test that creating and using a render pipeline with MultisampleStateExpandResolveTextureDawn
// chained struct should success.
-TEST_F(MSAARenderToSingleSampledPipelineDescriptorValidationTest, ValidUse) {
+TEST_F(LoadResolveTexturePipelineDescriptorValidationTest, ValidUse) {
constexpr uint32_t kSampleCount = 4;
+ auto msaaTexture = CreateTexture(wgpu::TextureUsage::RenderAttachment, kSampleCount);
+
// Create single sampled texture.
auto texture =
CreateTexture(wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding, 1);
- // Create render pass (with DawnRenderPassColorAttachmentRenderToSingleSampled).
- utils::ComboRenderPassDescriptor renderPassDescriptor({texture.CreateView()});
- renderPassDescriptor.cColorAttachments[0].loadOp = wgpu::LoadOp::Load;
-
- wgpu::DawnRenderPassColorAttachmentRenderToSingleSampled renderPassRenderToSingleSampledDesc;
- renderPassRenderToSingleSampledDesc.implicitSampleCount = kSampleCount;
- renderPassDescriptor.cColorAttachments[0].nextInChain = &renderPassRenderToSingleSampledDesc;
+ // Create render pass (with ExpandResolveTexture load op).
+ utils::ComboRenderPassDescriptor renderPassDescriptor({msaaTexture.CreateView()});
+ renderPassDescriptor.cColorAttachments[0].loadOp = wgpu::LoadOp::ExpandResolveTexture;
+ renderPassDescriptor.cColorAttachments[0].resolveTarget = texture.CreateView();
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::RenderPassEncoder renderPass = encoder.BeginRenderPass(&renderPassDescriptor);
@@ -2351,9 +2349,9 @@
pipelineDescriptor.vertex.module = vsModule;
pipelineDescriptor.cFragment.module = fsWithTextureModule;
- wgpu::DawnMultisampleStateRenderToSingleSampled pipelineMSAARenderToSingleSampledDesc;
- pipelineMSAARenderToSingleSampledDesc.enabled = true;
- pipelineDescriptor.multisample.nextInChain = &pipelineMSAARenderToSingleSampledDesc;
+ wgpu::MultisampleStateExpandResolveTextureDawn pipelineMSAAExpandResolveDesc;
+ pipelineMSAAExpandResolveDesc.enabled = true;
+ pipelineDescriptor.multisample.nextInChain = &pipelineMSAAExpandResolveDesc;
pipelineDescriptor.multisample.count = kSampleCount;
wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pipelineDescriptor);
@@ -2371,33 +2369,34 @@
encoder.Finish();
}
-// If a render pipeline's MultisampleState contains DawnMultisampleStateRenderToSingleSampled
+// If a render pipeline's MultisampleState contains MultisampleStateExpandResolveTextureDawn
// chained struct. Then its sampleCount must be > 1.
-TEST_F(MSAARenderToSingleSampledPipelineDescriptorValidationTest,
+TEST_F(LoadResolveTexturePipelineDescriptorValidationTest,
PipelineSampleCountMustBeGreaterThanOne) {
utils::ComboRenderPipelineDescriptor pipelineDescriptor;
pipelineDescriptor.vertex.module = vsModule;
pipelineDescriptor.cFragment.module = fsModule;
- wgpu::DawnMultisampleStateRenderToSingleSampled pipelineMSAARenderToSingleSampledDesc;
- pipelineMSAARenderToSingleSampledDesc.enabled = true;
- pipelineDescriptor.multisample.nextInChain = &pipelineMSAARenderToSingleSampledDesc;
+ wgpu::MultisampleStateExpandResolveTextureDawn pipelineMSAAExpandResolveDesc;
+ pipelineMSAAExpandResolveDesc.enabled = true;
+ pipelineDescriptor.multisample.nextInChain = &pipelineMSAAExpandResolveDesc;
pipelineDescriptor.multisample.count = 1;
ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&pipelineDescriptor),
testing::HasSubstr("multisample count (1) is not > 1"));
}
-// If a render pipeline is created with MSAA render to single sampled enabled , then it cannot be
-// used in a render pass that wasn't created with that feature enabled.
-TEST_F(MSAARenderToSingleSampledPipelineDescriptorValidationTest,
+// If a render pipeline is created with MultisampleStateExpandResolveTextureDawn.enabled =
+// true, then it cannot be used in a render pass that wasn't created with ExpandResolveTexture load
+// op.
+TEST_F(LoadResolveTexturePipelineDescriptorValidationTest,
MSAARenderToSingleSampledPipeline_UseIn_NormalRenderPass_Error) {
constexpr uint32_t kSampleCount = 4;
// Create MSAA texture.
auto texture = CreateTexture(wgpu::TextureUsage::RenderAttachment, 4);
- // Create render pass (without DawnRenderPassColorAttachmentRenderToSingleSampled).
+ // Create render pass (without ExpandResolveTexture load op).
utils::ComboRenderPassDescriptor renderPassDescriptor({texture.CreateView()});
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
@@ -2408,9 +2407,9 @@
pipelineDescriptor.vertex.module = vsModule;
pipelineDescriptor.cFragment.module = fsModule;
- wgpu::DawnMultisampleStateRenderToSingleSampled pipelineMSAARenderToSingleSampledDesc;
- pipelineMSAARenderToSingleSampledDesc.enabled = true;
- pipelineDescriptor.multisample.nextInChain = &pipelineMSAARenderToSingleSampledDesc;
+ wgpu::MultisampleStateExpandResolveTextureDawn pipelineMSAAExpandResolveDesc;
+ pipelineMSAAExpandResolveDesc.enabled = true;
+ pipelineDescriptor.multisample.nextInChain = &pipelineMSAAExpandResolveDesc;
pipelineDescriptor.multisample.count = kSampleCount;
wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pipelineDescriptor);
@@ -2420,26 +2419,28 @@
ASSERT_DEVICE_ERROR(encoder.Finish());
}
-// Using a normal render pipeline in a MSAA render to single sampled render pass should result in
+// Using a normal render pipeline in a ExpandResolveTexture render pass should result in
// incompatible error.
-TEST_F(MSAARenderToSingleSampledPipelineDescriptorValidationTest,
- NormalPipeline_Use_In_MSAARenderToSingleSampledRenderPass_Error) {
+TEST_F(LoadResolveTexturePipelineDescriptorValidationTest,
+ NormalPipeline_Use_In_ExpandResolveTextureRenderPass_Error) {
constexpr uint32_t kSampleCount = 4;
+ // Create multi sampled texture.
+ auto msaaTexture = CreateTexture(wgpu::TextureUsage::RenderAttachment, kSampleCount);
+
// Create single sampled texture.
auto texture =
CreateTexture(wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding, 1);
- // Create render pass (with DawnRenderPassColorAttachmentRenderToSingleSampled).
- utils::ComboRenderPassDescriptor renderPassDescriptor({texture.CreateView()});
- wgpu::DawnRenderPassColorAttachmentRenderToSingleSampled renderPassRenderToSingleSampledDesc;
- renderPassRenderToSingleSampledDesc.implicitSampleCount = kSampleCount;
- renderPassDescriptor.cColorAttachments[0].nextInChain = &renderPassRenderToSingleSampledDesc;
+ // Create render pass (with ExpandResolveTexture load op).
+ utils::ComboRenderPassDescriptor renderPassDescriptor({msaaTexture.CreateView()});
+ renderPassDescriptor.cColorAttachments[0].loadOp = wgpu::LoadOp::ExpandResolveTexture;
+ renderPassDescriptor.cColorAttachments[0].resolveTarget = texture.CreateView();
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::RenderPassEncoder renderPass = encoder.BeginRenderPass(&renderPassDescriptor);
- // Create render pipeline (without DawnMultisampleStateRenderToSingleSampled)
+ // Create render pipeline (without MultisampleStateExpandResolveTextureDawn)
utils::ComboRenderPipelineDescriptor pipelineDescriptor;
pipelineDescriptor.vertex.module = vsModule;
pipelineDescriptor.cFragment.module = fsModule;
@@ -2453,25 +2454,22 @@
ASSERT_DEVICE_ERROR(encoder.Finish());
}
-// Bind color attachment in the MSAA render to single sampled render pass as texture should result
+// Bind resolve attachment in a ExpandResolveTexture render pass as texture should result
// in error.
-TEST_F(MSAARenderToSingleSampledPipelineDescriptorValidationTest,
- BindColorAttachmentAsTextureError) {
+TEST_F(LoadResolveTexturePipelineDescriptorValidationTest, BindColorAttachmentAsTextureError) {
constexpr uint32_t kSampleCount = 4;
+ // Create multi sampled texture.
+ auto msaaTexture = CreateTexture(wgpu::TextureUsage::RenderAttachment, kSampleCount);
+
// Create single sampled texture.
- auto renderTexture =
- CreateTexture(wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding |
- wgpu::TextureUsage::TextureBinding,
- 1);
+ auto resolveTexture =
+ CreateTexture(wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding, 1);
- // Create render pass (with DawnRenderPassColorAttachmentRenderToSingleSampled).
- utils::ComboRenderPassDescriptor renderPassDescriptor({renderTexture.CreateView()});
- renderPassDescriptor.cColorAttachments[0].loadOp = wgpu::LoadOp::Load;
-
- wgpu::DawnRenderPassColorAttachmentRenderToSingleSampled renderPassRenderToSingleSampledDesc;
- renderPassRenderToSingleSampledDesc.implicitSampleCount = kSampleCount;
- renderPassDescriptor.cColorAttachments[0].nextInChain = &renderPassRenderToSingleSampledDesc;
+ // Create render pass (with ExpandResolveTexture load op).
+ utils::ComboRenderPassDescriptor renderPassDescriptor({msaaTexture.CreateView()});
+ renderPassDescriptor.cColorAttachments[0].loadOp = wgpu::LoadOp::ExpandResolveTexture;
+ renderPassDescriptor.cColorAttachments[0].resolveTarget = resolveTexture.CreateView();
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::RenderPassEncoder renderPass = encoder.BeginRenderPass(&renderPassDescriptor);
@@ -2481,16 +2479,16 @@
pipelineDescriptor.vertex.module = vsModule;
pipelineDescriptor.cFragment.module = fsWithTextureModule;
- wgpu::DawnMultisampleStateRenderToSingleSampled pipelineMSAARenderToSingleSampledDesc;
- pipelineMSAARenderToSingleSampledDesc.enabled = true;
- pipelineDescriptor.multisample.nextInChain = &pipelineMSAARenderToSingleSampledDesc;
+ wgpu::MultisampleStateExpandResolveTextureDawn pipelineMSAAExpandResolveDesc;
+ pipelineMSAAExpandResolveDesc.enabled = true;
+ pipelineDescriptor.multisample.nextInChain = &pipelineMSAAExpandResolveDesc;
pipelineDescriptor.multisample.count = kSampleCount;
wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pipelineDescriptor);
- // Use color attachment's texture as input texture.
+ // Use resolve attachment as input texture.
wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
- {{0, renderTexture.CreateView()}});
+ {{0, resolveTexture.CreateView()}});
renderPass.SetPipeline(pipeline);
renderPass.SetBindGroup(0, bindGroup);