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>
This commit is contained in:
parent
c1d3a66bd2
commit
7ffaa219cb
|
@ -790,7 +790,13 @@ namespace dawn_native {
|
||||||
|
|
||||||
void CommandEncoder::PopDebugGroup() {
|
void CommandEncoder::PopDebugGroup() {
|
||||||
mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
|
mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
|
||||||
|
if (GetDevice()->IsValidationEnabled()) {
|
||||||
|
if (mDebugGroupStackSize == 0) {
|
||||||
|
return DAWN_VALIDATION_ERROR("Pop must be balanced by a corresponding Push.");
|
||||||
|
}
|
||||||
|
}
|
||||||
allocator->Allocate<PopDebugGroupCmd>(Command::PopDebugGroup);
|
allocator->Allocate<PopDebugGroupCmd>(Command::PopDebugGroup);
|
||||||
|
mDebugGroupStackSize--;
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
});
|
});
|
||||||
|
@ -805,6 +811,8 @@ namespace dawn_native {
|
||||||
char* label = allocator->AllocateData<char>(cmd->length + 1);
|
char* label = allocator->AllocateData<char>(cmd->length + 1);
|
||||||
memcpy(label, groupLabel, cmd->length + 1);
|
memcpy(label, groupLabel, cmd->length + 1);
|
||||||
|
|
||||||
|
mDebugGroupStackSize++;
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -890,7 +898,9 @@ namespace dawn_native {
|
||||||
DAWN_TRY(ValidatePassResourceUsage(passUsage));
|
DAWN_TRY(ValidatePassResourceUsage(passUsage));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t debugGroupStackSize = 0;
|
if (mDebugGroupStackSize != 0) {
|
||||||
|
return DAWN_VALIDATION_ERROR("Each Push must be balanced by a corresponding Pop.");
|
||||||
|
}
|
||||||
|
|
||||||
commands->Reset();
|
commands->Reset();
|
||||||
Command type;
|
Command type;
|
||||||
|
@ -936,15 +946,12 @@ namespace dawn_native {
|
||||||
|
|
||||||
case Command::PopDebugGroup: {
|
case Command::PopDebugGroup: {
|
||||||
commands->NextCommand<PopDebugGroupCmd>();
|
commands->NextCommand<PopDebugGroupCmd>();
|
||||||
DAWN_TRY(ValidateCanPopDebugGroup(debugGroupStackSize));
|
|
||||||
debugGroupStackSize--;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Command::PushDebugGroup: {
|
case Command::PushDebugGroup: {
|
||||||
const PushDebugGroupCmd* cmd = commands->NextCommand<PushDebugGroupCmd>();
|
const PushDebugGroupCmd* cmd = commands->NextCommand<PushDebugGroupCmd>();
|
||||||
commands->NextData<char>(cmd->length + 1);
|
commands->NextData<char>(cmd->length + 1);
|
||||||
debugGroupStackSize++;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -962,8 +969,6 @@ namespace dawn_native {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DAWN_TRY(ValidateFinalDebugGroupStackSize(debugGroupStackSize));
|
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,6 +84,8 @@ namespace dawn_native {
|
||||||
std::set<TextureBase*> mTopLevelTextures;
|
std::set<TextureBase*> mTopLevelTextures;
|
||||||
std::set<QuerySetBase*> mUsedQuerySets;
|
std::set<QuerySetBase*> mUsedQuerySets;
|
||||||
QueryAvailabilityMap mQueryAvailabilityMap;
|
QueryAvailabilityMap mQueryAvailabilityMap;
|
||||||
|
|
||||||
|
uint64_t mDebugGroupStackSize = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dawn_native
|
} // namespace dawn_native
|
||||||
|
|
|
@ -33,7 +33,6 @@ namespace dawn_native {
|
||||||
Command type,
|
Command type,
|
||||||
CommandBufferStateTracker* commandBufferState,
|
CommandBufferStateTracker* commandBufferState,
|
||||||
const AttachmentState* attachmentState,
|
const AttachmentState* attachmentState,
|
||||||
uint64_t* debugGroupStackSize,
|
|
||||||
const char* disallowedMessage) {
|
const char* disallowedMessage) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Command::Draw: {
|
case Command::Draw: {
|
||||||
|
@ -68,15 +67,12 @@ namespace dawn_native {
|
||||||
|
|
||||||
case Command::PopDebugGroup: {
|
case Command::PopDebugGroup: {
|
||||||
commands->NextCommand<PopDebugGroupCmd>();
|
commands->NextCommand<PopDebugGroupCmd>();
|
||||||
DAWN_TRY(ValidateCanPopDebugGroup(*debugGroupStackSize));
|
|
||||||
*debugGroupStackSize -= 1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Command::PushDebugGroup: {
|
case Command::PushDebugGroup: {
|
||||||
PushDebugGroupCmd* cmd = commands->NextCommand<PushDebugGroupCmd>();
|
PushDebugGroupCmd* cmd = commands->NextCommand<PushDebugGroupCmd>();
|
||||||
commands->NextData<char>(cmd->length + 1);
|
commands->NextData<char>(cmd->length + 1);
|
||||||
*debugGroupStackSize += 1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,40 +118,21 @@ namespace dawn_native {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
MaybeError ValidateCanPopDebugGroup(uint64_t debugGroupStackSize) {
|
|
||||||
if (debugGroupStackSize == 0) {
|
|
||||||
return DAWN_VALIDATION_ERROR("Pop must be balanced by a corresponding Push.");
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
MaybeError ValidateFinalDebugGroupStackSize(uint64_t debugGroupStackSize) {
|
|
||||||
if (debugGroupStackSize != 0) {
|
|
||||||
return DAWN_VALIDATION_ERROR("Each Push must be balanced by a corresponding Pop.");
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
MaybeError ValidateRenderBundle(CommandIterator* commands,
|
MaybeError ValidateRenderBundle(CommandIterator* commands,
|
||||||
const AttachmentState* attachmentState) {
|
const AttachmentState* attachmentState) {
|
||||||
CommandBufferStateTracker commandBufferState;
|
CommandBufferStateTracker commandBufferState;
|
||||||
uint64_t debugGroupStackSize = 0;
|
|
||||||
|
|
||||||
Command type;
|
Command type;
|
||||||
while (commands->NextCommandId(&type)) {
|
while (commands->NextCommandId(&type)) {
|
||||||
DAWN_TRY(ValidateRenderBundleCommand(commands, type, &commandBufferState,
|
DAWN_TRY(ValidateRenderBundleCommand(commands, type, &commandBufferState,
|
||||||
attachmentState, &debugGroupStackSize,
|
attachmentState,
|
||||||
"Command disallowed inside a render bundle"));
|
"Command disallowed inside a render bundle"));
|
||||||
}
|
}
|
||||||
|
|
||||||
DAWN_TRY(ValidateFinalDebugGroupStackSize(debugGroupStackSize));
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError ValidateRenderPass(CommandIterator* commands, const BeginRenderPassCmd* renderPass) {
|
MaybeError ValidateRenderPass(CommandIterator* commands, const BeginRenderPassCmd* renderPass) {
|
||||||
CommandBufferStateTracker commandBufferState;
|
CommandBufferStateTracker commandBufferState;
|
||||||
uint64_t debugGroupStackSize = 0;
|
|
||||||
|
|
||||||
Command type;
|
Command type;
|
||||||
while (commands->NextCommandId(&type)) {
|
while (commands->NextCommandId(&type)) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -171,7 +148,6 @@ namespace dawn_native {
|
||||||
|
|
||||||
case Command::EndRenderPass: {
|
case Command::EndRenderPass: {
|
||||||
commands->NextCommand<EndRenderPassCmd>();
|
commands->NextCommand<EndRenderPassCmd>();
|
||||||
DAWN_TRY(ValidateFinalDebugGroupStackSize(debugGroupStackSize));
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,7 +198,7 @@ namespace dawn_native {
|
||||||
default:
|
default:
|
||||||
DAWN_TRY(ValidateRenderBundleCommand(
|
DAWN_TRY(ValidateRenderBundleCommand(
|
||||||
commands, type, &commandBufferState, renderPass->attachmentState.Get(),
|
commands, type, &commandBufferState, renderPass->attachmentState.Get(),
|
||||||
&debugGroupStackSize, "Command disallowed inside a render pass"));
|
"Command disallowed inside a render pass"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,14 +208,11 @@ namespace dawn_native {
|
||||||
|
|
||||||
MaybeError ValidateComputePass(CommandIterator* commands) {
|
MaybeError ValidateComputePass(CommandIterator* commands) {
|
||||||
CommandBufferStateTracker commandBufferState;
|
CommandBufferStateTracker commandBufferState;
|
||||||
uint64_t debugGroupStackSize = 0;
|
|
||||||
|
|
||||||
Command type;
|
Command type;
|
||||||
while (commands->NextCommandId(&type)) {
|
while (commands->NextCommandId(&type)) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Command::EndComputePass: {
|
case Command::EndComputePass: {
|
||||||
commands->NextCommand<EndComputePassCmd>();
|
commands->NextCommand<EndComputePassCmd>();
|
||||||
DAWN_TRY(ValidateFinalDebugGroupStackSize(debugGroupStackSize));
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,15 +236,12 @@ namespace dawn_native {
|
||||||
|
|
||||||
case Command::PopDebugGroup: {
|
case Command::PopDebugGroup: {
|
||||||
commands->NextCommand<PopDebugGroupCmd>();
|
commands->NextCommand<PopDebugGroupCmd>();
|
||||||
DAWN_TRY(ValidateCanPopDebugGroup(debugGroupStackSize));
|
|
||||||
debugGroupStackSize--;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Command::PushDebugGroup: {
|
case Command::PushDebugGroup: {
|
||||||
PushDebugGroupCmd* cmd = commands->NextCommand<PushDebugGroupCmd>();
|
PushDebugGroupCmd* cmd = commands->NextCommand<PushDebugGroupCmd>();
|
||||||
commands->NextData<char>(cmd->length + 1);
|
commands->NextData<char>(cmd->length + 1);
|
||||||
debugGroupStackSize++;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,9 +29,6 @@ namespace dawn_native {
|
||||||
struct PassResourceUsage;
|
struct PassResourceUsage;
|
||||||
struct TexelBlockInfo;
|
struct TexelBlockInfo;
|
||||||
|
|
||||||
MaybeError ValidateCanPopDebugGroup(uint64_t debugGroupStackSize);
|
|
||||||
MaybeError ValidateFinalDebugGroupStackSize(uint64_t debugGroupStackSize);
|
|
||||||
|
|
||||||
MaybeError ValidateRenderBundle(CommandIterator* commands,
|
MaybeError ValidateRenderBundle(CommandIterator* commands,
|
||||||
const AttachmentState* attachmentState);
|
const AttachmentState* attachmentState);
|
||||||
MaybeError ValidateRenderPass(CommandIterator* commands, const BeginRenderPassCmd* renderPass);
|
MaybeError ValidateRenderPass(CommandIterator* commands, const BeginRenderPassCmd* renderPass);
|
||||||
|
|
|
@ -47,6 +47,10 @@ namespace dawn_native {
|
||||||
|
|
||||||
void ComputePassEncoder::EndPass() {
|
void ComputePassEncoder::EndPass() {
|
||||||
if (mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
|
if (mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
|
||||||
|
if (IsValidationEnabled()) {
|
||||||
|
DAWN_TRY(ValidateProgrammableEncoderEnd());
|
||||||
|
}
|
||||||
|
|
||||||
allocator->Allocate<EndComputePassCmd>(Command::EndComputePass);
|
allocator->Allocate<EndComputePassCmd>(Command::EndComputePass);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -97,13 +97,20 @@ namespace dawn_native {
|
||||||
: ObjectBase(device, errorTag),
|
: ObjectBase(device, errorTag),
|
||||||
mEncodingContext(encodingContext),
|
mEncodingContext(encodingContext),
|
||||||
mUsageTracker(passType),
|
mUsageTracker(passType),
|
||||||
mValidationEnabled(false) {
|
mValidationEnabled(device->IsValidationEnabled()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProgrammablePassEncoder::IsValidationEnabled() const {
|
bool ProgrammablePassEncoder::IsValidationEnabled() const {
|
||||||
return mValidationEnabled;
|
return mValidationEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MaybeError ProgrammablePassEncoder::ValidateProgrammableEncoderEnd() const {
|
||||||
|
if (mDebugGroupStackSize != 0) {
|
||||||
|
return DAWN_VALIDATION_ERROR("Each Push must be balanced by a corresponding Pop.");
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void ProgrammablePassEncoder::InsertDebugMarker(const char* groupLabel) {
|
void ProgrammablePassEncoder::InsertDebugMarker(const char* groupLabel) {
|
||||||
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
|
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
|
||||||
InsertDebugMarkerCmd* cmd =
|
InsertDebugMarkerCmd* cmd =
|
||||||
|
@ -119,7 +126,13 @@ namespace dawn_native {
|
||||||
|
|
||||||
void ProgrammablePassEncoder::PopDebugGroup() {
|
void ProgrammablePassEncoder::PopDebugGroup() {
|
||||||
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
|
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
|
||||||
|
if (IsValidationEnabled()) {
|
||||||
|
if (mDebugGroupStackSize == 0) {
|
||||||
|
return DAWN_VALIDATION_ERROR("Pop must be balanced by a corresponding Push.");
|
||||||
|
}
|
||||||
|
}
|
||||||
allocator->Allocate<PopDebugGroupCmd>(Command::PopDebugGroup);
|
allocator->Allocate<PopDebugGroupCmd>(Command::PopDebugGroup);
|
||||||
|
mDebugGroupStackSize--;
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
});
|
});
|
||||||
|
@ -134,6 +147,8 @@ namespace dawn_native {
|
||||||
char* label = allocator->AllocateData<char>(cmd->length + 1);
|
char* label = allocator->AllocateData<char>(cmd->length + 1);
|
||||||
memcpy(label, groupLabel, cmd->length + 1);
|
memcpy(label, groupLabel, cmd->length + 1);
|
||||||
|
|
||||||
|
mDebugGroupStackSize++;
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,7 @@ namespace dawn_native {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool IsValidationEnabled() const;
|
bool IsValidationEnabled() const;
|
||||||
|
MaybeError ValidateProgrammableEncoderEnd() const;
|
||||||
|
|
||||||
// Construct an "error" programmable pass encoder.
|
// Construct an "error" programmable pass encoder.
|
||||||
ProgrammablePassEncoder(DeviceBase* device,
|
ProgrammablePassEncoder(DeviceBase* device,
|
||||||
|
@ -55,6 +56,8 @@ namespace dawn_native {
|
||||||
EncodingContext* mEncodingContext = nullptr;
|
EncodingContext* mEncodingContext = nullptr;
|
||||||
PassResourceUsageTracker mUsageTracker;
|
PassResourceUsageTracker mUsageTracker;
|
||||||
|
|
||||||
|
uint64_t mDebugGroupStackSize = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const bool mValidationEnabled;
|
const bool mValidationEnabled;
|
||||||
};
|
};
|
||||||
|
|
|
@ -103,19 +103,29 @@ namespace dawn_native {
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderBundleBase* RenderBundleEncoder::Finish(const RenderBundleDescriptor* descriptor) {
|
RenderBundleBase* RenderBundleEncoder::Finish(const RenderBundleDescriptor* descriptor) {
|
||||||
PassResourceUsage usages = mUsageTracker.AcquireResourceUsage();
|
RenderBundleBase* result = nullptr;
|
||||||
|
|
||||||
DeviceBase* device = GetDevice();
|
if (GetDevice()->ConsumedError(FinishImpl(descriptor), &result)) {
|
||||||
|
return RenderBundleBase::MakeError(GetDevice());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResultOrError<RenderBundleBase*> RenderBundleEncoder::FinishImpl(
|
||||||
|
const RenderBundleDescriptor* descriptor) {
|
||||||
// Even if mBundleEncodingContext.Finish() validation fails, calling it will mutate the
|
// Even if mBundleEncodingContext.Finish() validation fails, calling it will mutate the
|
||||||
// internal state of the encoding context. Subsequent calls to encode commands will generate
|
// internal state of the encoding context. Subsequent calls to encode commands will generate
|
||||||
// errors.
|
// errors.
|
||||||
if (device->ConsumedError(mBundleEncodingContext.Finish()) ||
|
DAWN_TRY(mBundleEncodingContext.Finish());
|
||||||
(device->IsValidationEnabled() &&
|
|
||||||
device->ConsumedError(ValidateFinish(mBundleEncodingContext.GetIterator(), usages)))) {
|
PassResourceUsage usages = mUsageTracker.AcquireResourceUsage();
|
||||||
return RenderBundleBase::MakeError(device);
|
if (IsValidationEnabled()) {
|
||||||
|
DAWN_TRY(GetDevice()->ValidateObject(this));
|
||||||
|
DAWN_TRY(ValidateProgrammableEncoderEnd());
|
||||||
|
DAWN_TRY(ValidateFinish(mBundleEncodingContext.GetIterator(), usages));
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(!IsError());
|
|
||||||
return new RenderBundleBase(this, descriptor, mAttachmentState.Get(), std::move(usages));
|
return new RenderBundleBase(this, descriptor, mAttachmentState.Get(), std::move(usages));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ namespace dawn_native {
|
||||||
private:
|
private:
|
||||||
RenderBundleEncoder(DeviceBase* device, ErrorTag errorTag);
|
RenderBundleEncoder(DeviceBase* device, ErrorTag errorTag);
|
||||||
|
|
||||||
|
ResultOrError<RenderBundleBase*> FinishImpl(const RenderBundleDescriptor* descriptor);
|
||||||
MaybeError ValidateFinish(CommandIterator* commands, const PassResourceUsage& usages) const;
|
MaybeError ValidateFinish(CommandIterator* commands, const PassResourceUsage& usages) const;
|
||||||
|
|
||||||
EncodingContext mBundleEncodingContext;
|
EncodingContext mBundleEncodingContext;
|
||||||
|
|
|
@ -94,15 +94,15 @@ namespace dawn_native {
|
||||||
|
|
||||||
void RenderPassEncoder::EndPass() {
|
void RenderPassEncoder::EndPass() {
|
||||||
if (mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
|
if (mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
|
||||||
allocator->Allocate<EndRenderPassCmd>(Command::EndRenderPass);
|
|
||||||
|
|
||||||
if (IsValidationEnabled()) {
|
if (IsValidationEnabled()) {
|
||||||
|
DAWN_TRY(ValidateProgrammableEncoderEnd());
|
||||||
if (mOcclusionQueryActive) {
|
if (mOcclusionQueryActive) {
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"The occlusion query must be ended before endPass.");
|
"The occlusion query must be ended before endPass.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allocator->Allocate<EndRenderPassCmd>(Command::EndRenderPass);
|
||||||
return {};
|
return {};
|
||||||
})) {
|
})) {
|
||||||
mEncodingContext->ExitPass(this, mUsageTracker.AcquireResourceUsage());
|
mEncodingContext->ExitPass(this, mUsageTracker.AcquireResourceUsage());
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include "tests/unittests/validation/ValidationTest.h"
|
#include "tests/unittests/validation/ValidationTest.h"
|
||||||
|
|
||||||
|
#include "utils/ComboRenderBundleEncoderDescriptor.h"
|
||||||
#include "utils/WGPUHelpers.h"
|
#include "utils/WGPUHelpers.h"
|
||||||
|
|
||||||
class DebugMarkerValidationTest : public ValidationTest {};
|
class DebugMarkerValidationTest : public ValidationTest {};
|
||||||
|
@ -70,6 +71,52 @@ TEST_F(DebugMarkerValidationTest, RenderUnbalancedPop) {
|
||||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
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.
|
// Correct usage of debug markers should succeed in compute pass.
|
||||||
TEST_F(DebugMarkerValidationTest, ComputeSuccess) {
|
TEST_F(DebugMarkerValidationTest, ComputeSuccess) {
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
|
|
|
@ -141,6 +141,28 @@ TEST_F(RenderBundleValidationTest, Empty) {
|
||||||
commandEncoder.Finish();
|
commandEncoder.Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that an empty error bundle encoder produces an error bundle.
|
||||||
|
// This is a regression test for error render bundle encoders containing no commands would
|
||||||
|
// produce non-error render bundles.
|
||||||
|
TEST_F(RenderBundleValidationTest, EmptyErrorEncoderProducesErrorBundle) {
|
||||||
|
DummyRenderPass renderPass(device);
|
||||||
|
|
||||||
|
utils::ComboRenderBundleEncoderDescriptor desc = {};
|
||||||
|
// Having 0 attachments is invalid!
|
||||||
|
desc.colorFormatsCount = 0;
|
||||||
|
|
||||||
|
wgpu::RenderBundleEncoder renderBundleEncoder;
|
||||||
|
ASSERT_DEVICE_ERROR(renderBundleEncoder = device.CreateRenderBundleEncoder(&desc));
|
||||||
|
wgpu::RenderBundle renderBundle;
|
||||||
|
ASSERT_DEVICE_ERROR(renderBundle = renderBundleEncoder.Finish());
|
||||||
|
|
||||||
|
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
|
||||||
|
wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPass);
|
||||||
|
pass.ExecuteBundles(1, &renderBundle);
|
||||||
|
pass.EndPass();
|
||||||
|
ASSERT_DEVICE_ERROR(commandEncoder.Finish());
|
||||||
|
}
|
||||||
|
|
||||||
// Test executing zero render bundles.
|
// Test executing zero render bundles.
|
||||||
TEST_F(RenderBundleValidationTest, ZeroBundles) {
|
TEST_F(RenderBundleValidationTest, ZeroBundles) {
|
||||||
DummyRenderPass renderPass(device);
|
DummyRenderPass renderPass(device);
|
||||||
|
|
Loading…
Reference in New Issue