1 // Copyright 2019 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 
15 #include "tests/unittests/validation/ValidationTest.h"
16 
17 #include "utils/WGPUHelpers.h"
18 
19 class DebugMarkerValidationTest : public ValidationTest {};
20 
21 // Correct usage of debug markers should succeed in render pass.
TEST_F(DebugMarkerValidationTest,RenderSuccess)22 TEST_F(DebugMarkerValidationTest, RenderSuccess) {
23     DummyRenderPass renderPass(device);
24 
25     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
26     {
27         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
28         pass.PushDebugGroup("Event Start");
29         pass.PushDebugGroup("Event Start");
30         pass.InsertDebugMarker("Marker");
31         pass.PopDebugGroup();
32         pass.PopDebugGroup();
33         pass.EndPass();
34     }
35 
36     encoder.Finish();
37 }
38 
39 // A PushDebugGroup call without a following PopDebugGroup produces an error in render pass.
TEST_F(DebugMarkerValidationTest,RenderUnbalancedPush)40 TEST_F(DebugMarkerValidationTest, RenderUnbalancedPush) {
41     DummyRenderPass renderPass(device);
42 
43     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
44     {
45         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
46         pass.PushDebugGroup("Event Start");
47         pass.PushDebugGroup("Event Start");
48         pass.InsertDebugMarker("Marker");
49         pass.PopDebugGroup();
50         pass.EndPass();
51     }
52 
53     ASSERT_DEVICE_ERROR(encoder.Finish());
54 }
55 
56 // A PopDebugGroup call without a preceding PushDebugGroup produces an error in render pass.
TEST_F(DebugMarkerValidationTest,RenderUnbalancedPop)57 TEST_F(DebugMarkerValidationTest, RenderUnbalancedPop) {
58     DummyRenderPass renderPass(device);
59 
60     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
61     {
62         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
63         pass.PushDebugGroup("Event Start");
64         pass.InsertDebugMarker("Marker");
65         pass.PopDebugGroup();
66         pass.PopDebugGroup();
67         pass.EndPass();
68     }
69 
70     ASSERT_DEVICE_ERROR(encoder.Finish());
71 }
72 
73 // Correct usage of debug markers should succeed in compute pass.
TEST_F(DebugMarkerValidationTest,ComputeSuccess)74 TEST_F(DebugMarkerValidationTest, ComputeSuccess) {
75     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
76     {
77         wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
78         pass.PushDebugGroup("Event Start");
79         pass.PushDebugGroup("Event Start");
80         pass.InsertDebugMarker("Marker");
81         pass.PopDebugGroup();
82         pass.PopDebugGroup();
83         pass.EndPass();
84     }
85 
86     encoder.Finish();
87 }
88 
89 // A PushDebugGroup call without a following PopDebugGroup produces an error in compute pass.
TEST_F(DebugMarkerValidationTest,ComputeUnbalancedPush)90 TEST_F(DebugMarkerValidationTest, ComputeUnbalancedPush) {
91     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
92     {
93         wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
94         pass.PushDebugGroup("Event Start");
95         pass.PushDebugGroup("Event Start");
96         pass.InsertDebugMarker("Marker");
97         pass.PopDebugGroup();
98         pass.EndPass();
99     }
100 
101     ASSERT_DEVICE_ERROR(encoder.Finish());
102 }
103 
104 // A PopDebugGroup call without a preceding PushDebugGroup produces an error in compute pass.
TEST_F(DebugMarkerValidationTest,ComputeUnbalancedPop)105 TEST_F(DebugMarkerValidationTest, ComputeUnbalancedPop) {
106     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
107     {
108         wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
109         pass.PushDebugGroup("Event Start");
110         pass.InsertDebugMarker("Marker");
111         pass.PopDebugGroup();
112         pass.PopDebugGroup();
113         pass.EndPass();
114     }
115 
116     ASSERT_DEVICE_ERROR(encoder.Finish());
117 }
118 
119 // Correct usage of debug markers should succeed in command encoder.
TEST_F(DebugMarkerValidationTest,CommandEncoderSuccess)120 TEST_F(DebugMarkerValidationTest, CommandEncoderSuccess) {
121     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
122     encoder.PushDebugGroup("Event Start");
123     encoder.PushDebugGroup("Event Start");
124     encoder.InsertDebugMarker("Marker");
125     encoder.PopDebugGroup();
126     encoder.PopDebugGroup();
127     encoder.Finish();
128 }
129 
130 // A PushDebugGroup call without a following PopDebugGroup produces an error in command encoder.
TEST_F(DebugMarkerValidationTest,CommandEncoderUnbalancedPush)131 TEST_F(DebugMarkerValidationTest, CommandEncoderUnbalancedPush) {
132     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
133     encoder.PushDebugGroup("Event Start");
134     encoder.PushDebugGroup("Event Start");
135     encoder.InsertDebugMarker("Marker");
136     encoder.PopDebugGroup();
137     ASSERT_DEVICE_ERROR(encoder.Finish());
138 }
139 
140 // A PopDebugGroup call without a preceding PushDebugGroup produces an error in command encoder.
TEST_F(DebugMarkerValidationTest,CommandEncoderUnbalancedPop)141 TEST_F(DebugMarkerValidationTest, CommandEncoderUnbalancedPop) {
142     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
143     encoder.PushDebugGroup("Event Start");
144     encoder.InsertDebugMarker("Marker");
145     encoder.PopDebugGroup();
146     encoder.PopDebugGroup();
147     ASSERT_DEVICE_ERROR(encoder.Finish());
148 }
149 
150 // It is possible to nested pushes in a compute pass in a command encoder.
TEST_F(DebugMarkerValidationTest,NestedComputeInCommandEncoder)151 TEST_F(DebugMarkerValidationTest, NestedComputeInCommandEncoder) {
152     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
153     encoder.PushDebugGroup("Event Start");
154     {
155         wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
156         pass.PushDebugGroup("Event Start");
157         pass.InsertDebugMarker("Marker");
158         pass.PopDebugGroup();
159         pass.EndPass();
160     }
161     encoder.PopDebugGroup();
162     encoder.Finish();
163 }
164 
165 // Command encoder and compute pass pushes must be balanced independently.
TEST_F(DebugMarkerValidationTest,NestedComputeInCommandEncoderIndependent)166 TEST_F(DebugMarkerValidationTest, NestedComputeInCommandEncoderIndependent) {
167     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
168     encoder.PushDebugGroup("Event Start");
169     {
170         wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
171         pass.InsertDebugMarker("Marker");
172         pass.PopDebugGroup();
173         pass.EndPass();
174     }
175     ASSERT_DEVICE_ERROR(encoder.Finish());
176 }
177 
178 // It is possible to nested pushes in a render pass in a command encoder.
TEST_F(DebugMarkerValidationTest,NestedRenderInCommandEncoder)179 TEST_F(DebugMarkerValidationTest, NestedRenderInCommandEncoder) {
180     DummyRenderPass renderPass(device);
181 
182     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
183     encoder.PushDebugGroup("Event Start");
184     {
185         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
186         pass.PushDebugGroup("Event Start");
187         pass.InsertDebugMarker("Marker");
188         pass.PopDebugGroup();
189         pass.EndPass();
190     }
191     encoder.PopDebugGroup();
192     encoder.Finish();
193 }
194 
195 // Command encoder and render pass pushes must be balanced independently.
TEST_F(DebugMarkerValidationTest,NestedRenderInCommandEncoderIndependent)196 TEST_F(DebugMarkerValidationTest, NestedRenderInCommandEncoderIndependent) {
197     DummyRenderPass renderPass(device);
198 
199     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
200     encoder.PushDebugGroup("Event Start");
201     {
202         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
203         pass.InsertDebugMarker("Marker");
204         pass.PopDebugGroup();
205         pass.EndPass();
206     }
207     ASSERT_DEVICE_ERROR(encoder.Finish());
208 }
209