dawn_native: Do attachment state validation at encoding time.

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: Ifb8b7883abe18089dc3d632baebbcc79b3f324f7
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/38843
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Stephen White <senorblanco@chromium.org>
This commit is contained in:
Corentin Wallez 2021-01-27 17:20:16 +00:00 committed by Commit Bot service account
parent 3b49f247b0
commit 95ff834028
11 changed files with 57 additions and 43 deletions

View File

@ -503,6 +503,7 @@ namespace dawn_native {
uint32_t width = 0;
uint32_t height = 0;
Ref<AttachmentState> attachmentState;
bool success =
mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
uint32_t sampleCount = 0;
@ -516,6 +517,7 @@ namespace dawn_native {
allocator->Allocate<BeginRenderPassCmd>(Command::BeginRenderPass);
cmd->attachmentState = device->GetOrCreateAttachmentState(descriptor);
attachmentState = cmd->attachmentState;
for (ColorAttachmentIndex index :
IterateBitSet(cmd->attachmentState->GetColorAttachmentsMask())) {
@ -565,9 +567,9 @@ namespace dawn_native {
});
if (success) {
RenderPassEncoder* passEncoder =
new RenderPassEncoder(device, this, &mEncodingContext, std::move(usageTracker),
descriptor->occlusionQuerySet, width, height);
RenderPassEncoder* passEncoder = new RenderPassEncoder(
device, this, &mEncodingContext, std::move(usageTracker),
std::move(attachmentState), descriptor->occlusionQuerySet, width, height);
mEncodingContext.EnterPass(passEncoder);
return passEncoder;
}

View File

@ -32,7 +32,6 @@ namespace dawn_native {
inline MaybeError ValidateRenderBundleCommand(CommandIterator* commands,
Command type,
CommandBufferStateTracker* commandBufferState,
const AttachmentState* attachmentState,
const char* disallowedMessage) {
switch (type) {
case Command::Draw: {
@ -79,10 +78,6 @@ namespace dawn_native {
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;
}
@ -118,13 +113,11 @@ namespace dawn_native {
} // namespace
MaybeError ValidateRenderBundle(CommandIterator* commands,
const AttachmentState* attachmentState) {
MaybeError ValidateRenderBundle(CommandIterator* commands) {
CommandBufferStateTracker commandBufferState;
Command type;
while (commands->NextCommandId(&type)) {
DAWN_TRY(ValidateRenderBundleCommand(commands, type, &commandBufferState,
attachmentState,
"Command disallowed inside a render bundle"));
}
@ -153,14 +146,7 @@ namespace dawn_native {
case Command::ExecuteBundles: {
ExecuteBundlesCmd* cmd = commands->NextCommand<ExecuteBundlesCmd>();
auto bundles = commands->NextData<Ref<RenderBundleBase>>(cmd->count);
for (uint32_t i = 0; i < cmd->count; ++i) {
if (DAWN_UNLIKELY(renderPass->attachmentState.Get() !=
bundles[i]->GetAttachmentState())) {
return DAWN_VALIDATION_ERROR(
"Render bundle is not compatible with render pass");
}
}
commands->NextData<Ref<RenderBundleBase>>(cmd->count);
if (cmd->count > 0) {
// Reset state. It is invalidated after render bundle execution.
@ -196,9 +182,9 @@ namespace dawn_native {
}
default:
DAWN_TRY(ValidateRenderBundleCommand(
commands, type, &commandBufferState, renderPass->attachmentState.Get(),
"Command disallowed inside a render pass"));
DAWN_TRY(
ValidateRenderBundleCommand(commands, type, &commandBufferState,
"Command disallowed inside a render pass"));
}
}

View File

@ -29,8 +29,7 @@ namespace dawn_native {
struct PassResourceUsage;
struct TexelBlockInfo;
MaybeError ValidateRenderBundle(CommandIterator* commands,
const AttachmentState* attachmentState);
MaybeError ValidateRenderBundle(CommandIterator* commands);
MaybeError ValidateRenderPass(CommandIterator* commands, const BeginRenderPassCmd* renderPass);
MaybeError ValidateComputePass(CommandIterator* commands);

View File

@ -23,11 +23,11 @@ namespace dawn_native {
RenderBundleBase::RenderBundleBase(RenderBundleEncoder* encoder,
const RenderBundleDescriptor* descriptor,
AttachmentState* attachmentState,
Ref<AttachmentState> attachmentState,
PassResourceUsage resourceUsage)
: ObjectBase(encoder->GetDevice()),
mCommands(encoder->AcquireCommands()),
mAttachmentState(attachmentState),
mAttachmentState(std::move(attachmentState)),
mResourceUsage(std::move(resourceUsage)) {
}

View File

@ -36,7 +36,7 @@ namespace dawn_native {
public:
RenderBundleBase(RenderBundleEncoder* encoder,
const RenderBundleDescriptor* descriptor,
AttachmentState* attachmentState,
Ref<AttachmentState> attachmentState,
PassResourceUsage resourceUsage);
static RenderBundleBase* MakeError(DeviceBase* device);

View File

@ -79,9 +79,10 @@ namespace dawn_native {
RenderBundleEncoder::RenderBundleEncoder(DeviceBase* device,
const RenderBundleEncoderDescriptor* descriptor)
: RenderEncoderBase(device, &mBundleEncodingContext),
mBundleEncodingContext(device, this),
mAttachmentState(device->GetOrCreateAttachmentState(descriptor)) {
: RenderEncoderBase(device,
&mBundleEncodingContext,
device->GetOrCreateAttachmentState(descriptor)),
mBundleEncodingContext(device, this) {
}
RenderBundleEncoder::RenderBundleEncoder(DeviceBase* device, ErrorTag errorTag)
@ -94,10 +95,6 @@ namespace dawn_native {
return new RenderBundleEncoder(device, ObjectBase::kError);
}
const AttachmentState* RenderBundleEncoder::GetAttachmentState() const {
return mAttachmentState.Get();
}
CommandIterator RenderBundleEncoder::AcquireCommands() {
return mBundleEncodingContext.AcquireCommands();
}
@ -126,7 +123,7 @@ namespace dawn_native {
DAWN_TRY(ValidateFinish(mBundleEncodingContext.GetIterator(), usages));
}
return new RenderBundleBase(this, descriptor, mAttachmentState.Get(), std::move(usages));
return new RenderBundleBase(this, descriptor, AcquireAttachmentState(), std::move(usages));
}
MaybeError RenderBundleEncoder::ValidateFinish(CommandIterator* commands,
@ -134,7 +131,7 @@ namespace dawn_native {
TRACE_EVENT0(GetDevice()->GetPlatform(), Validation, "RenderBundleEncoder::ValidateFinish");
DAWN_TRY(GetDevice()->ValidateObject(this));
DAWN_TRY(ValidatePassResourceUsage(usages));
DAWN_TRY(ValidateRenderBundle(commands, mAttachmentState.Get()));
DAWN_TRY(ValidateRenderBundle(commands));
return {};
}

View File

@ -15,7 +15,6 @@
#ifndef DAWNNATIVE_RENDERBUNDLEENCODER_H_
#define DAWNNATIVE_RENDERBUNDLEENCODER_H_
#include "dawn_native/AttachmentState.h"
#include "dawn_native/EncodingContext.h"
#include "dawn_native/Error.h"
#include "dawn_native/RenderBundle.h"
@ -33,8 +32,6 @@ namespace dawn_native {
static RenderBundleEncoder* MakeError(DeviceBase* device);
const AttachmentState* GetAttachmentState() const;
RenderBundleBase* Finish(const RenderBundleDescriptor* descriptor);
CommandIterator AcquireCommands();
@ -46,7 +43,6 @@ namespace dawn_native {
MaybeError ValidateFinish(CommandIterator* commands, const PassResourceUsage& usages) const;
EncodingContext mBundleEncodingContext;
Ref<AttachmentState> mAttachmentState;
};
} // namespace dawn_native

View File

@ -28,8 +28,11 @@
namespace dawn_native {
RenderEncoderBase::RenderEncoderBase(DeviceBase* device, EncodingContext* encodingContext)
RenderEncoderBase::RenderEncoderBase(DeviceBase* device,
EncodingContext* encodingContext,
Ref<AttachmentState> attachmentState)
: ProgrammablePassEncoder(device, encodingContext, PassType::Render),
mAttachmentState(std::move(attachmentState)),
mDisableBaseVertex(device->IsToggleEnabled(Toggle::DisableBaseVertex)),
mDisableBaseInstance(device->IsToggleEnabled(Toggle::DisableBaseInstance)) {
}
@ -42,6 +45,16 @@ namespace dawn_native {
mDisableBaseInstance(device->IsToggleEnabled(Toggle::DisableBaseInstance)) {
}
const AttachmentState* RenderEncoderBase::GetAttachmentState() const {
ASSERT(!IsError());
ASSERT(mAttachmentState != nullptr);
return mAttachmentState.Get();
}
Ref<AttachmentState> RenderEncoderBase::AcquireAttachmentState() {
return std::move(mAttachmentState);
}
void RenderEncoderBase::Draw(uint32_t vertexCount,
uint32_t instanceCount,
uint32_t firstVertex,
@ -157,6 +170,12 @@ namespace dawn_native {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
if (IsValidationEnabled()) {
DAWN_TRY(GetDevice()->ValidateObject(pipeline));
if (pipeline->GetAttachmentState() != mAttachmentState.Get()) {
return DAWN_VALIDATION_ERROR(
"Pipeline attachment state is not compatible with render encoder "
"attachment state");
}
}
SetRenderPipelineCmd* cmd =

View File

@ -15,6 +15,7 @@
#ifndef DAWNNATIVE_RENDERENCODERBASE_H_
#define DAWNNATIVE_RENDERENCODERBASE_H_
#include "dawn_native/AttachmentState.h"
#include "dawn_native/Error.h"
#include "dawn_native/ProgrammablePassEncoder.h"
@ -22,7 +23,9 @@ namespace dawn_native {
class RenderEncoderBase : public ProgrammablePassEncoder {
public:
RenderEncoderBase(DeviceBase* device, EncodingContext* encodingContext);
RenderEncoderBase(DeviceBase* device,
EncodingContext* encodingContext,
Ref<AttachmentState> attachmentState);
void Draw(uint32_t vertexCount,
uint32_t instanceCount = 1,
@ -47,11 +50,15 @@ namespace dawn_native {
void SetIndexBufferWithFormat(BufferBase* buffer, wgpu::IndexFormat format, uint64_t offset,
uint64_t size);
const AttachmentState* GetAttachmentState() const;
Ref<AttachmentState> AcquireAttachmentState();
protected:
// Construct an "error" render encoder base.
RenderEncoderBase(DeviceBase* device, EncodingContext* encodingContext, ErrorTag errorTag);
private:
Ref<AttachmentState> mAttachmentState;
const bool mDisableBaseVertex;
const bool mDisableBaseInstance;
};

View File

@ -52,10 +52,11 @@ namespace dawn_native {
CommandEncoder* commandEncoder,
EncodingContext* encodingContext,
PassResourceUsageTracker usageTracker,
Ref<AttachmentState> attachmentState,
QuerySetBase* occlusionQuerySet,
uint32_t renderTargetWidth,
uint32_t renderTargetHeight)
: RenderEncoderBase(device, encodingContext),
: RenderEncoderBase(device, encodingContext, std::move(attachmentState)),
mCommandEncoder(commandEncoder),
mRenderTargetWidth(renderTargetWidth),
mRenderTargetHeight(renderTargetHeight),
@ -198,6 +199,12 @@ namespace dawn_native {
if (IsValidationEnabled()) {
for (uint32_t i = 0; i < count; ++i) {
DAWN_TRY(GetDevice()->ValidateObject(renderBundles[i]));
if (GetAttachmentState() != renderBundles[i]->GetAttachmentState()) {
return DAWN_VALIDATION_ERROR(
"Render bundle attachment state is not compatible with render pass "
"attachment state");
}
}
}

View File

@ -28,6 +28,7 @@ namespace dawn_native {
CommandEncoder* commandEncoder,
EncodingContext* encodingContext,
PassResourceUsageTracker usageTracker,
Ref<AttachmentState> attachmentState,
QuerySetBase* occlusionQuerySet,
uint32_t renderTargetWidth,
uint32_t renderTargetHeight);