dawn-cmake/src/tests/unittests/validation/DebugMarkerValidationTests.cpp
Corentin Wallez 7ffaa219cb dawn_native: Do debug marker validation at encoding time.
This also adds missing coverage for push/pop debug group in render
bundles. The RenderBundleEncoder didn't validate itself on Finish, so
add a regression test for that too.

The overarching goal with this CL is to do validation at encoding time
which will help produce SyncScopeResourceUsage in the frontend for
dispatch() calls so that they can be reused by the backends.

Bug: dawn:635
Change-Id: Ie5a2d987fda3854b3145ba4b7a34994ea605e820
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/38842
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Auto-Submit: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Stephen White <senorblanco@chromium.org>
2021-01-27 16:03:32 +00:00

256 lines
8.9 KiB
C++

// Copyright 2019 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "tests/unittests/validation/ValidationTest.h"
#include "utils/ComboRenderBundleEncoderDescriptor.h"
#include "utils/WGPUHelpers.h"
class DebugMarkerValidationTest : public ValidationTest {};
// Correct usage of debug markers should succeed in render pass.
TEST_F(DebugMarkerValidationTest, RenderSuccess) {
DummyRenderPass renderPass(device);
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
{
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
pass.PushDebugGroup("Event Start");
pass.PushDebugGroup("Event Start");
pass.InsertDebugMarker("Marker");
pass.PopDebugGroup();
pass.PopDebugGroup();
pass.EndPass();
}
encoder.Finish();
}
// A PushDebugGroup call without a following PopDebugGroup produces an error in render pass.
TEST_F(DebugMarkerValidationTest, RenderUnbalancedPush) {
DummyRenderPass renderPass(device);
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
{
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
pass.PushDebugGroup("Event Start");
pass.PushDebugGroup("Event Start");
pass.InsertDebugMarker("Marker");
pass.PopDebugGroup();
pass.EndPass();
}
ASSERT_DEVICE_ERROR(encoder.Finish());
}
// A PopDebugGroup call without a preceding PushDebugGroup produces an error in render pass.
TEST_F(DebugMarkerValidationTest, RenderUnbalancedPop) {
DummyRenderPass renderPass(device);
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
{
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
pass.PushDebugGroup("Event Start");
pass.InsertDebugMarker("Marker");
pass.PopDebugGroup();
pass.PopDebugGroup();
pass.EndPass();
}
ASSERT_DEVICE_ERROR(encoder.Finish());
}
// Correct usage of debug markers should succeed in render bundle.
TEST_F(DebugMarkerValidationTest, RenderBundleSuccess) {
utils::ComboRenderBundleEncoderDescriptor desc;
desc.cColorFormats[0] = wgpu::TextureFormat::RGBA8Unorm;
desc.colorFormatsCount = 1;
wgpu::RenderBundleEncoder encoder = device.CreateRenderBundleEncoder(&desc);
encoder.PushDebugGroup("Event Start");
encoder.PushDebugGroup("Event Start");
encoder.InsertDebugMarker("Marker");
encoder.PopDebugGroup();
encoder.PopDebugGroup();
encoder.Finish();
}
// A PushDebugGroup call without a following PopDebugGroup produces an error in render bundle.
TEST_F(DebugMarkerValidationTest, RenderBundleUnbalancedPush) {
utils::ComboRenderBundleEncoderDescriptor desc;
desc.cColorFormats[0] = wgpu::TextureFormat::RGBA8Unorm;
desc.colorFormatsCount = 1;
wgpu::RenderBundleEncoder encoder = device.CreateRenderBundleEncoder(&desc);
encoder.PushDebugGroup("Event Start");
encoder.PushDebugGroup("Event Start");
encoder.InsertDebugMarker("Marker");
encoder.PopDebugGroup();
ASSERT_DEVICE_ERROR(encoder.Finish());
}
// A PopDebugGroup call without a preceding PushDebugGroup produces an error in render bundle.
TEST_F(DebugMarkerValidationTest, RenderBundleUnbalancedPop) {
utils::ComboRenderBundleEncoderDescriptor desc;
desc.cColorFormats[0] = wgpu::TextureFormat::RGBA8Unorm;
desc.colorFormatsCount = 1;
wgpu::RenderBundleEncoder encoder = device.CreateRenderBundleEncoder(&desc);
encoder.PushDebugGroup("Event Start");
encoder.InsertDebugMarker("Marker");
encoder.PopDebugGroup();
encoder.PopDebugGroup();
ASSERT_DEVICE_ERROR(encoder.Finish());
}
// Correct usage of debug markers should succeed in compute pass.
TEST_F(DebugMarkerValidationTest, ComputeSuccess) {
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
{
wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
pass.PushDebugGroup("Event Start");
pass.PushDebugGroup("Event Start");
pass.InsertDebugMarker("Marker");
pass.PopDebugGroup();
pass.PopDebugGroup();
pass.EndPass();
}
encoder.Finish();
}
// A PushDebugGroup call without a following PopDebugGroup produces an error in compute pass.
TEST_F(DebugMarkerValidationTest, ComputeUnbalancedPush) {
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
{
wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
pass.PushDebugGroup("Event Start");
pass.PushDebugGroup("Event Start");
pass.InsertDebugMarker("Marker");
pass.PopDebugGroup();
pass.EndPass();
}
ASSERT_DEVICE_ERROR(encoder.Finish());
}
// A PopDebugGroup call without a preceding PushDebugGroup produces an error in compute pass.
TEST_F(DebugMarkerValidationTest, ComputeUnbalancedPop) {
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
{
wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
pass.PushDebugGroup("Event Start");
pass.InsertDebugMarker("Marker");
pass.PopDebugGroup();
pass.PopDebugGroup();
pass.EndPass();
}
ASSERT_DEVICE_ERROR(encoder.Finish());
}
// Correct usage of debug markers should succeed in command encoder.
TEST_F(DebugMarkerValidationTest, CommandEncoderSuccess) {
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.PushDebugGroup("Event Start");
encoder.PushDebugGroup("Event Start");
encoder.InsertDebugMarker("Marker");
encoder.PopDebugGroup();
encoder.PopDebugGroup();
encoder.Finish();
}
// A PushDebugGroup call without a following PopDebugGroup produces an error in command encoder.
TEST_F(DebugMarkerValidationTest, CommandEncoderUnbalancedPush) {
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.PushDebugGroup("Event Start");
encoder.PushDebugGroup("Event Start");
encoder.InsertDebugMarker("Marker");
encoder.PopDebugGroup();
ASSERT_DEVICE_ERROR(encoder.Finish());
}
// A PopDebugGroup call without a preceding PushDebugGroup produces an error in command encoder.
TEST_F(DebugMarkerValidationTest, CommandEncoderUnbalancedPop) {
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.PushDebugGroup("Event Start");
encoder.InsertDebugMarker("Marker");
encoder.PopDebugGroup();
encoder.PopDebugGroup();
ASSERT_DEVICE_ERROR(encoder.Finish());
}
// It is possible to nested pushes in a compute pass in a command encoder.
TEST_F(DebugMarkerValidationTest, NestedComputeInCommandEncoder) {
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.PushDebugGroup("Event Start");
{
wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
pass.PushDebugGroup("Event Start");
pass.InsertDebugMarker("Marker");
pass.PopDebugGroup();
pass.EndPass();
}
encoder.PopDebugGroup();
encoder.Finish();
}
// Command encoder and compute pass pushes must be balanced independently.
TEST_F(DebugMarkerValidationTest, NestedComputeInCommandEncoderIndependent) {
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.PushDebugGroup("Event Start");
{
wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
pass.InsertDebugMarker("Marker");
pass.PopDebugGroup();
pass.EndPass();
}
ASSERT_DEVICE_ERROR(encoder.Finish());
}
// It is possible to nested pushes in a render pass in a command encoder.
TEST_F(DebugMarkerValidationTest, NestedRenderInCommandEncoder) {
DummyRenderPass renderPass(device);
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.PushDebugGroup("Event Start");
{
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
pass.PushDebugGroup("Event Start");
pass.InsertDebugMarker("Marker");
pass.PopDebugGroup();
pass.EndPass();
}
encoder.PopDebugGroup();
encoder.Finish();
}
// Command encoder and render pass pushes must be balanced independently.
TEST_F(DebugMarkerValidationTest, NestedRenderInCommandEncoderIndependent) {
DummyRenderPass renderPass(device);
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.PushDebugGroup("Event Start");
{
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
pass.InsertDebugMarker("Marker");
pass.PopDebugGroup();
pass.EndPass();
}
ASSERT_DEVICE_ERROR(encoder.Finish());
}