| // Copyright 2021 The Dawn & Tint Authors |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are met: |
| // |
| // 1. Redistributions of source code must retain the above copyright notice, this |
| // list of conditions and the following disclaimer. |
| // |
| // 2. Redistributions in binary form must reproduce the above copyright notice, |
| // this list of conditions and the following disclaimer in the documentation |
| // and/or other materials provided with the distribution. |
| // |
| // 3. Neither the name of the copyright holder nor the names of its |
| // contributors may be used to endorse or promote products derived from |
| // this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
| // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| #include <optional> |
| #include <vector> |
| |
| #include "dawn/tests/DawnTest.h" |
| #include "dawn/utils/ComboRenderPipelineDescriptor.h" |
| #include "dawn/utils/TextureUtils.h" |
| #include "dawn/utils/WGPUHelpers.h" |
| |
| namespace dawn { |
| namespace { |
| |
| constexpr static uint32_t kSize = 4; |
| |
| using TextureFormat = wgpu::TextureFormat; |
| DAWN_TEST_PARAM_STRUCT(ReadOnlyDepthStencilAttachmentTestsParams, TextureFormat); |
| |
| class ReadOnlyDepthStencilAttachmentTests |
| : public DawnTestWithParams<ReadOnlyDepthStencilAttachmentTestsParams> { |
| protected: |
| void SetUp() override { |
| DawnTestWithParams<ReadOnlyDepthStencilAttachmentTestsParams>::SetUp(); |
| DAWN_TEST_UNSUPPORTED_IF(!mIsFormatSupported); |
| } |
| |
| std::vector<wgpu::FeatureName> GetRequiredFeatures() override { |
| switch (GetParam().mTextureFormat) { |
| case wgpu::TextureFormat::Depth32FloatStencil8: |
| if (SupportsFeatures({wgpu::FeatureName::Depth32FloatStencil8})) { |
| mIsFormatSupported = true; |
| return {wgpu::FeatureName::Depth32FloatStencil8}; |
| } |
| |
| return {}; |
| default: |
| mIsFormatSupported = true; |
| return {}; |
| } |
| } |
| |
| struct TestSpec { |
| wgpu::TextureAspect readonlyAspects; |
| std::optional<wgpu::TextureAspect> sampledAspect = std::nullopt; |
| |
| wgpu::CompareFunction depthCompare = wgpu::CompareFunction::Always; |
| wgpu::CompareFunction stencilCompare = wgpu::CompareFunction::Always; |
| bool depthWriteEnabled = false; |
| bool stencilWriteEnabled = false; |
| |
| float depthClearValue = 0.0; |
| uint32_t stencilClearValue = 0; |
| uint32_t stencilRef = 0; |
| |
| wgpu::Texture depthStencilTexture; |
| }; |
| |
| wgpu::RenderPipeline CreateRenderPipeline(wgpu::TextureFormat format, |
| const TestSpec& spec) const { |
| utils::ComboRenderPipelineDescriptor pipelineDescriptor; |
| |
| // Draw a rectangle via two triangles. The depth value of the top of the rectangle is 0.4. |
| // The depth value of the bottom is 0.0. The depth value gradually change from 0.4 to 0.0 |
| // from the top to the bottom. The top part will compare with the depth values and fail to |
| // pass the depth test. The bottom part will compare with the depth values in depth buffer |
| // and pass the depth test, and sample from the depth buffer in fragment shader in the same |
| // pipeline. |
| pipelineDescriptor.vertex.module = utils::CreateShaderModule(device, R"( |
| @vertex |
| fn main(@builtin(vertex_index) VertexIndex : u32) -> @builtin(position) vec4f { |
| var pos = array( |
| vec3f(-1.0, 1.0, 0.4), |
| vec3f(-1.0, -1.0, 0.0), |
| vec3f( 1.0, 1.0, 0.4), |
| vec3f( 1.0, 1.0, 0.4), |
| vec3f(-1.0, -1.0, 0.0), |
| vec3f( 1.0, -1.0, 0.0)); |
| return vec4f(pos[VertexIndex], 1.0); |
| })"); |
| |
| if (!spec.sampledAspect.has_value()) { |
| // Draw a solid blue into color buffer if not sample from depth/stencil attachment. |
| pipelineDescriptor.cFragment.module = utils::CreateShaderModule(device, R"( |
| @fragment fn main() -> @location(0) vec4f { |
| return vec4f(0.0, 0.0, 1.0, 0.0); |
| })"); |
| } else if (spec.sampledAspect == wgpu::TextureAspect::DepthOnly) { |
| // Sample from depth attachment and draw that sampled texel into color buffer. |
| pipelineDescriptor.cFragment.module = utils::CreateShaderModule(device, R"( |
| @group(0) @binding(0) var samp : sampler; |
| @group(0) @binding(1) var tex : texture_depth_2d; |
| |
| @fragment |
| fn main(@builtin(position) FragCoord : vec4f) -> @location(0) vec4f { |
| return vec4f(textureSample(tex, samp, FragCoord.xy), 0.0, 0.0, 0.0); |
| })"); |
| |
| } else { |
| DAWN_ASSERT(spec.sampledAspect == wgpu::TextureAspect::StencilOnly); |
| // Sample from stencil attachment and draw that sampled texel into color buffer. |
| pipelineDescriptor.cFragment.module = utils::CreateShaderModule(device, R"( |
| @group(0) @binding(0) var samp : sampler; |
| @group(0) @binding(1) var tex : texture_2d<u32>; |
| |
| @fragment |
| fn main(@builtin(position) FragCoord : vec4f) -> @location(0) vec4f { |
| _ = samp; |
| var texel = textureLoad(tex, vec2i(FragCoord.xy), 0); |
| return vec4f(f32(texel[0]) / 255.0, 0.0, 0.0, 0.0); |
| })"); |
| } |
| |
| wgpu::DepthStencilState* depthStencil = pipelineDescriptor.EnableDepthStencil(format); |
| depthStencil->depthCompare = spec.depthCompare; |
| depthStencil->depthWriteEnabled = spec.depthWriteEnabled; |
| depthStencil->stencilFront.compare = spec.stencilCompare; |
| if (spec.stencilWriteEnabled) { |
| depthStencil->stencilFront.passOp = wgpu::StencilOperation::Replace; |
| } |
| |
| return device.CreateRenderPipeline(&pipelineDescriptor); |
| } |
| |
| struct RenderResult { |
| wgpu::Texture color; |
| wgpu::Texture depthStencil; |
| }; |
| RenderResult DoRender(const TestSpec& spec) const { |
| wgpu::TextureFormat testFormat = GetParam().mTextureFormat; |
| |
| // Create or reuse the test textures. |
| wgpu::Texture depthStencilTexture = spec.depthStencilTexture; |
| if (!depthStencilTexture) { |
| wgpu::TextureDescriptor dsTextureDesc = {}; |
| dsTextureDesc.size = {kSize, kSize, 1}; |
| dsTextureDesc.format = testFormat; |
| dsTextureDesc.usage = |
| wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding; |
| depthStencilTexture = device.CreateTexture(&dsTextureDesc); |
| } |
| |
| wgpu::TextureDescriptor colorTextureDesc = {}; |
| colorTextureDesc.size = {kSize, kSize, 1}; |
| colorTextureDesc.format = wgpu::TextureFormat::RGBA8Unorm; |
| colorTextureDesc.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc; |
| wgpu::Texture colorTexture = device.CreateTexture(&colorTextureDesc); |
| |
| wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder(); |
| |
| // Do a first render pass that writes the initial values to the aspects that will be |
| // readonly. |
| if (!spec.depthStencilTexture) { |
| utils::ComboRenderPassDescriptor passDescriptorInit({}, |
| depthStencilTexture.CreateView()); |
| passDescriptorInit.UnsetDepthStencilLoadStoreOpsForFormat(testFormat); |
| passDescriptorInit.cDepthStencilAttachmentInfo.depthClearValue = spec.depthClearValue; |
| passDescriptorInit.cDepthStencilAttachmentInfo.stencilClearValue = |
| spec.stencilClearValue; |
| |
| wgpu::RenderPassEncoder passInit = commandEncoder.BeginRenderPass(&passDescriptorInit); |
| passInit.End(); |
| } |
| |
| // Do the render pass with the readonly attachment, that will potentially use the pipeline |
| // to read and/or write attachments. |
| utils::ComboRenderPassDescriptor passDescriptor({colorTexture.CreateView()}, |
| depthStencilTexture.CreateView()); |
| passDescriptor.cDepthStencilAttachmentInfo.depthLoadOp = wgpu::LoadOp::Load; |
| passDescriptor.cDepthStencilAttachmentInfo.stencilLoadOp = wgpu::LoadOp::Load; |
| passDescriptor.UnsetDepthStencilLoadStoreOpsForFormat(testFormat); |
| |
| if (spec.readonlyAspects != wgpu::TextureAspect::StencilOnly) { |
| passDescriptor.cDepthStencilAttachmentInfo.depthReadOnly = true; |
| passDescriptor.cDepthStencilAttachmentInfo.depthLoadOp = wgpu::LoadOp::Undefined; |
| passDescriptor.cDepthStencilAttachmentInfo.depthStoreOp = wgpu::StoreOp::Undefined; |
| } |
| if (spec.readonlyAspects != wgpu::TextureAspect::DepthOnly) { |
| passDescriptor.cDepthStencilAttachmentInfo.stencilReadOnly = true; |
| passDescriptor.cDepthStencilAttachmentInfo.stencilLoadOp = wgpu::LoadOp::Undefined; |
| passDescriptor.cDepthStencilAttachmentInfo.stencilStoreOp = wgpu::StoreOp::Undefined; |
| } |
| |
| // Create a render pass with readonly depth/stencil attachment. The attachment has already |
| // been initialized. The pipeline in this render pass will sample from the attachment. TODO |
| // The pipeline will read from the attachment to do depth/stencil test too. |
| wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&passDescriptor); |
| wgpu::RenderPipeline pipeline = CreateRenderPipeline(testFormat, spec); |
| pass.SetPipeline(pipeline); |
| pass.SetStencilReference(spec.stencilRef); |
| |
| // Bind the bindgroup is needed. |
| if (spec.sampledAspect.has_value()) { |
| wgpu::TextureViewDescriptor viewDesc = {}; |
| viewDesc.aspect = spec.sampledAspect.value(); |
| wgpu::TextureView view = depthStencilTexture.CreateView(&viewDesc); |
| |
| wgpu::BindGroup bindGroup = utils::MakeBindGroup( |
| device, pipeline.GetBindGroupLayout(0), {{0, device.CreateSampler()}, {1, view}}); |
| pass.SetBindGroup(0, bindGroup); |
| } |
| |
| pass.Draw(6); |
| pass.End(); |
| |
| wgpu::CommandBuffer commands = commandEncoder.Finish(); |
| queue.Submit(1, &commands); |
| |
| return {colorTexture, depthStencilTexture}; |
| } |
| |
| void CheckFullColor(wgpu::Texture color, utils::RGBA8 fullColor) { |
| std::vector<utils::RGBA8> expected(kSize * kSize, fullColor); |
| EXPECT_TEXTURE_EQ(expected.data(), color, {0, 0}, {kSize, kSize}); |
| } |
| |
| void CheckTopBottomColor(wgpu::Texture color, utils::RGBA8 topColor, utils::RGBA8 bottomColor) { |
| std::vector<utils::RGBA8> expectedTop(kSize * kSize / 2, topColor); |
| EXPECT_TEXTURE_EQ(expectedTop.data(), color, {0, 0}, {kSize, kSize / 2}); |
| std::vector<utils::RGBA8> expectedBottom(kSize * kSize / 2, bottomColor); |
| EXPECT_TEXTURE_EQ(expectedBottom.data(), color, {0, kSize / 2}, {kSize, kSize / 2}); |
| } |
| |
| private: |
| bool mIsFormatSupported = false; |
| }; |
| |
| class ReadOnlyDepthAttachmentTests : public ReadOnlyDepthStencilAttachmentTests {}; |
| |
| TEST_P(ReadOnlyDepthAttachmentTests, SampleFromAttachment) { |
| // TODO(dawn:2163): The texture reads zeroes, maybe ANGLE's TextureStorageD3D11 is missing a |
| // copy between the storages? |
| DAWN_SUPPRESS_TEST_IF(IsANGLED3D11()); |
| |
| // TODO(crbug.com/dawn/2295): diagnose this failure on Pixel 4 OpenGLES |
| DAWN_SUPPRESS_TEST_IF(IsOpenGLES() && IsAndroid() && IsQualcomm()); |
| |
| TestSpec spec; |
| spec.readonlyAspects = wgpu::TextureAspect::DepthOnly; |
| spec.sampledAspect = wgpu::TextureAspect::DepthOnly; |
| spec.depthCompare = wgpu::CompareFunction::LessEqual; |
| spec.depthClearValue = 0.2; |
| auto render = DoRender(spec); |
| |
| // The top part is not rendered by the pipeline. Its color is the default clear color for |
| // color attachment. |
| // The bottom part is rendered, whose red channel is sampled from depth attachment, which |
| // is initialized into 0.2. |
| CheckTopBottomColor(render.color, {0, 0, 0, 0}, {static_cast<uint8_t>(0.2 * 255), 0, 0, 0}); |
| } |
| |
| TEST_P(ReadOnlyDepthAttachmentTests, NotSampleFromAttachment) { |
| TestSpec spec; |
| spec.readonlyAspects = wgpu::TextureAspect::DepthOnly; |
| spec.depthCompare = wgpu::CompareFunction::LessEqual; |
| spec.depthClearValue = 0.2; |
| auto render = DoRender(spec); |
| |
| // The top part is not rendered by the pipeline. Its color is the default clear color for |
| // color attachment. |
| // The bottom part is rendered. Its color is set to blue. |
| CheckTopBottomColor(render.color, {0, 0, 0, 0}, {0, 0, 255, 0}); |
| } |
| |
| // Regression test for crbug.com/dawn/1512 where having aspectReadOnly for an unused aspect of a |
| // depth-stencil texture would cause the attachment to be considered read-only, causing layout |
| // mismatch issues. |
| TEST_P(ReadOnlyDepthAttachmentTests, UnusedAspectWithReadOnly) { |
| wgpu::TextureFormat format = GetParam().mTextureFormat; |
| wgpu::TextureDescriptor tDesc; |
| tDesc.size = {1, 1}; |
| tDesc.format = format; |
| tDesc.usage = wgpu::TextureUsage::RenderAttachment; |
| wgpu::Texture depthStencilTexture = device.CreateTexture(&tDesc); |
| |
| utils::ComboRenderPassDescriptor passDescriptor({}, depthStencilTexture.CreateView()); |
| if (utils::IsStencilOnlyFormat(format)) { |
| passDescriptor.cDepthStencilAttachmentInfo.depthReadOnly = true; |
| passDescriptor.cDepthStencilAttachmentInfo.depthLoadOp = wgpu::LoadOp::Undefined; |
| passDescriptor.cDepthStencilAttachmentInfo.depthStoreOp = wgpu::StoreOp::Undefined; |
| } else { |
| passDescriptor.cDepthStencilAttachmentInfo.depthReadOnly = false; |
| } |
| if (utils::IsDepthOnlyFormat(format)) { |
| passDescriptor.cDepthStencilAttachmentInfo.stencilReadOnly = true; |
| passDescriptor.cDepthStencilAttachmentInfo.stencilLoadOp = wgpu::LoadOp::Undefined; |
| passDescriptor.cDepthStencilAttachmentInfo.stencilStoreOp = wgpu::StoreOp::Undefined; |
| } else { |
| passDescriptor.cDepthStencilAttachmentInfo.stencilReadOnly = false; |
| } |
| |
| wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); |
| wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&passDescriptor); |
| pass.End(); |
| wgpu::CommandBuffer commands = encoder.Finish(); |
| |
| queue.Submit(1, &commands); |
| } |
| |
| class ReadOnlyStencilAttachmentTests : public ReadOnlyDepthStencilAttachmentTests {}; |
| |
| TEST_P(ReadOnlyStencilAttachmentTests, SampleFromAttachment) { |
| // TODO(angleproject:8384): ASSERT is triggered in the ANGLE D3D11 backend likely because of |
| // the usage of the GL_STENCIL_INDEX8 format. |
| DAWN_SUPPRESS_TEST_IF(IsANGLED3D11() && |
| GetParam().mTextureFormat == wgpu::TextureFormat::Stencil8); |
| |
| // stencilRefValue < stencilValue (stencilInitValue), so stencil test passes. The pipeline |
| // samples from stencil buffer and writes into color buffer. |
| { |
| TestSpec spec; |
| spec.readonlyAspects = wgpu::TextureAspect::StencilOnly; |
| spec.sampledAspect = wgpu::TextureAspect::StencilOnly; |
| spec.stencilCompare = wgpu::CompareFunction::LessEqual; |
| spec.stencilClearValue = 3; |
| spec.stencilRef = 2; |
| auto render = DoRender(spec); |
| CheckFullColor(render.color, {3, 0, 0, 0}); |
| } |
| |
| // stencilRefValue > stencilValue (stencilInitValue), so stencil test fails. The pipeline |
| // doesn't change color buffer. Sampled data from stencil buffer is discarded. |
| { |
| TestSpec spec; |
| spec.readonlyAspects = wgpu::TextureAspect::StencilOnly; |
| spec.sampledAspect = wgpu::TextureAspect::StencilOnly; |
| spec.stencilCompare = wgpu::CompareFunction::LessEqual; |
| spec.stencilClearValue = 1; |
| spec.stencilRef = 2; |
| auto render = DoRender(spec); |
| CheckFullColor(render.color, {0, 0, 0, 0}); |
| } |
| } |
| |
| TEST_P(ReadOnlyStencilAttachmentTests, NotSampleFromAttachment) { |
| // stencilRefValue < stencilValue (stencilInitValue), so stencil test passes. The pipeline |
| // draw solid blue into color buffer. |
| { |
| TestSpec spec; |
| spec.readonlyAspects = wgpu::TextureAspect::StencilOnly; |
| spec.stencilCompare = wgpu::CompareFunction::LessEqual; |
| spec.stencilClearValue = 3; |
| spec.stencilRef = 2; |
| auto render = DoRender(spec); |
| CheckFullColor(render.color, {0, 0, 255, 0}); |
| } |
| |
| // stencilRefValue > stencilValue (stencilInitValue), so stencil test fails. The pipeline |
| // doesn't change color buffer. drawing data is discarded. |
| { |
| TestSpec spec; |
| spec.readonlyAspects = wgpu::TextureAspect::StencilOnly; |
| spec.stencilCompare = wgpu::CompareFunction::LessEqual; |
| spec.stencilClearValue = 1; |
| spec.stencilRef = 2; |
| auto render = DoRender(spec); |
| CheckFullColor(render.color, {0, 0, 0, 0}); |
| } |
| } |
| |
| class ReadOnlyDepthAndStencilAttachmentTests : public ReadOnlyDepthStencilAttachmentTests {}; |
| |
| // Test that using stencilReadOnly while modifying the depth aspect works. |
| TEST_P(ReadOnlyDepthAndStencilAttachmentTests, ModifyDepthSampleStencil) { |
| // Stencil test is always true but the depth test passes only for the |
| TestSpec spec1; |
| spec1.readonlyAspects = wgpu::TextureAspect::StencilOnly; |
| spec1.sampledAspect = wgpu::TextureAspect::StencilOnly; |
| spec1.stencilClearValue = 42; |
| spec1.depthClearValue = 0.2; |
| spec1.depthCompare = wgpu::CompareFunction::LessEqual; |
| spec1.depthWriteEnabled = true; |
| auto render1 = DoRender(spec1); |
| |
| // Stencil was read successfully, but only in the bottom part. |
| CheckTopBottomColor(render1.color, {0, 0, 0, 0}, {42, 0, 0, 0}); |
| |
| // Check that the depth was written by setting depthCompare equal, and rendering a solid |
| // blue color. The depth was only written on the bottom half due to the depth test in the |
| // first render. |
| TestSpec spec2; |
| spec2.readonlyAspects = wgpu::TextureAspect::StencilOnly; |
| spec2.depthStencilTexture = render1.depthStencil; |
| spec2.depthCompare = wgpu::CompareFunction::Equal; |
| auto render2 = DoRender(spec2); |
| CheckTopBottomColor(render2.color, {0, 0, 0, 0}, {0, 0, 255, 0}); |
| } |
| |
| // Test that using depthReadOnly while modifying the stencil aspect works. |
| TEST_P(ReadOnlyDepthAndStencilAttachmentTests, SampleDepthModifyStencil) { |
| // TODO(dawn:2163): The texture reads zeroes, maybe ANGLE's TextureStorageD3D11 is missing a |
| // copy between the storages? |
| DAWN_SUPPRESS_TEST_IF(IsANGLED3D11()); |
| |
| // TODO(crbug.com/dawn/2295): diagnose this failure on Pixel 4 OpenGLES |
| DAWN_SUPPRESS_TEST_IF(IsOpenGLES() && IsAndroid() && IsQualcomm()); |
| |
| // Depth/stencil tests are true, the depth is correctly sampled from the depthClearValue. |
| // The stencil is written to the value of the stencil ref. |
| TestSpec spec1; |
| spec1.readonlyAspects = wgpu::TextureAspect::DepthOnly; |
| spec1.sampledAspect = wgpu::TextureAspect::DepthOnly; |
| spec1.depthClearValue = 0.2; |
| spec1.stencilWriteEnabled = true; |
| spec1.stencilRef = 42; |
| spec1.stencilClearValue = 0; |
| auto render1 = DoRender(spec1); |
| CheckFullColor(render1.color, {static_cast<uint8_t>(0.2 * 255), 0, 0, 0}); |
| |
| // The stencil test checks that the stencil ref matches what's in the stencil buffer |
| // so that we know it was correctly written. The whole quad should be drawn. |
| TestSpec spec2; |
| spec2.readonlyAspects = wgpu::TextureAspect::DepthOnly; |
| spec2.depthStencilTexture = render1.depthStencil; |
| spec2.stencilCompare = wgpu::CompareFunction::Equal; |
| spec2.stencilRef = 42; |
| auto render2 = DoRender(spec2); |
| CheckFullColor(render2.color, {0, 0, 255, 0}); |
| } |
| |
| // Test sampling depth with both the depth and stencil readonly. |
| TEST_P(ReadOnlyDepthAndStencilAttachmentTests, BothReadOnlySampleDepth) { |
| // TODO(dawn:2163): The texture reads zeroes, maybe ANGLE's TextureStorageD3D11 is missing a |
| // copy between the storages? |
| DAWN_SUPPRESS_TEST_IF(IsANGLED3D11()); |
| |
| // TODO(crbug.com/dawn/2295): diagnose this failure on Pixel 4 OpenGLES |
| DAWN_SUPPRESS_TEST_IF(IsOpenGLES() && IsAndroid() && IsQualcomm()); |
| |
| // Sample the depth while using both depth an stencil testing. |
| |
| // First render: depth test passes only for the bottom half, stencil passes. |
| TestSpec spec; |
| spec.readonlyAspects = wgpu::TextureAspect::All; |
| spec.sampledAspect = wgpu::TextureAspect::DepthOnly; |
| spec.depthCompare = wgpu::CompareFunction::LessEqual; |
| spec.depthClearValue = 0.2; |
| spec.stencilRef = 42; |
| spec.stencilClearValue = 43; |
| spec.stencilCompare = wgpu::CompareFunction::LessEqual; |
| auto render1 = DoRender(spec); |
| CheckTopBottomColor(render1.color, {0, 0, 0, 0}, {static_cast<uint8_t>(0.2 * 255), 0, 0, 0}); |
| |
| // Second render: stencil test fails. |
| spec.stencilClearValue = 41; |
| auto render2 = DoRender(spec); |
| CheckFullColor(render2.color, {0, 0, 0, 0}); |
| } |
| |
| // Test sampling stencil with both the depth and stencil readonly. |
| TEST_P(ReadOnlyDepthAndStencilAttachmentTests, BothReadOnlySampleStencil) { |
| // Sample the stencil while using both depth an stencil testing. |
| |
| // First render: depth test passes only for the bottom half, stencil passes. |
| TestSpec spec; |
| spec.readonlyAspects = wgpu::TextureAspect::All; |
| spec.sampledAspect = wgpu::TextureAspect::StencilOnly; |
| spec.depthCompare = wgpu::CompareFunction::LessEqual; |
| spec.depthClearValue = 0.2; |
| spec.stencilRef = 42; |
| spec.stencilClearValue = 43; |
| spec.stencilCompare = wgpu::CompareFunction::LessEqual; |
| auto render1 = DoRender(spec); |
| CheckTopBottomColor(render1.color, {0, 0, 0, 0}, {43, 0, 0, 0}); |
| |
| // Second render: stencil test fails. |
| spec.stencilClearValue = 41; |
| auto render2 = DoRender(spec); |
| CheckFullColor(render2.color, {0, 0, 0, 0}); |
| } |
| |
| DAWN_INSTANTIATE_TEST_P(ReadOnlyDepthAttachmentTests, |
| {D3D11Backend(), D3D12Backend(), |
| D3D12Backend({}, {"use_d3d12_render_pass"}), MetalBackend(), |
| OpenGLBackend(), OpenGLESBackend(), VulkanBackend()}, |
| std::vector<wgpu::TextureFormat>(utils::kDepthFormats.begin(), |
| utils::kDepthFormats.end())); |
| DAWN_INSTANTIATE_TEST_P(ReadOnlyStencilAttachmentTests, |
| {D3D11Backend(), D3D12Backend(), |
| D3D12Backend({}, {"use_d3d12_render_pass"}), MetalBackend(), |
| OpenGLBackend(), OpenGLESBackend(), VulkanBackend()}, |
| std::vector<wgpu::TextureFormat>(utils::kStencilFormats.begin(), |
| utils::kStencilFormats.end())); |
| DAWN_INSTANTIATE_TEST_P(ReadOnlyDepthAndStencilAttachmentTests, |
| {D3D11Backend(), D3D12Backend(), |
| D3D12Backend({}, {"use_d3d12_render_pass"}), MetalBackend(), |
| OpenGLBackend(), OpenGLESBackend(), VulkanBackend()}, |
| std::vector<wgpu::TextureFormat>(utils::kDepthAndStencilFormats.begin(), |
| utils::kDepthAndStencilFormats.end())); |
| |
| } // anonymous namespace |
| } // namespace dawn |