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>
diff --git a/BUILD.gn b/BUILD.gn
index 4375a36..074e244 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -124,6 +124,8 @@
"src/dawn_native/CommandBufferStateTracker.h",
"src/dawn_native/CommandEncoder.cpp",
"src/dawn_native/CommandEncoder.h",
+ "src/dawn_native/CommandValidation.cpp",
+ "src/dawn_native/CommandValidation.h",
"src/dawn_native/Commands.cpp",
"src/dawn_native/Commands.h",
"src/dawn_native/ComputePassEncoder.cpp",
diff --git a/src/dawn_native/CommandEncoder.cpp b/src/dawn_native/CommandEncoder.cpp
index 0fff02f..13bea84 100644
--- a/src/dawn_native/CommandEncoder.cpp
+++ b/src/dawn_native/CommandEncoder.cpp
@@ -19,6 +19,7 @@
#include "dawn_native/Buffer.h"
#include "dawn_native/CommandBuffer.h"
#include "dawn_native/CommandBufferStateTracker.h"
+#include "dawn_native/CommandValidation.h"
#include "dawn_native/Commands.h"
#include "dawn_native/ComputePassEncoder.h"
#include "dawn_native/Device.h"
@@ -121,29 +122,6 @@
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) {
if (texture->GetSampleCount() > 1) {
return DAWN_VALIDATION_ERROR("The sample count of textures must be 1");
@@ -476,39 +454,6 @@
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
CommandEncoderBase::CommandEncoderBase(DeviceBase* device, const CommandEncoderDescriptor*)
@@ -749,12 +694,12 @@
switch (type) {
case Command::BeginComputePass: {
commands->NextCommand<BeginComputePassCmd>();
- DAWN_TRY(ValidateComputePass(commands));
+ DAWN_TRY(ValidateComputePass(commands, &mResourceUsages.perPass));
} break;
case Command::BeginRenderPass: {
BeginRenderPassCmd* cmd = commands->NextCommand<BeginRenderPassCmd>();
- DAWN_TRY(ValidateRenderPass(commands, cmd));
+ DAWN_TRY(ValidateRenderPass(commands, cmd, &mResourceUsages.perPass));
} break;
case Command::CopyBufferToBuffer: {
@@ -881,211 +826,4 @@
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
diff --git a/src/dawn_native/CommandEncoder.h b/src/dawn_native/CommandEncoder.h
index 3a59e8e..bcb1137 100644
--- a/src/dawn_native/CommandEncoder.h
+++ b/src/dawn_native/CommandEncoder.h
@@ -56,15 +56,11 @@
private:
MaybeError ValidateFinish(const CommandBufferDescriptor* descriptor);
- MaybeError ValidateComputePass(CommandIterator* commands);
- MaybeError ValidateRenderPass(CommandIterator* commands, BeginRenderPassCmd* renderPass);
EncodingContext mEncodingContext;
bool mWereResourceUsagesAcquired = false;
CommandBufferResourceUsage mResourceUsages;
-
- unsigned int mDebugGroupStackSize = 0;
};
} // namespace dawn_native
diff --git a/src/dawn_native/CommandValidation.cpp b/src/dawn_native/CommandValidation.cpp
new file mode 100644
index 0000000..9099a9e
--- /dev/null
+++ b/src/dawn_native/CommandValidation.cpp
@@ -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
diff --git a/src/dawn_native/CommandValidation.h b/src/dawn_native/CommandValidation.h
new file mode 100644
index 0000000..2d29cb3
--- /dev/null
+++ b/src/dawn_native/CommandValidation.h
@@ -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_
diff --git a/src/dawn_native/RenderPipeline.cpp b/src/dawn_native/RenderPipeline.cpp
index a9fd5d7..6626c59 100644
--- a/src/dawn_native/RenderPipeline.cpp
+++ b/src/dawn_native/RenderPipeline.cpp
@@ -514,16 +514,10 @@
return mAttachmentState->GetSampleCount();
}
- MaybeError RenderPipelineBase::ValidateCompatibleWith(
- const BeginRenderPassCmd* renderPass) const {
+ const AttachmentState* RenderPipelineBase::GetAttachmentState() const {
ASSERT(!IsError());
- if (renderPass->attachmentState.Get() != mAttachmentState.Get()) {
- return DAWN_VALIDATION_ERROR(
- "Pipeline attachment state is not compatible with render pass");
- }
-
- return {};
+ return mAttachmentState.Get();
}
std::bitset<kMaxVertexAttributes> RenderPipelineBase::GetAttributesUsingInput(
diff --git a/src/dawn_native/RenderPipeline.h b/src/dawn_native/RenderPipeline.h
index f8e884e..7a00e3a 100644
--- a/src/dawn_native/RenderPipeline.h
+++ b/src/dawn_native/RenderPipeline.h
@@ -78,9 +78,8 @@
dawn::TextureFormat GetDepthStencilFormat() const;
uint32_t GetSampleCount() const;
- // A pipeline can be used in a render pass if its attachment info matches the actual
- // attachments in the render pass. This returns whether it is the case.
- MaybeError ValidateCompatibleWith(const BeginRenderPassCmd* renderPassCmd) const;
+ const AttachmentState* GetAttachmentState() const;
+
std::bitset<kMaxVertexAttributes> GetAttributesUsingInput(uint32_t slot) const;
std::array<std::bitset<kMaxVertexAttributes>, kMaxVertexBuffers> attributesUsingInput;