dawn_native: Skip more validation if it is disabled.

Also cache the boolean for IsValidationEnabled in the
ProgrammablePassEncoder.

Bug: dawn:635
Change-Id: I5f095d003d28b84eacbc488a7f8f3c346c646187
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/38521
Commit-Queue: Austin Eng <enga@chromium.org>
Auto-Submit: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Stephen White <senorblanco@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
Corentin Wallez 2021-01-23 00:07:46 +00:00 committed by Commit Bot service account
parent 0ac48eb9a4
commit f1f8394de0
5 changed files with 156 additions and 106 deletions

View File

@ -68,14 +68,17 @@ namespace dawn_native {
void ComputePassEncoder::DispatchIndirect(BufferBase* indirectBuffer, uint64_t indirectOffset) { void ComputePassEncoder::DispatchIndirect(BufferBase* indirectBuffer, uint64_t indirectOffset) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
if (IsValidationEnabled()) {
DAWN_TRY(GetDevice()->ValidateObject(indirectBuffer)); DAWN_TRY(GetDevice()->ValidateObject(indirectBuffer));
DAWN_TRY(ValidateCanUseAs(indirectBuffer, wgpu::BufferUsage::Indirect)); DAWN_TRY(ValidateCanUseAs(indirectBuffer, wgpu::BufferUsage::Indirect));
// Indexed dispatches need a compute-shader based validation to check that the dispatch // Indexed dispatches need a compute-shader based validation to check that the
// sizes aren't too big. Disallow them as unsafe until the validation is implemented. // dispatch sizes aren't too big. Disallow them as unsafe until the validation is
// implemented.
if (GetDevice()->IsToggleEnabled(Toggle::DisallowUnsafeAPIs)) { if (GetDevice()->IsToggleEnabled(Toggle::DisallowUnsafeAPIs)) {
return DAWN_VALIDATION_ERROR( return DAWN_VALIDATION_ERROR(
"DispatchIndirect is disallowed because it doesn't validate that the dispatch " "DispatchIndirect is disallowed because it doesn't validate that the "
"dispatch "
"size is valid yet."); "size is valid yet.");
} }
@ -87,6 +90,7 @@ namespace dawn_native {
indirectOffset + kDispatchIndirectSize > indirectBuffer->GetSize()) { indirectOffset + kDispatchIndirectSize > indirectBuffer->GetSize()) {
return DAWN_VALIDATION_ERROR("Indirect offset out of bounds"); return DAWN_VALIDATION_ERROR("Indirect offset out of bounds");
} }
}
DispatchIndirectCmd* dispatch = DispatchIndirectCmd* dispatch =
allocator->Allocate<DispatchIndirectCmd>(Command::DispatchIndirect); allocator->Allocate<DispatchIndirectCmd>(Command::DispatchIndirect);
@ -101,7 +105,9 @@ namespace dawn_native {
void ComputePassEncoder::SetPipeline(ComputePipelineBase* pipeline) { void ComputePassEncoder::SetPipeline(ComputePipelineBase* pipeline) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
if (IsValidationEnabled()) {
DAWN_TRY(GetDevice()->ValidateObject(pipeline)); DAWN_TRY(GetDevice()->ValidateObject(pipeline));
}
SetComputePipelineCmd* cmd = SetComputePipelineCmd* cmd =
allocator->Allocate<SetComputePipelineCmd>(Command::SetComputePipeline); allocator->Allocate<SetComputePipelineCmd>(Command::SetComputePipeline);
@ -113,7 +119,7 @@ namespace dawn_native {
void ComputePassEncoder::WriteTimestamp(QuerySetBase* querySet, uint32_t queryIndex) { void ComputePassEncoder::WriteTimestamp(QuerySetBase* querySet, uint32_t queryIndex) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
if (GetDevice()->IsValidationEnabled()) { if (IsValidationEnabled()) {
DAWN_TRY(GetDevice()->ValidateObject(querySet)); DAWN_TRY(GetDevice()->ValidateObject(querySet));
DAWN_TRY(ValidateTimestampQuery(querySet, queryIndex)); DAWN_TRY(ValidateTimestampQuery(querySet, queryIndex));
} }

View File

@ -84,14 +84,24 @@ namespace dawn_native {
ProgrammablePassEncoder::ProgrammablePassEncoder(DeviceBase* device, ProgrammablePassEncoder::ProgrammablePassEncoder(DeviceBase* device,
EncodingContext* encodingContext, EncodingContext* encodingContext,
PassType passType) PassType passType)
: ObjectBase(device), mEncodingContext(encodingContext), mUsageTracker(passType) { : ObjectBase(device),
mEncodingContext(encodingContext),
mUsageTracker(passType),
mValidationEnabled(device->IsValidationEnabled()) {
} }
ProgrammablePassEncoder::ProgrammablePassEncoder(DeviceBase* device, ProgrammablePassEncoder::ProgrammablePassEncoder(DeviceBase* device,
EncodingContext* encodingContext, EncodingContext* encodingContext,
ErrorTag errorTag, ErrorTag errorTag,
PassType passType) PassType passType)
: ObjectBase(device, errorTag), mEncodingContext(encodingContext), mUsageTracker(passType) { : ObjectBase(device, errorTag),
mEncodingContext(encodingContext),
mUsageTracker(passType),
mValidationEnabled(false) {
}
bool ProgrammablePassEncoder::IsValidationEnabled() const {
return mValidationEnabled;
} }
void ProgrammablePassEncoder::InsertDebugMarker(const char* groupLabel) { void ProgrammablePassEncoder::InsertDebugMarker(const char* groupLabel) {
@ -135,7 +145,7 @@ namespace dawn_native {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
BindGroupIndex groupIndex(groupIndexIn); BindGroupIndex groupIndex(groupIndexIn);
if (GetDevice()->IsValidationEnabled()) { if (IsValidationEnabled()) {
DAWN_TRY(GetDevice()->ValidateObject(group)); DAWN_TRY(GetDevice()->ValidateObject(group));
if (groupIndex >= kMaxBindGroupsTyped) { if (groupIndex >= kMaxBindGroupsTyped) {

View File

@ -44,6 +44,8 @@ namespace dawn_native {
const uint32_t* dynamicOffsets = nullptr); const uint32_t* dynamicOffsets = nullptr);
protected: protected:
bool IsValidationEnabled() const;
// Construct an "error" programmable pass encoder. // Construct an "error" programmable pass encoder.
ProgrammablePassEncoder(DeviceBase* device, ProgrammablePassEncoder(DeviceBase* device,
EncodingContext* encodingContext, EncodingContext* encodingContext,
@ -52,6 +54,9 @@ namespace dawn_native {
EncodingContext* mEncodingContext = nullptr; EncodingContext* mEncodingContext = nullptr;
PassResourceUsageTracker mUsageTracker; PassResourceUsageTracker mUsageTracker;
private:
const bool mValidationEnabled;
}; };
} // namespace dawn_native } // namespace dawn_native

View File

@ -47,9 +47,11 @@ namespace dawn_native {
uint32_t firstVertex, uint32_t firstVertex,
uint32_t firstInstance) { uint32_t firstInstance) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
if (IsValidationEnabled()) {
if (mDisableBaseInstance && firstInstance != 0) { if (mDisableBaseInstance && firstInstance != 0) {
return DAWN_VALIDATION_ERROR("Non-zero first instance not supported"); return DAWN_VALIDATION_ERROR("Non-zero first instance not supported");
} }
}
DrawCmd* draw = allocator->Allocate<DrawCmd>(Command::Draw); DrawCmd* draw = allocator->Allocate<DrawCmd>(Command::Draw);
draw->vertexCount = vertexCount; draw->vertexCount = vertexCount;
@ -67,12 +69,14 @@ namespace dawn_native {
int32_t baseVertex, int32_t baseVertex,
uint32_t firstInstance) { uint32_t firstInstance) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
if (IsValidationEnabled()) {
if (mDisableBaseInstance && firstInstance != 0) { if (mDisableBaseInstance && firstInstance != 0) {
return DAWN_VALIDATION_ERROR("Non-zero first instance not supported"); return DAWN_VALIDATION_ERROR("Non-zero first instance not supported");
} }
if (mDisableBaseVertex && baseVertex != 0) { if (mDisableBaseVertex && baseVertex != 0) {
return DAWN_VALIDATION_ERROR("Non-zero base vertex not supported"); return DAWN_VALIDATION_ERROR("Non-zero base vertex not supported");
} }
}
DrawIndexedCmd* draw = allocator->Allocate<DrawIndexedCmd>(Command::DrawIndexed); DrawIndexedCmd* draw = allocator->Allocate<DrawIndexedCmd>(Command::DrawIndexed);
draw->indexCount = indexCount; draw->indexCount = indexCount;
@ -87,6 +91,7 @@ namespace dawn_native {
void RenderEncoderBase::DrawIndirect(BufferBase* indirectBuffer, uint64_t indirectOffset) { void RenderEncoderBase::DrawIndirect(BufferBase* indirectBuffer, uint64_t indirectOffset) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
if (IsValidationEnabled()) {
DAWN_TRY(GetDevice()->ValidateObject(indirectBuffer)); DAWN_TRY(GetDevice()->ValidateObject(indirectBuffer));
DAWN_TRY(ValidateCanUseAs(indirectBuffer, wgpu::BufferUsage::Indirect)); DAWN_TRY(ValidateCanUseAs(indirectBuffer, wgpu::BufferUsage::Indirect));
@ -98,6 +103,7 @@ namespace dawn_native {
indirectOffset + kDrawIndirectSize > indirectBuffer->GetSize()) { indirectOffset + kDrawIndirectSize > indirectBuffer->GetSize()) {
return DAWN_VALIDATION_ERROR("Indirect offset out of bounds"); return DAWN_VALIDATION_ERROR("Indirect offset out of bounds");
} }
}
DrawIndirectCmd* cmd = allocator->Allocate<DrawIndirectCmd>(Command::DrawIndirect); DrawIndirectCmd* cmd = allocator->Allocate<DrawIndirectCmd>(Command::DrawIndirect);
cmd->indirectBuffer = indirectBuffer; cmd->indirectBuffer = indirectBuffer;
@ -112,15 +118,17 @@ namespace dawn_native {
void RenderEncoderBase::DrawIndexedIndirect(BufferBase* indirectBuffer, void RenderEncoderBase::DrawIndexedIndirect(BufferBase* indirectBuffer,
uint64_t indirectOffset) { uint64_t indirectOffset) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
if (IsValidationEnabled()) {
DAWN_TRY(GetDevice()->ValidateObject(indirectBuffer)); DAWN_TRY(GetDevice()->ValidateObject(indirectBuffer));
DAWN_TRY(ValidateCanUseAs(indirectBuffer, wgpu::BufferUsage::Indirect)); DAWN_TRY(ValidateCanUseAs(indirectBuffer, wgpu::BufferUsage::Indirect));
// Indexed indirect draws need a compute-shader based validation check that the range of // Indexed indirect draws need a compute-shader based validation check that the
// indices is contained inside the index buffer on Metal. Disallow them as unsafe until // range of indices is contained inside the index buffer on Metal. Disallow them as
// the validation is implemented. // unsafe until the validation is implemented.
if (GetDevice()->IsToggleEnabled(Toggle::DisallowUnsafeAPIs)) { if (GetDevice()->IsToggleEnabled(Toggle::DisallowUnsafeAPIs)) {
return DAWN_VALIDATION_ERROR( return DAWN_VALIDATION_ERROR(
"DrawIndexedIndirect is disallowed because it doesn't validate that the index " "DrawIndexedIndirect is disallowed because it doesn't validate that the "
"index "
"range is valid yet."); "range is valid yet.");
} }
@ -132,6 +140,7 @@ namespace dawn_native {
indirectOffset + kDrawIndexedIndirectSize > indirectBuffer->GetSize())) { indirectOffset + kDrawIndexedIndirectSize > indirectBuffer->GetSize())) {
return DAWN_VALIDATION_ERROR("Indirect offset out of bounds"); return DAWN_VALIDATION_ERROR("Indirect offset out of bounds");
} }
}
DrawIndexedIndirectCmd* cmd = DrawIndexedIndirectCmd* cmd =
allocator->Allocate<DrawIndexedIndirectCmd>(Command::DrawIndexedIndirect); allocator->Allocate<DrawIndexedIndirectCmd>(Command::DrawIndexedIndirect);
@ -146,7 +155,9 @@ namespace dawn_native {
void RenderEncoderBase::SetPipeline(RenderPipelineBase* pipeline) { void RenderEncoderBase::SetPipeline(RenderPipelineBase* pipeline) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
if (IsValidationEnabled()) {
DAWN_TRY(GetDevice()->ValidateObject(pipeline)); DAWN_TRY(GetDevice()->ValidateObject(pipeline));
}
SetRenderPipelineCmd* cmd = SetRenderPipelineCmd* cmd =
allocator->Allocate<SetRenderPipelineCmd>(Command::SetRenderPipeline); allocator->Allocate<SetRenderPipelineCmd>(Command::SetRenderPipeline);
@ -169,6 +180,7 @@ namespace dawn_native {
uint64_t offset, uint64_t offset,
uint64_t size) { uint64_t size) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
if (IsValidationEnabled()) {
DAWN_TRY(GetDevice()->ValidateObject(buffer)); DAWN_TRY(GetDevice()->ValidateObject(buffer));
DAWN_TRY(ValidateCanUseAs(buffer, wgpu::BufferUsage::Index)); DAWN_TRY(ValidateCanUseAs(buffer, wgpu::BufferUsage::Index));
@ -190,6 +202,11 @@ namespace dawn_native {
return DAWN_VALIDATION_ERROR("Size + offset larger than the buffer size"); return DAWN_VALIDATION_ERROR("Size + offset larger than the buffer size");
} }
} }
} else {
if (size == 0) {
size = buffer->GetSize() - offset;
}
}
SetIndexBufferCmd* cmd = SetIndexBufferCmd* cmd =
allocator->Allocate<SetIndexBufferCmd>(Command::SetIndexBuffer); allocator->Allocate<SetIndexBufferCmd>(Command::SetIndexBuffer);
@ -209,6 +226,7 @@ namespace dawn_native {
uint64_t offset, uint64_t offset,
uint64_t size) { uint64_t size) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
if (IsValidationEnabled()) {
DAWN_TRY(GetDevice()->ValidateObject(buffer)); DAWN_TRY(GetDevice()->ValidateObject(buffer));
DAWN_TRY(ValidateCanUseAs(buffer, wgpu::BufferUsage::Vertex)); DAWN_TRY(ValidateCanUseAs(buffer, wgpu::BufferUsage::Vertex));
@ -229,6 +247,11 @@ namespace dawn_native {
return DAWN_VALIDATION_ERROR("Size + offset larger than the buffer size"); return DAWN_VALIDATION_ERROR("Size + offset larger than the buffer size");
} }
} }
} else {
if (size == 0) {
size = buffer->GetSize() - offset;
}
}
SetVertexBufferCmd* cmd = SetVertexBufferCmd* cmd =
allocator->Allocate<SetVertexBufferCmd>(Command::SetVertexBuffer); allocator->Allocate<SetVertexBufferCmd>(Command::SetVertexBuffer);

View File

@ -96,7 +96,7 @@ namespace dawn_native {
if (mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { if (mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
allocator->Allocate<EndRenderPassCmd>(Command::EndRenderPass); allocator->Allocate<EndRenderPassCmd>(Command::EndRenderPass);
if (GetDevice()->IsValidationEnabled()) { if (IsValidationEnabled()) {
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.");
@ -135,6 +135,7 @@ namespace dawn_native {
float minDepth, float minDepth,
float maxDepth) { float maxDepth) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
if (IsValidationEnabled()) {
if ((isnan(x) || isnan(y) || isnan(width) || isnan(height) || isnan(minDepth) || if ((isnan(x) || isnan(y) || isnan(width) || isnan(height) || isnan(minDepth) ||
isnan(maxDepth))) { isnan(maxDepth))) {
return DAWN_VALIDATION_ERROR("NaN is not allowed."); return DAWN_VALIDATION_ERROR("NaN is not allowed.");
@ -154,6 +155,7 @@ namespace dawn_native {
return DAWN_VALIDATION_ERROR( return DAWN_VALIDATION_ERROR(
"minDepth and maxDepth must be in [0, 1] and minDepth <= maxDepth."); "minDepth and maxDepth must be in [0, 1] and minDepth <= maxDepth.");
} }
}
SetViewportCmd* cmd = allocator->Allocate<SetViewportCmd>(Command::SetViewport); SetViewportCmd* cmd = allocator->Allocate<SetViewportCmd>(Command::SetViewport);
cmd->x = x; cmd->x = x;
@ -172,11 +174,13 @@ namespace dawn_native {
uint32_t width, uint32_t width,
uint32_t height) { uint32_t height) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
if (IsValidationEnabled()) {
if (width > mRenderTargetWidth || height > mRenderTargetHeight || if (width > mRenderTargetWidth || height > mRenderTargetHeight ||
x > mRenderTargetWidth - width || y > mRenderTargetHeight - height) { x > mRenderTargetWidth - width || y > mRenderTargetHeight - height) {
return DAWN_VALIDATION_ERROR( return DAWN_VALIDATION_ERROR(
"The scissor rect must be contained in the render targets"); "The scissor rect must be contained in the render targets");
} }
}
SetScissorRectCmd* cmd = SetScissorRectCmd* cmd =
allocator->Allocate<SetScissorRectCmd>(Command::SetScissorRect); allocator->Allocate<SetScissorRectCmd>(Command::SetScissorRect);
@ -191,9 +195,11 @@ namespace dawn_native {
void RenderPassEncoder::ExecuteBundles(uint32_t count, RenderBundleBase* const* renderBundles) { void RenderPassEncoder::ExecuteBundles(uint32_t count, RenderBundleBase* const* renderBundles) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
if (IsValidationEnabled()) {
for (uint32_t i = 0; i < count; ++i) { for (uint32_t i = 0; i < count; ++i) {
DAWN_TRY(GetDevice()->ValidateObject(renderBundles[i])); DAWN_TRY(GetDevice()->ValidateObject(renderBundles[i]));
} }
}
ExecuteBundlesCmd* cmd = ExecuteBundlesCmd* cmd =
allocator->Allocate<ExecuteBundlesCmd>(Command::ExecuteBundles); allocator->Allocate<ExecuteBundlesCmd>(Command::ExecuteBundles);
@ -219,7 +225,7 @@ namespace dawn_native {
void RenderPassEncoder::BeginOcclusionQuery(uint32_t queryIndex) { void RenderPassEncoder::BeginOcclusionQuery(uint32_t queryIndex) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
if (GetDevice()->IsValidationEnabled()) { if (IsValidationEnabled()) {
if (mOcclusionQuerySet.Get() == nullptr) { if (mOcclusionQuerySet.Get() == nullptr) {
return DAWN_VALIDATION_ERROR( return DAWN_VALIDATION_ERROR(
"The occlusionQuerySet in RenderPassDescriptor must be set."); "The occlusionQuerySet in RenderPassDescriptor must be set.");
@ -258,7 +264,7 @@ namespace dawn_native {
void RenderPassEncoder::EndOcclusionQuery() { void RenderPassEncoder::EndOcclusionQuery() {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
if (GetDevice()->IsValidationEnabled()) { if (IsValidationEnabled()) {
if (!mOcclusionQueryActive) { if (!mOcclusionQueryActive) {
return DAWN_VALIDATION_ERROR( return DAWN_VALIDATION_ERROR(
"EndOcclusionQuery cannot be called without corresponding " "EndOcclusionQuery cannot be called without corresponding "
@ -280,7 +286,7 @@ namespace dawn_native {
void RenderPassEncoder::WriteTimestamp(QuerySetBase* querySet, uint32_t queryIndex) { void RenderPassEncoder::WriteTimestamp(QuerySetBase* querySet, uint32_t queryIndex) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
if (GetDevice()->IsValidationEnabled()) { if (IsValidationEnabled()) {
DAWN_TRY(GetDevice()->ValidateObject(querySet)); DAWN_TRY(GetDevice()->ValidateObject(querySet));
DAWN_TRY(ValidateTimestampQuery(querySet, queryIndex)); DAWN_TRY(ValidateTimestampQuery(querySet, queryIndex));
DAWN_TRY( DAWN_TRY(