Implementation of Debug Marker APIs

Introduces pushDebugGroup, popDebugGroup, and insertDebugMarker implementations
for Vulkan and Metal using VK_EXT_debug_marker and XCode, respectively.

Bug: dawn:44
Change-Id: I0ae56c4d67aa832123f27a1fcdddf65746261e57
Reviewed-on: https://dawn-review.googlesource.com/c/4241
Commit-Queue: Brandon Jones <brandon1.jones@intel.com>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
Brandon Jones 2019-02-20 20:21:00 +00:00 committed by Commit Bot service account
parent 938811eef9
commit 11d32c8095
20 changed files with 467 additions and 0 deletions

View File

@ -944,6 +944,7 @@ test("dawn_unittests") {
"src/tests/unittests/validation/CommandBufferValidationTests.cpp",
"src/tests/unittests/validation/ComputeValidationTests.cpp",
"src/tests/unittests/validation/CopyCommandsValidationTests.cpp",
"src/tests/unittests/validation/DebugMarkerValidationTests.cpp",
"src/tests/unittests/validation/DynamicStateCommandValidationTests.cpp",
"src/tests/unittests/validation/FenceValidationTests.cpp",
"src/tests/unittests/validation/InputStateValidationTests.cpp",
@ -1002,6 +1003,7 @@ test("dawn_end2end_tests") {
"src/tests/end2end/ColorStateTests.cpp",
"src/tests/end2end/ComputeCopyStorageBufferTests.cpp",
"src/tests/end2end/CopyTests.cpp",
"src/tests/end2end/DebugMarkerTests.cpp",
"src/tests/end2end/DepthStencilStateTests.cpp",
"src/tests/end2end/DrawIndexedTests.cpp",
"src/tests/end2end/DrawTests.cpp",

View File

@ -336,6 +336,22 @@
"compute pass encoder": {
"category": "object",
"methods": [
{
"name": "insert debug marker",
"args": [
{"name": "group label", "type": "char", "annotation": "const*", "length": "strlen"}
]
},
{
"name": "pop debug group",
"args": []
},
{
"name": "push debug group",
"args": [
{"name": "group label", "type": "char", "annotation": "const*", "length": "strlen"}
]
},
{
"name": "set pipeline",
"args": [
@ -804,6 +820,22 @@
{"name": "first instance", "type": "uint32_t"}
]
},
{
"name": "insert debug marker",
"args": [
{"name": "group label", "type": "char", "annotation": "const*", "length": "strlen"}
]
},
{
"name": "pop debug group",
"args": []
},
{
"name": "push debug group",
"args": [
{"name": "group label", "type": "char", "annotation": "const*", "length": "strlen"}
]
},
{
"name": "set stencil reference",
"args": [

38
docs/DebugMarkers.md Normal file
View File

@ -0,0 +1,38 @@
# Debug Markers
Dawn provides debug tooling integration for each backend.
Debugging markers are exposed through this API:
```
partial GPUProgrammablePassEncoder {
void pushDebugGroup(const char * markerLabel);
void popDebugGroup();
void insertDebugMarker(const char * markerLabel);
};
```
These APIs will result in silent no-ops if they are used without setting up
the execution environment properly. Each backend has a specific process
for setting up this environment.
## D3D12
Debug markers are currently unimplemented on D3D12 pending resolution of a licensing issue.
## Vulkan
Debug markers on Vulkan are implemented with [VK_EXT_debug_marker](https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VK_EXT_debug_marker).
To enable marker functionality, you must launch your application from your debugging tool. Attaching to an already running application is not supported.
Vulkan markers have been tested with [RenderDoc](https://renderdoc.org/).
## Metal
Debug markers on Metal are used with the XCode debugger.
To enable marker functionality, you must launch your application from XCode and use [GPU Frame Capture](https://developer.apple.com/documentation/metal/tools_profiling_and_debugging/metal_gpu_capture).
## OpenGL
Debug markers on OpenGL are not implemented and will result in a silent no-op. This is due to low adoption of the GL_EXT_debug_marker extension in Linux device drivers.

View File

@ -94,6 +94,29 @@ namespace dawn_native {
return {};
}
inline MaybeError PushDebugMarkerStack(unsigned int* counter) {
*counter += 1;
return {};
}
inline MaybeError PopDebugMarkerStack(unsigned int* counter) {
if (*counter == 0) {
return DAWN_VALIDATION_ERROR("Pop must be balanced by a corresponding Push.");
} else {
*counter -= 1;
}
return {};
}
inline MaybeError ValidateDebugGroups(const unsigned int counter) {
if (counter != 0) {
return DAWN_VALIDATION_ERROR("Each Push must be balanced by a corresponding Pop.");
}
return {};
}
MaybeError ComputeTextureCopyBufferSize(const Extent3D& copySize,
uint32_t rowPitch,
uint32_t imageHeight,
@ -635,6 +658,8 @@ namespace dawn_native {
case Command::EndComputePass: {
mIterator.NextCommand<EndComputePassCmd>();
DAWN_TRY(ValidateDebugGroups(mDebugGroupStackSize));
DAWN_TRY(usageTracker.ValidateUsages(PassType::Compute));
mResourceUsages.perPass.push_back(usageTracker.AcquireResourceUsage());
return {};
@ -645,6 +670,22 @@ namespace dawn_native {
DAWN_TRY(persistentState.ValidateCanDispatch());
} break;
case Command::InsertDebugMarker: {
InsertDebugMarkerCmd* cmd = mIterator.NextCommand<InsertDebugMarkerCmd>();
mIterator.NextData<char>(cmd->length + 1);
} break;
case Command::PopDebugGroup: {
mIterator.NextCommand<PopDebugGroupCmd>();
DAWN_TRY(PopDebugMarkerStack(&mDebugGroupStackSize));
} break;
case Command::PushDebugGroup: {
PushDebugGroupCmd* cmd = mIterator.NextCommand<PushDebugGroupCmd>();
mIterator.NextData<char>(cmd->length + 1);
DAWN_TRY(PushDebugMarkerStack(&mDebugGroupStackSize));
} break;
case Command::SetComputePipeline: {
SetComputePipelineCmd* cmd = mIterator.NextCommand<SetComputePipelineCmd>();
ComputePipelineBase* pipeline = cmd->pipeline.Get();
@ -701,6 +742,8 @@ namespace dawn_native {
case Command::EndRenderPass: {
mIterator.NextCommand<EndRenderPassCmd>();
DAWN_TRY(ValidateDebugGroups(mDebugGroupStackSize));
DAWN_TRY(usageTracker.ValidateUsages(PassType::Render));
mResourceUsages.perPass.push_back(usageTracker.AcquireResourceUsage());
return {};
@ -716,6 +759,22 @@ namespace dawn_native {
DAWN_TRY(persistentState.ValidateCanDrawIndexed());
} break;
case Command::InsertDebugMarker: {
InsertDebugMarkerCmd* cmd = mIterator.NextCommand<InsertDebugMarkerCmd>();
mIterator.NextData<char>(cmd->length + 1);
} break;
case Command::PopDebugGroup: {
mIterator.NextCommand<PopDebugGroupCmd>();
DAWN_TRY(PopDebugMarkerStack(&mDebugGroupStackSize));
} break;
case Command::PushDebugGroup: {
PushDebugGroupCmd* cmd = mIterator.NextCommand<PushDebugGroupCmd>();
mIterator.NextData<char>(cmd->length + 1);
DAWN_TRY(PushDebugMarkerStack(&mDebugGroupStackSize));
} break;
case Command::SetRenderPipeline: {
SetRenderPipelineCmd* cmd = mIterator.NextCommand<SetRenderPipelineCmd>();
RenderPipelineBase* pipeline = cmd->pipeline.Get();

View File

@ -87,6 +87,8 @@ namespace dawn_native {
bool mWereResourceUsagesAcquired = false;
CommandBufferResourceUsage mResourceUsages;
unsigned int mDebugGroupStackSize = 0;
bool mGotError = false;
std::string mErrorMessage;
};

View File

@ -69,6 +69,20 @@ namespace dawn_native {
EndRenderPassCmd* cmd = commands->NextCommand<EndRenderPassCmd>();
cmd->~EndRenderPassCmd();
} break;
case Command::InsertDebugMarker: {
InsertDebugMarkerCmd* cmd = commands->NextCommand<InsertDebugMarkerCmd>();
commands->NextData<char>(cmd->length + 1);
cmd->~InsertDebugMarkerCmd();
} break;
case Command::PopDebugGroup: {
PopDebugGroupCmd* cmd = commands->NextCommand<PopDebugGroupCmd>();
cmd->~PopDebugGroupCmd();
} break;
case Command::PushDebugGroup: {
PushDebugGroupCmd* cmd = commands->NextCommand<PushDebugGroupCmd>();
commands->NextData<char>(cmd->length + 1);
cmd->~PushDebugGroupCmd();
} break;
case Command::SetComputePipeline: {
SetComputePipelineCmd* cmd = commands->NextCommand<SetComputePipelineCmd>();
cmd->~SetComputePipelineCmd();
@ -158,6 +172,20 @@ namespace dawn_native {
commands->NextCommand<EndRenderPassCmd>();
break;
case Command::InsertDebugMarker: {
InsertDebugMarkerCmd* cmd = commands->NextCommand<InsertDebugMarkerCmd>();
commands->NextData<char>(cmd->length + 1);
} break;
case Command::PopDebugGroup:
commands->NextCommand<PopDebugGroupCmd>();
break;
case Command::PushDebugGroup: {
PushDebugGroupCmd* cmd = commands->NextCommand<PushDebugGroupCmd>();
commands->NextData<char>(cmd->length + 1);
} break;
case Command::SetComputePipeline:
commands->NextCommand<SetComputePipelineCmd>();
break;

View File

@ -41,6 +41,9 @@ namespace dawn_native {
DrawIndexed,
EndComputePass,
EndRenderPass,
InsertDebugMarker,
PopDebugGroup,
PushDebugGroup,
SetComputePipeline,
SetRenderPipeline,
SetPushConstants,
@ -140,6 +143,16 @@ namespace dawn_native {
struct EndRenderPassCmd {};
struct InsertDebugMarkerCmd {
uint32_t length;
};
struct PopDebugGroupCmd {};
struct PushDebugGroupCmd {
uint32_t length;
};
struct SetComputePipelineCmd {
Ref<ComputePipelineBase> pipeline;
};

View File

@ -38,6 +38,30 @@ namespace dawn_native {
mAllocator = nullptr;
}
void ProgrammablePassEncoder::InsertDebugMarker(const char* groupLabel) {
InsertDebugMarkerCmd* cmd =
mAllocator->Allocate<InsertDebugMarkerCmd>(Command::InsertDebugMarker);
new (cmd) InsertDebugMarkerCmd;
cmd->length = strlen(groupLabel);
char* label = mAllocator->AllocateData<char>(cmd->length + 1);
memcpy(label, groupLabel, cmd->length + 1);
}
void ProgrammablePassEncoder::PopDebugGroup() {
PopDebugGroupCmd* cmd = mAllocator->Allocate<PopDebugGroupCmd>(Command::PopDebugGroup);
new (cmd) PopDebugGroupCmd;
}
void ProgrammablePassEncoder::PushDebugGroup(const char* groupLabel) {
PushDebugGroupCmd* cmd = mAllocator->Allocate<PushDebugGroupCmd>(Command::PushDebugGroup);
new (cmd) PushDebugGroupCmd;
cmd->length = strlen(groupLabel);
char* label = mAllocator->AllocateData<char>(cmd->length + 1);
memcpy(label, groupLabel, cmd->length + 1);
}
void ProgrammablePassEncoder::SetBindGroup(uint32_t groupIndex, BindGroupBase* group) {
if (mTopLevelEncoder->ConsumedError(ValidateCanRecordCommands()) ||
mTopLevelEncoder->ConsumedError(GetDevice()->ValidateObject(group))) {

View File

@ -35,6 +35,10 @@ namespace dawn_native {
void EndPass();
void InsertDebugMarker(const char* groupLabel);
void PopDebugGroup();
void PushDebugGroup(const char* groupLabel);
void SetBindGroup(uint32_t groupIndex, BindGroupBase* group);
void SetPushConstants(dawn::ShaderStageBit stages,
uint32_t offset,

View File

@ -696,6 +696,14 @@ namespace dawn_native { namespace d3d12 {
draw->firstInstance);
} break;
case Command::InsertDebugMarker:
case Command::PopDebugGroup:
case Command::PushDebugGroup: {
// TODO(brandon1.jones@intel.com): Implement debug markers after PIX licensing
// issue is resolved.
SkipCommand(&mCommands, type);
} break;
case Command::SetRenderPipeline: {
SetRenderPipelineCmd* cmd = mCommands.NextCommand<SetRenderPipelineCmd>();
RenderPipeline* pipeline = ToBackend(cmd->pipeline).Get();

View File

@ -435,6 +435,30 @@ namespace dawn_native { namespace metal {
}
} break;
case Command::InsertDebugMarker: {
InsertDebugMarkerCmd* cmd = mCommands.NextCommand<InsertDebugMarkerCmd>();
auto label = mCommands.NextData<char>(cmd->length + 1);
NSString* mtlLabel = [[NSString alloc] initWithUTF8String:label];
[encoder insertDebugSignpost:mtlLabel];
[mtlLabel release];
} break;
case Command::PopDebugGroup: {
mCommands.NextCommand<PopDebugGroupCmd>();
[encoder popDebugGroup];
} break;
case Command::PushDebugGroup: {
PushDebugGroupCmd* cmd = mCommands.NextCommand<PushDebugGroupCmd>();
auto label = mCommands.NextData<char>(cmd->length + 1);
NSString* mtlLabel = [[NSString alloc] initWithUTF8String:label];
[encoder pushDebugGroup:mtlLabel];
[mtlLabel release];
} break;
case Command::SetRenderPipeline: {
SetRenderPipelineCmd* cmd = mCommands.NextCommand<SetRenderPipelineCmd>();
lastPipeline = ToBackend(cmd->pipeline).Get();

View File

@ -637,6 +637,14 @@ namespace dawn_native { namespace opengl {
}
} break;
case Command::InsertDebugMarker:
case Command::PopDebugGroup:
case Command::PushDebugGroup: {
// Due to lack of linux driver support for GL_EXT_debug_marker
// extension these functions are skipped.
SkipCommand(&mCommands, type);
} break;
case Command::SetRenderPipeline: {
SetRenderPipelineCmd* cmd = mCommands.NextCommand<SetRenderPipelineCmd>();
lastPipeline = ToBackend(cmd->pipeline).Get();

View File

@ -432,6 +432,53 @@ namespace dawn_native { namespace vulkan {
draw->firstInstance);
} break;
case Command::InsertDebugMarker: {
if (device->GetDeviceInfo().debugMarker) {
InsertDebugMarkerCmd* cmd = mCommands.NextCommand<InsertDebugMarkerCmd>();
const char* label = mCommands.NextData<char>(cmd->length + 1);
VkDebugMarkerMarkerInfoEXT markerInfo;
markerInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
markerInfo.pNext = nullptr;
markerInfo.pMarkerName = label;
// Default color to black
markerInfo.color[0] = 0.0;
markerInfo.color[1] = 0.0;
markerInfo.color[2] = 0.0;
markerInfo.color[3] = 1.0;
device->fn.CmdDebugMarkerInsertEXT(commands, &markerInfo);
} else {
SkipCommand(&mCommands, Command::InsertDebugMarker);
}
} break;
case Command::PopDebugGroup: {
if (device->GetDeviceInfo().debugMarker) {
mCommands.NextCommand<PopDebugGroupCmd>();
device->fn.CmdDebugMarkerEndEXT(commands);
} else {
SkipCommand(&mCommands, Command::PopDebugGroup);
}
} break;
case Command::PushDebugGroup: {
if (device->GetDeviceInfo().debugMarker) {
PushDebugGroupCmd* cmd = mCommands.NextCommand<PushDebugGroupCmd>();
const char* label = mCommands.NextData<char>(cmd->length + 1);
VkDebugMarkerMarkerInfoEXT markerInfo;
markerInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
markerInfo.pNext = nullptr;
markerInfo.pMarkerName = label;
// Default color to black
markerInfo.color[0] = 0.0;
markerInfo.color[1] = 0.0;
markerInfo.color[2] = 0.0;
markerInfo.color[3] = 1.0;
device->fn.CmdDebugMarkerBeginEXT(commands, &markerInfo);
} else {
SkipCommand(&mCommands, Command::PushDebugGroup);
}
} break;
case Command::SetBindGroup: {
SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
VkDescriptorSet set = ToBackend(cmd->group.Get())->GetHandle();

View File

@ -331,6 +331,11 @@ namespace dawn_native { namespace vulkan {
std::vector<const char*> extensionsToRequest;
std::vector<VkDeviceQueueCreateInfo> queuesToRequest;
if (mDeviceInfo.debugMarker) {
extensionsToRequest.push_back(kExtensionNameExtDebugMarker);
usedKnobs.debugMarker = true;
}
if (mDeviceInfo.swapchain) {
extensionsToRequest.push_back(kExtensionNameKhrSwapchain);
usedKnobs.swapchain = true;

View File

@ -208,6 +208,12 @@ namespace dawn_native { namespace vulkan {
GET_DEVICE_PROC(UpdateDescriptorSets);
GET_DEVICE_PROC(WaitForFences);
if (usedKnobs.debugMarker) {
GET_DEVICE_PROC(CmdDebugMarkerBeginEXT);
GET_DEVICE_PROC(CmdDebugMarkerEndEXT);
GET_DEVICE_PROC(CmdDebugMarkerInsertEXT);
}
if (usedKnobs.swapchain) {
GET_DEVICE_PROC(CreateSwapchainKHR);
GET_DEVICE_PROC(DestroySwapchainKHR);

View File

@ -204,6 +204,11 @@ namespace dawn_native { namespace vulkan {
PFN_vkUpdateDescriptorSets UpdateDescriptorSets = nullptr;
PFN_vkWaitForFences WaitForFences = nullptr;
// VK_EXT_debug_marker
PFN_vkCmdDebugMarkerBeginEXT CmdDebugMarkerBeginEXT = nullptr;
PFN_vkCmdDebugMarkerEndEXT CmdDebugMarkerEndEXT = nullptr;
PFN_vkCmdDebugMarkerInsertEXT CmdDebugMarkerInsertEXT = nullptr;
// VK_KHR_swapchain
PFN_vkCreateSwapchainKHR CreateSwapchainKHR = nullptr;
PFN_vkDestroySwapchainKHR DestroySwapchainKHR = nullptr;

View File

@ -35,6 +35,7 @@ namespace dawn_native { namespace vulkan {
const char kLayerNameLunargVKTrace[] = "VK_LAYER_LUNARG_vktrace";
const char kLayerNameRenderDocCapture[] = "VK_LAYER_RENDERDOC_Capture";
const char kExtensionNameExtDebugMarker[] = "VK_EXT_debug_marker";
const char kExtensionNameExtDebugReport[] = "VK_EXT_debug_report";
const char kExtensionNameMvkMacosSurface[] = "VK_MVK_macos_surface";
const char kExtensionNameKhrSurface[] = "VK_KHR_surface";
@ -207,6 +208,10 @@ namespace dawn_native { namespace vulkan {
}
for (const auto& extension : info.extensions) {
if (IsExtensionName(extension, kExtensionNameExtDebugMarker)) {
info.debugMarker = true;
}
if (IsExtensionName(extension, kExtensionNameKhrSwapchain)) {
info.swapchain = true;
}

View File

@ -29,6 +29,7 @@ namespace dawn_native { namespace vulkan {
extern const char kLayerNameLunargVKTrace[];
extern const char kLayerNameRenderDocCapture[];
extern const char kExtensionNameExtDebugMarker[];
extern const char kExtensionNameExtDebugReport[];
extern const char kExtensionNameMvkMacosSurface[];
extern const char kExtensionNameKhrSurface[];
@ -66,6 +67,7 @@ namespace dawn_native { namespace vulkan {
VkPhysicalDeviceFeatures features;
// Extensions
bool debugMarker = false;
bool swapchain = false;
};

View File

@ -0,0 +1,38 @@
// 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/DawnTest.h"
#include "utils/DawnHelpers.h"
class DebugMarkerTests : public DawnTest {};
// Make sure that calling a marker API without a debugging tool attached doesn't cause a failure.
TEST_P(DebugMarkerTests, NoFailureWithoutDebugToolAttached) {
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 4, 4);
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
{
dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
pass.PushDebugGroup("Event Start");
pass.InsertDebugMarker("Marker");
pass.PopDebugGroup();
pass.EndPass();
}
dawn::CommandBuffer commands = encoder.Finish();
queue.Submit(1, &commands);
}
DAWN_INSTANTIATE_TEST(DebugMarkerTests, D3D12Backend, MetalBackend, OpenGLBackend, VulkanBackend)

View File

@ -0,0 +1,117 @@
// 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/DawnHelpers.h"
class DebugMarkerValidationTest : public ValidationTest {};
// Correct usage of debug markers should succeed in render pass.
TEST_F(DebugMarkerValidationTest, RenderSuccess) {
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 4, 4);
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
{
dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
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) {
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 4, 4);
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
{
dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
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) {
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 4, 4);
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
{
dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
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 compute pass.
TEST_F(DebugMarkerValidationTest, ComputeSuccess) {
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
{
dawn::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) {
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
{
dawn::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) {
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
{
dawn::ComputePassEncoder pass = encoder.BeginComputePass();
pass.PushDebugGroup("Event Start");
pass.InsertDebugMarker("Marker");
pass.PopDebugGroup();
pass.PopDebugGroup();
pass.EndPass();
}
ASSERT_DEVICE_ERROR(encoder.Finish());
}