blob: e30299f43a9ab73d2be3431ac4cb59aab79bef82 [file] [log] [blame]
Yunchao Hedaffd222021-10-14 04:09:21 +00001// Copyright 2021 The Dawn Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Yunchao Hee43eaab2021-10-18 16:57:31 +000015#include "utils/ComboRenderBundleEncoderDescriptor.h"
Yunchao Hedaffd222021-10-14 04:09:21 +000016#include "utils/ComboRenderPipelineDescriptor.h"
17#include "utils/WGPUHelpers.h"
18
19#include "tests/unittests/validation/ValidationTest.h"
20
21constexpr static uint32_t kSize = 4;
22
23namespace {
24
25 class RenderPipelineAndPassCompatibilityTests : public ValidationTest {
26 public:
27 wgpu::RenderPipeline CreatePipeline(wgpu::TextureFormat format,
28 bool enableDepthWrite,
29 bool enableStencilWrite) {
30 // Create a NoOp pipeline
31 utils::ComboRenderPipelineDescriptor pipelineDescriptor;
32 pipelineDescriptor.vertex.module = utils::CreateShaderModule(device, R"(
33 [[stage(vertex)]] fn main() -> [[builtin(position)]] vec4<f32> {
34 return vec4<f32>();
35 })");
36 pipelineDescriptor.cFragment.module = utils::CreateShaderModule(device, R"(
37 [[stage(fragment)]] fn main() {
38 })");
39 pipelineDescriptor.cFragment.targets = nullptr;
40 pipelineDescriptor.cFragment.targetCount = 0;
41
42 // Enable depth/stencil write if needed
43 wgpu::DepthStencilState* depthStencil = pipelineDescriptor.EnableDepthStencil(format);
44 if (enableDepthWrite) {
45 depthStencil->depthWriteEnabled = true;
46 }
47 if (enableStencilWrite) {
48 depthStencil->stencilFront.failOp = wgpu::StencilOperation::Replace;
49 }
50 return device.CreateRenderPipeline(&pipelineDescriptor);
51 }
52
53 utils::ComboRenderPassDescriptor CreateRenderPassDescriptor(wgpu::TextureFormat format,
54 bool depthReadOnly,
55 bool stencilReadOnly) {
56 wgpu::TextureDescriptor textureDescriptor = {};
57 textureDescriptor.size = {kSize, kSize, 1};
58 textureDescriptor.format = format;
59 textureDescriptor.usage = wgpu::TextureUsage::RenderAttachment;
60 wgpu::Texture depthStencilTexture = device.CreateTexture(&textureDescriptor);
61
62 utils::ComboRenderPassDescriptor passDescriptor({}, depthStencilTexture.CreateView());
63 if (depthReadOnly) {
64 passDescriptor.cDepthStencilAttachmentInfo.depthReadOnly = true;
65 passDescriptor.cDepthStencilAttachmentInfo.depthLoadOp = wgpu::LoadOp::Load;
66 passDescriptor.cDepthStencilAttachmentInfo.depthStoreOp = wgpu::StoreOp::Store;
67 }
68
69 if (stencilReadOnly) {
70 passDescriptor.cDepthStencilAttachmentInfo.stencilReadOnly = true;
71 passDescriptor.cDepthStencilAttachmentInfo.stencilLoadOp = wgpu::LoadOp::Load;
72 passDescriptor.cDepthStencilAttachmentInfo.stencilStoreOp = wgpu::StoreOp::Store;
73 }
74
75 return passDescriptor;
76 }
77 };
78
79 // Test depthWrite/stencilWrite in DepthStencilState in pipeline vs
80 // depthReadOnly/stencilReadOnly in DepthStencilAttachment in pass
81 TEST_F(RenderPipelineAndPassCompatibilityTests, WriteAndReadOnlyConflictForDepthStencil) {
82 wgpu::TextureFormat kFormat = wgpu::TextureFormat::Depth24PlusStencil8;
83 // If the format has both depth and stencil aspects, depthReadOnly and stencilReadOnly
84 // should be the same. So it is not necessary to set two separate booleans like
85 // depthReadOnlyInPass and stencilReadOnlyInPass.
86 for (bool depthStencilReadOnlyInPass : {true, false}) {
87 for (bool depthWriteInPipeline : {true, false}) {
88 for (bool stencilWriteInPipeline : {true, false}) {
89 wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
90 utils::ComboRenderPassDescriptor passDescriptor = CreateRenderPassDescriptor(
91 kFormat, depthStencilReadOnlyInPass, depthStencilReadOnlyInPass);
92 wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&passDescriptor);
93 wgpu::RenderPipeline pipeline =
94 CreatePipeline(kFormat, depthWriteInPipeline, stencilWriteInPipeline);
95 pass.SetPipeline(pipeline);
96 pass.Draw(3);
97 pass.EndPass();
98 if (depthStencilReadOnlyInPass &&
99 (depthWriteInPipeline || stencilWriteInPipeline)) {
100 ASSERT_DEVICE_ERROR(encoder.Finish());
101 } else {
102 encoder.Finish();
103 }
104 }
105 }
106 }
107 }
108
Yunchao Hee43eaab2021-10-18 16:57:31 +0000109 // Test depthWrite/stencilWrite in DepthStencilState in pipeline vs
110 // depthReadOnly/stencilReadOnly in RenderBundleEncoderDescriptor in RenderBundle
111 TEST_F(RenderPipelineAndPassCompatibilityTests,
112 WriteAndReadOnlyConflictForDepthStencilWithRenderBundle) {
113 wgpu::TextureFormat kFormat = wgpu::TextureFormat::Depth24PlusStencil8;
114 // If the format has both depth and stencil aspects, depthReadOnly and stencilReadOnly
115 // should be the same. So it is not necessary to set two separate booleans like
116 // depthReadOnlyInBundle and stencilReadOnlyInBundle.
117 for (bool depthStencilReadOnlyInBundle : {true, false}) {
118 utils::ComboRenderBundleEncoderDescriptor desc = {};
119 desc.depthStencilFormat = kFormat;
120 desc.depthReadOnly = depthStencilReadOnlyInBundle;
121 desc.stencilReadOnly = depthStencilReadOnlyInBundle;
122
123 for (bool depthWriteInPipeline : {true, false}) {
124 for (bool stencilWriteInPipeline : {true, false}) {
125 wgpu::RenderBundleEncoder renderBundleEncoder =
126 device.CreateRenderBundleEncoder(&desc);
127 wgpu::RenderPipeline pipeline =
128 CreatePipeline(kFormat, depthWriteInPipeline, stencilWriteInPipeline);
129 renderBundleEncoder.SetPipeline(pipeline);
130 renderBundleEncoder.Draw(3);
131 if (depthStencilReadOnlyInBundle &&
132 (depthWriteInPipeline || stencilWriteInPipeline)) {
133 ASSERT_DEVICE_ERROR(renderBundleEncoder.Finish());
134 } else {
135 renderBundleEncoder.Finish();
136 }
137 }
138 }
139 }
140 }
141
Yunchao Hedaffd222021-10-14 04:09:21 +0000142 // TODO(dawn:485): add more tests. For example:
Yunchao Hedaffd222021-10-14 04:09:21 +0000143 // - depth/stencil attachment should be designated if depth/stencil test is enabled.
144 // - pipeline and pass compatibility tests for color attachment(s).
145 // - pipeline and pass compatibility tests for compute.
146
147} // anonymous namespace