Factor RenderPass command validation

Validation of GPURenderBundle will share code with RenderPass
validation. Factor validation of commands for GPURenderBundle
into a separate function.

Bug: dawn:154
Change-Id: I79a229592ead27d462da0dd2d12fbdb95443ff19
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/9980
Commit-Queue: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
Austin Eng 2019-08-13 00:22:28 +00:00 committed by Commit Bot service account
parent 9b45b5aafa
commit 3318caaa51
7 changed files with 366 additions and 280 deletions

View File

@ -124,6 +124,8 @@ source_set("libdawn_native_sources") {
"src/dawn_native/CommandBufferStateTracker.h", "src/dawn_native/CommandBufferStateTracker.h",
"src/dawn_native/CommandEncoder.cpp", "src/dawn_native/CommandEncoder.cpp",
"src/dawn_native/CommandEncoder.h", "src/dawn_native/CommandEncoder.h",
"src/dawn_native/CommandValidation.cpp",
"src/dawn_native/CommandValidation.h",
"src/dawn_native/Commands.cpp", "src/dawn_native/Commands.cpp",
"src/dawn_native/Commands.h", "src/dawn_native/Commands.h",
"src/dawn_native/ComputePassEncoder.cpp", "src/dawn_native/ComputePassEncoder.cpp",

View File

@ -19,6 +19,7 @@
#include "dawn_native/Buffer.h" #include "dawn_native/Buffer.h"
#include "dawn_native/CommandBuffer.h" #include "dawn_native/CommandBuffer.h"
#include "dawn_native/CommandBufferStateTracker.h" #include "dawn_native/CommandBufferStateTracker.h"
#include "dawn_native/CommandValidation.h"
#include "dawn_native/Commands.h" #include "dawn_native/Commands.h"
#include "dawn_native/ComputePassEncoder.h" #include "dawn_native/ComputePassEncoder.h"
#include "dawn_native/Device.h" #include "dawn_native/Device.h"
@ -121,29 +122,6 @@ namespace dawn_native {
return {}; 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 ValidateTextureSampleCountInCopyCommands(const TextureBase* texture) { MaybeError ValidateTextureSampleCountInCopyCommands(const TextureBase* texture) {
if (texture->GetSampleCount() > 1) { if (texture->GetSampleCount() > 1) {
return DAWN_VALIDATION_ERROR("The sample count of textures must be 1"); return DAWN_VALIDATION_ERROR("The sample count of textures must be 1");
@ -476,39 +454,6 @@ namespace dawn_native {
return {}; return {};
} }
void TrackBindGroupResourceUsage(BindGroupBase* group, PassResourceUsageTracker* tracker) {
const auto& layoutInfo = group->GetLayout()->GetBindingInfo();
for (uint32_t i : IterateBitSet(layoutInfo.mask)) {
dawn::BindingType type = layoutInfo.types[i];
switch (type) {
case dawn::BindingType::UniformBuffer: {
BufferBase* buffer = group->GetBindingAsBufferBinding(i).buffer;
tracker->BufferUsedAs(buffer, dawn::BufferUsageBit::Uniform);
} break;
case dawn::BindingType::StorageBuffer: {
BufferBase* buffer = group->GetBindingAsBufferBinding(i).buffer;
tracker->BufferUsedAs(buffer, dawn::BufferUsageBit::Storage);
} break;
case dawn::BindingType::SampledTexture: {
TextureBase* texture = group->GetBindingAsTextureView(i)->GetTexture();
tracker->TextureUsedAs(texture, dawn::TextureUsageBit::Sampled);
} break;
case dawn::BindingType::Sampler:
break;
case dawn::BindingType::StorageTexture:
case dawn::BindingType::ReadonlyStorageBuffer:
UNREACHABLE();
break;
}
}
}
} // namespace } // namespace
CommandEncoderBase::CommandEncoderBase(DeviceBase* device, const CommandEncoderDescriptor*) CommandEncoderBase::CommandEncoderBase(DeviceBase* device, const CommandEncoderDescriptor*)
@ -749,12 +694,12 @@ namespace dawn_native {
switch (type) { switch (type) {
case Command::BeginComputePass: { case Command::BeginComputePass: {
commands->NextCommand<BeginComputePassCmd>(); commands->NextCommand<BeginComputePassCmd>();
DAWN_TRY(ValidateComputePass(commands)); DAWN_TRY(ValidateComputePass(commands, &mResourceUsages.perPass));
} break; } break;
case Command::BeginRenderPass: { case Command::BeginRenderPass: {
BeginRenderPassCmd* cmd = commands->NextCommand<BeginRenderPassCmd>(); BeginRenderPassCmd* cmd = commands->NextCommand<BeginRenderPassCmd>();
DAWN_TRY(ValidateRenderPass(commands, cmd)); DAWN_TRY(ValidateRenderPass(commands, cmd, &mResourceUsages.perPass));
} break; } break;
case Command::CopyBufferToBuffer: { case Command::CopyBufferToBuffer: {
@ -881,211 +826,4 @@ namespace dawn_native {
return {}; return {};
} }
MaybeError CommandEncoderBase::ValidateComputePass(CommandIterator* commands) {
PassResourceUsageTracker usageTracker;
CommandBufferStateTracker persistentState;
Command type;
while (commands->NextCommandId(&type)) {
switch (type) {
case Command::EndComputePass: {
commands->NextCommand<EndComputePassCmd>();
DAWN_TRY(ValidateDebugGroups(mDebugGroupStackSize));
DAWN_TRY(usageTracker.ValidateComputePassUsages());
mResourceUsages.perPass.push_back(usageTracker.AcquireResourceUsage());
return {};
} break;
case Command::Dispatch: {
commands->NextCommand<DispatchCmd>();
DAWN_TRY(persistentState.ValidateCanDispatch());
} break;
case Command::DispatchIndirect: {
DispatchIndirectCmd* cmd = commands->NextCommand<DispatchIndirectCmd>();
DAWN_TRY(persistentState.ValidateCanDispatch());
usageTracker.BufferUsedAs(cmd->indirectBuffer.Get(),
dawn::BufferUsageBit::Indirect);
} break;
case Command::InsertDebugMarker: {
InsertDebugMarkerCmd* cmd = commands->NextCommand<InsertDebugMarkerCmd>();
commands->NextData<char>(cmd->length + 1);
} break;
case Command::PopDebugGroup: {
commands->NextCommand<PopDebugGroupCmd>();
DAWN_TRY(PopDebugMarkerStack(&mDebugGroupStackSize));
} break;
case Command::PushDebugGroup: {
PushDebugGroupCmd* cmd = commands->NextCommand<PushDebugGroupCmd>();
commands->NextData<char>(cmd->length + 1);
DAWN_TRY(PushDebugMarkerStack(&mDebugGroupStackSize));
} break;
case Command::SetComputePipeline: {
SetComputePipelineCmd* cmd = commands->NextCommand<SetComputePipelineCmd>();
ComputePipelineBase* pipeline = cmd->pipeline.Get();
persistentState.SetComputePipeline(pipeline);
} break;
case Command::SetBindGroup: {
SetBindGroupCmd* cmd = commands->NextCommand<SetBindGroupCmd>();
if (cmd->dynamicOffsetCount > 0) {
commands->NextData<uint64_t>(cmd->dynamicOffsetCount);
}
TrackBindGroupResourceUsage(cmd->group.Get(), &usageTracker);
persistentState.SetBindGroup(cmd->index, cmd->group.Get());
} break;
default:
return DAWN_VALIDATION_ERROR("Command disallowed inside a compute pass");
}
}
UNREACHABLE();
return DAWN_VALIDATION_ERROR("Unfinished compute pass");
}
MaybeError CommandEncoderBase::ValidateRenderPass(CommandIterator* commands,
BeginRenderPassCmd* renderPass) {
PassResourceUsageTracker usageTracker;
CommandBufferStateTracker persistentState;
// Track usage of the render pass attachments
for (uint32_t i : IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
RenderPassColorAttachmentInfo* colorAttachment = &renderPass->colorAttachments[i];
TextureBase* texture = colorAttachment->view->GetTexture();
usageTracker.TextureUsedAs(texture, dawn::TextureUsageBit::OutputAttachment);
TextureViewBase* resolveTarget = colorAttachment->resolveTarget.Get();
if (resolveTarget != nullptr) {
usageTracker.TextureUsedAs(resolveTarget->GetTexture(),
dawn::TextureUsageBit::OutputAttachment);
}
}
if (renderPass->attachmentState->HasDepthStencilAttachment()) {
TextureBase* texture = renderPass->depthStencilAttachment.view->GetTexture();
usageTracker.TextureUsedAs(texture, dawn::TextureUsageBit::OutputAttachment);
}
Command type;
while (commands->NextCommandId(&type)) {
switch (type) {
case Command::EndRenderPass: {
commands->NextCommand<EndRenderPassCmd>();
DAWN_TRY(ValidateDebugGroups(mDebugGroupStackSize));
DAWN_TRY(usageTracker.ValidateRenderPassUsages());
mResourceUsages.perPass.push_back(usageTracker.AcquireResourceUsage());
return {};
} break;
case Command::Draw: {
commands->NextCommand<DrawCmd>();
DAWN_TRY(persistentState.ValidateCanDraw());
} break;
case Command::DrawIndexed: {
commands->NextCommand<DrawIndexedCmd>();
DAWN_TRY(persistentState.ValidateCanDrawIndexed());
} break;
case Command::DrawIndirect: {
DrawIndirectCmd* cmd = commands->NextCommand<DrawIndirectCmd>();
DAWN_TRY(persistentState.ValidateCanDraw());
usageTracker.BufferUsedAs(cmd->indirectBuffer.Get(),
dawn::BufferUsageBit::Indirect);
} break;
case Command::DrawIndexedIndirect: {
DrawIndexedIndirectCmd* cmd = commands->NextCommand<DrawIndexedIndirectCmd>();
DAWN_TRY(persistentState.ValidateCanDrawIndexed());
usageTracker.BufferUsedAs(cmd->indirectBuffer.Get(),
dawn::BufferUsageBit::Indirect);
} break;
case Command::InsertDebugMarker: {
InsertDebugMarkerCmd* cmd = commands->NextCommand<InsertDebugMarkerCmd>();
commands->NextData<char>(cmd->length + 1);
} break;
case Command::PopDebugGroup: {
commands->NextCommand<PopDebugGroupCmd>();
DAWN_TRY(PopDebugMarkerStack(&mDebugGroupStackSize));
} break;
case Command::PushDebugGroup: {
PushDebugGroupCmd* cmd = commands->NextCommand<PushDebugGroupCmd>();
commands->NextData<char>(cmd->length + 1);
DAWN_TRY(PushDebugMarkerStack(&mDebugGroupStackSize));
} break;
case Command::SetRenderPipeline: {
SetRenderPipelineCmd* cmd = commands->NextCommand<SetRenderPipelineCmd>();
RenderPipelineBase* pipeline = cmd->pipeline.Get();
DAWN_TRY(pipeline->ValidateCompatibleWith(renderPass));
persistentState.SetRenderPipeline(pipeline);
} break;
case Command::SetStencilReference: {
commands->NextCommand<SetStencilReferenceCmd>();
} break;
case Command::SetBlendColor: {
commands->NextCommand<SetBlendColorCmd>();
} break;
case Command::SetViewport: {
commands->NextCommand<SetViewportCmd>();
} break;
case Command::SetScissorRect: {
commands->NextCommand<SetScissorRectCmd>();
} break;
case Command::SetBindGroup: {
SetBindGroupCmd* cmd = commands->NextCommand<SetBindGroupCmd>();
if (cmd->dynamicOffsetCount > 0) {
commands->NextData<uint64_t>(cmd->dynamicOffsetCount);
}
TrackBindGroupResourceUsage(cmd->group.Get(), &usageTracker);
persistentState.SetBindGroup(cmd->index, cmd->group.Get());
} break;
case Command::SetIndexBuffer: {
SetIndexBufferCmd* cmd = commands->NextCommand<SetIndexBufferCmd>();
usageTracker.BufferUsedAs(cmd->buffer.Get(), dawn::BufferUsageBit::Index);
persistentState.SetIndexBuffer();
} break;
case Command::SetVertexBuffers: {
SetVertexBuffersCmd* cmd = commands->NextCommand<SetVertexBuffersCmd>();
auto buffers = commands->NextData<Ref<BufferBase>>(cmd->count);
commands->NextData<uint64_t>(cmd->count);
for (uint32_t i = 0; i < cmd->count; ++i) {
usageTracker.BufferUsedAs(buffers[i].Get(), dawn::BufferUsageBit::Vertex);
}
persistentState.SetVertexBuffer(cmd->startSlot, cmd->count);
} break;
default:
return DAWN_VALIDATION_ERROR("Command disallowed inside a render pass");
}
}
UNREACHABLE();
return DAWN_VALIDATION_ERROR("Unfinished render pass");
}
} // namespace dawn_native } // namespace dawn_native

View File

@ -56,15 +56,11 @@ namespace dawn_native {
private: private:
MaybeError ValidateFinish(const CommandBufferDescriptor* descriptor); MaybeError ValidateFinish(const CommandBufferDescriptor* descriptor);
MaybeError ValidateComputePass(CommandIterator* commands);
MaybeError ValidateRenderPass(CommandIterator* commands, BeginRenderPassCmd* renderPass);
EncodingContext mEncodingContext; EncodingContext mEncodingContext;
bool mWereResourceUsagesAcquired = false; bool mWereResourceUsagesAcquired = false;
CommandBufferResourceUsage mResourceUsages; CommandBufferResourceUsage mResourceUsages;
unsigned int mDebugGroupStackSize = 0;
}; };
} // namespace dawn_native } // namespace dawn_native

View File

@ -0,0 +1,321 @@
// 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 "dawn_native/CommandValidation.h"
#include "common/BitSetIterator.h"
#include "dawn_native/BindGroup.h"
#include "dawn_native/CommandBufferStateTracker.h"
#include "dawn_native/Commands.h"
#include "dawn_native/PassResourceUsageTracker.h"
#include "dawn_native/RenderPipeline.h"
namespace dawn_native {
namespace {
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 {};
}
void TrackBindGroupResourceUsage(BindGroupBase* group,
PassResourceUsageTracker* usageTracker) {
const auto& layoutInfo = group->GetLayout()->GetBindingInfo();
for (uint32_t i : IterateBitSet(layoutInfo.mask)) {
dawn::BindingType type = layoutInfo.types[i];
switch (type) {
case dawn::BindingType::UniformBuffer: {
BufferBase* buffer = group->GetBindingAsBufferBinding(i).buffer;
usageTracker->BufferUsedAs(buffer, dawn::BufferUsageBit::Uniform);
} break;
case dawn::BindingType::StorageBuffer: {
BufferBase* buffer = group->GetBindingAsBufferBinding(i).buffer;
usageTracker->BufferUsedAs(buffer, dawn::BufferUsageBit::Storage);
} break;
case dawn::BindingType::SampledTexture: {
TextureBase* texture = group->GetBindingAsTextureView(i)->GetTexture();
usageTracker->TextureUsedAs(texture, dawn::TextureUsageBit::Sampled);
} break;
case dawn::BindingType::Sampler:
break;
case dawn::BindingType::StorageTexture:
case dawn::BindingType::ReadonlyStorageBuffer:
UNREACHABLE();
break;
}
}
}
inline MaybeError ValidateRenderBundleCommand(CommandIterator* commands,
Command type,
PassResourceUsageTracker* usageTracker,
CommandBufferStateTracker* commandBufferState,
const AttachmentState* attachmentState,
unsigned int* debugGroupStackSize,
const char* disallowedMessage) {
switch (type) {
case Command::Draw: {
commands->NextCommand<DrawCmd>();
DAWN_TRY(commandBufferState->ValidateCanDraw());
} break;
case Command::DrawIndexed: {
commands->NextCommand<DrawIndexedCmd>();
DAWN_TRY(commandBufferState->ValidateCanDrawIndexed());
} break;
case Command::DrawIndirect: {
DrawIndirectCmd* cmd = commands->NextCommand<DrawIndirectCmd>();
DAWN_TRY(commandBufferState->ValidateCanDraw());
usageTracker->BufferUsedAs(cmd->indirectBuffer.Get(),
dawn::BufferUsageBit::Indirect);
} break;
case Command::DrawIndexedIndirect: {
DrawIndexedIndirectCmd* cmd = commands->NextCommand<DrawIndexedIndirectCmd>();
DAWN_TRY(commandBufferState->ValidateCanDrawIndexed());
usageTracker->BufferUsedAs(cmd->indirectBuffer.Get(),
dawn::BufferUsageBit::Indirect);
} break;
case Command::InsertDebugMarker: {
InsertDebugMarkerCmd* cmd = commands->NextCommand<InsertDebugMarkerCmd>();
commands->NextData<char>(cmd->length + 1);
} break;
case Command::PopDebugGroup: {
commands->NextCommand<PopDebugGroupCmd>();
DAWN_TRY(PopDebugMarkerStack(debugGroupStackSize));
} break;
case Command::PushDebugGroup: {
PushDebugGroupCmd* cmd = commands->NextCommand<PushDebugGroupCmd>();
commands->NextData<char>(cmd->length + 1);
DAWN_TRY(PushDebugMarkerStack(debugGroupStackSize));
} break;
case Command::SetRenderPipeline: {
SetRenderPipelineCmd* cmd = commands->NextCommand<SetRenderPipelineCmd>();
RenderPipelineBase* pipeline = cmd->pipeline.Get();
if (DAWN_UNLIKELY(pipeline->GetAttachmentState() != attachmentState)) {
return DAWN_VALIDATION_ERROR("Pipeline attachment state is not compatible");
}
commandBufferState->SetRenderPipeline(pipeline);
} break;
case Command::SetBindGroup: {
SetBindGroupCmd* cmd = commands->NextCommand<SetBindGroupCmd>();
if (cmd->dynamicOffsetCount > 0) {
commands->NextData<uint64_t>(cmd->dynamicOffsetCount);
}
TrackBindGroupResourceUsage(cmd->group.Get(), usageTracker);
commandBufferState->SetBindGroup(cmd->index, cmd->group.Get());
} break;
case Command::SetIndexBuffer: {
SetIndexBufferCmd* cmd = commands->NextCommand<SetIndexBufferCmd>();
usageTracker->BufferUsedAs(cmd->buffer.Get(), dawn::BufferUsageBit::Index);
commandBufferState->SetIndexBuffer();
} break;
case Command::SetVertexBuffers: {
SetVertexBuffersCmd* cmd = commands->NextCommand<SetVertexBuffersCmd>();
auto buffers = commands->NextData<Ref<BufferBase>>(cmd->count);
commands->NextData<uint64_t>(cmd->count);
for (uint32_t i = 0; i < cmd->count; ++i) {
usageTracker->BufferUsedAs(buffers[i].Get(), dawn::BufferUsageBit::Vertex);
}
commandBufferState->SetVertexBuffer(cmd->startSlot, cmd->count);
} break;
default:
return DAWN_VALIDATION_ERROR(disallowedMessage);
}
return {};
}
} // namespace
MaybeError ValidateRenderPass(CommandIterator* commands,
BeginRenderPassCmd* renderPass,
std::vector<PassResourceUsage>* perPassResourceUsages) {
PassResourceUsageTracker usageTracker;
CommandBufferStateTracker commandBufferState;
unsigned int debugGroupStackSize = 0;
// Track usage of the render pass attachments
for (uint32_t i : IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
RenderPassColorAttachmentInfo* colorAttachment = &renderPass->colorAttachments[i];
TextureBase* texture = colorAttachment->view->GetTexture();
usageTracker.TextureUsedAs(texture, dawn::TextureUsageBit::OutputAttachment);
TextureViewBase* resolveTarget = colorAttachment->resolveTarget.Get();
if (resolveTarget != nullptr) {
usageTracker.TextureUsedAs(resolveTarget->GetTexture(),
dawn::TextureUsageBit::OutputAttachment);
}
}
if (renderPass->attachmentState->HasDepthStencilAttachment()) {
TextureBase* texture = renderPass->depthStencilAttachment.view->GetTexture();
usageTracker.TextureUsedAs(texture, dawn::TextureUsageBit::OutputAttachment);
}
Command type;
while (commands->NextCommandId(&type)) {
switch (type) {
case Command::EndRenderPass: {
commands->NextCommand<EndRenderPassCmd>();
DAWN_TRY(ValidateDebugGroups(debugGroupStackSize));
DAWN_TRY(usageTracker.ValidateRenderPassUsages());
ASSERT(perPassResourceUsages != nullptr);
perPassResourceUsages->push_back(usageTracker.AcquireResourceUsage());
return {};
} break;
case Command::SetStencilReference: {
commands->NextCommand<SetStencilReferenceCmd>();
} break;
case Command::SetBlendColor: {
commands->NextCommand<SetBlendColorCmd>();
} break;
case Command::SetViewport: {
commands->NextCommand<SetViewportCmd>();
} break;
case Command::SetScissorRect: {
commands->NextCommand<SetScissorRectCmd>();
} break;
default:
DAWN_TRY(ValidateRenderBundleCommand(
commands, type, &usageTracker, &commandBufferState,
renderPass->attachmentState.Get(), &debugGroupStackSize,
"Command disallowed inside a render pass"));
}
}
UNREACHABLE();
return DAWN_VALIDATION_ERROR("Unfinished render pass");
}
MaybeError ValidateComputePass(CommandIterator* commands,
std::vector<PassResourceUsage>* perPassResourceUsages) {
PassResourceUsageTracker usageTracker;
CommandBufferStateTracker commandBufferState;
unsigned int debugGroupStackSize = 0;
Command type;
while (commands->NextCommandId(&type)) {
switch (type) {
case Command::EndComputePass: {
commands->NextCommand<EndComputePassCmd>();
DAWN_TRY(ValidateDebugGroups(debugGroupStackSize));
DAWN_TRY(usageTracker.ValidateComputePassUsages());
ASSERT(perPassResourceUsages != nullptr);
perPassResourceUsages->push_back(usageTracker.AcquireResourceUsage());
return {};
} break;
case Command::Dispatch: {
commands->NextCommand<DispatchCmd>();
DAWN_TRY(commandBufferState.ValidateCanDispatch());
} break;
case Command::DispatchIndirect: {
DispatchIndirectCmd* cmd = commands->NextCommand<DispatchIndirectCmd>();
DAWN_TRY(commandBufferState.ValidateCanDispatch());
usageTracker.BufferUsedAs(cmd->indirectBuffer.Get(),
dawn::BufferUsageBit::Indirect);
} break;
case Command::InsertDebugMarker: {
InsertDebugMarkerCmd* cmd = commands->NextCommand<InsertDebugMarkerCmd>();
commands->NextData<char>(cmd->length + 1);
} break;
case Command::PopDebugGroup: {
commands->NextCommand<PopDebugGroupCmd>();
DAWN_TRY(PopDebugMarkerStack(&debugGroupStackSize));
} break;
case Command::PushDebugGroup: {
PushDebugGroupCmd* cmd = commands->NextCommand<PushDebugGroupCmd>();
commands->NextData<char>(cmd->length + 1);
DAWN_TRY(PushDebugMarkerStack(&debugGroupStackSize));
} break;
case Command::SetComputePipeline: {
SetComputePipelineCmd* cmd = commands->NextCommand<SetComputePipelineCmd>();
ComputePipelineBase* pipeline = cmd->pipeline.Get();
commandBufferState.SetComputePipeline(pipeline);
} break;
case Command::SetBindGroup: {
SetBindGroupCmd* cmd = commands->NextCommand<SetBindGroupCmd>();
if (cmd->dynamicOffsetCount > 0) {
commands->NextData<uint64_t>(cmd->dynamicOffsetCount);
}
TrackBindGroupResourceUsage(cmd->group.Get(), &usageTracker);
commandBufferState.SetBindGroup(cmd->index, cmd->group.Get());
} break;
default:
return DAWN_VALIDATION_ERROR("Command disallowed inside a compute pass");
}
}
UNREACHABLE();
return DAWN_VALIDATION_ERROR("Unfinished compute pass");
}
} // namespace dawn_native

View File

@ -0,0 +1,36 @@
// 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.
#ifndef DAWNNATIVE_COMMANDVALIDATION_H_
#define DAWNNATIVE_COMMANDVALIDATION_H_
#include "dawn_native/CommandAllocator.h"
#include "dawn_native/Error.h"
#include <vector>
namespace dawn_native {
struct BeginRenderPassCmd;
struct PassResourceUsage;
MaybeError ValidateRenderPass(CommandIterator* commands,
BeginRenderPassCmd* renderPass,
std::vector<PassResourceUsage>* perPassResourceUsages);
MaybeError ValidateComputePass(CommandIterator* commands,
std::vector<PassResourceUsage>* perPassResourceUsages);
} // namespace dawn_native
#endif // DAWNNATIVE_COMMANDVALIDATION_H_

View File

@ -514,16 +514,10 @@ namespace dawn_native {
return mAttachmentState->GetSampleCount(); return mAttachmentState->GetSampleCount();
} }
MaybeError RenderPipelineBase::ValidateCompatibleWith( const AttachmentState* RenderPipelineBase::GetAttachmentState() const {
const BeginRenderPassCmd* renderPass) const {
ASSERT(!IsError()); ASSERT(!IsError());
if (renderPass->attachmentState.Get() != mAttachmentState.Get()) { return mAttachmentState.Get();
return DAWN_VALIDATION_ERROR(
"Pipeline attachment state is not compatible with render pass");
}
return {};
} }
std::bitset<kMaxVertexAttributes> RenderPipelineBase::GetAttributesUsingInput( std::bitset<kMaxVertexAttributes> RenderPipelineBase::GetAttributesUsingInput(

View File

@ -78,9 +78,8 @@ namespace dawn_native {
dawn::TextureFormat GetDepthStencilFormat() const; dawn::TextureFormat GetDepthStencilFormat() const;
uint32_t GetSampleCount() const; uint32_t GetSampleCount() const;
// A pipeline can be used in a render pass if its attachment info matches the actual const AttachmentState* GetAttachmentState() const;
// attachments in the render pass. This returns whether it is the case.
MaybeError ValidateCompatibleWith(const BeginRenderPassCmd* renderPassCmd) const;
std::bitset<kMaxVertexAttributes> GetAttributesUsingInput(uint32_t slot) const; std::bitset<kMaxVertexAttributes> GetAttributesUsingInput(uint32_t slot) const;
std::array<std::bitset<kMaxVertexAttributes>, kMaxVertexBuffers> attributesUsingInput; std::array<std::bitset<kMaxVertexAttributes>, kMaxVertexBuffers> attributesUsingInput;