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>
diff --git a/src/dawn_native/ComputePassEncoder.cpp b/src/dawn_native/ComputePassEncoder.cpp
index 39af70f..37c1322 100644
--- a/src/dawn_native/ComputePassEncoder.cpp
+++ b/src/dawn_native/ComputePassEncoder.cpp
@@ -68,24 +68,28 @@
void ComputePassEncoder::DispatchIndirect(BufferBase* indirectBuffer, uint64_t indirectOffset) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
- DAWN_TRY(GetDevice()->ValidateObject(indirectBuffer));
- DAWN_TRY(ValidateCanUseAs(indirectBuffer, wgpu::BufferUsage::Indirect));
+ if (IsValidationEnabled()) {
+ DAWN_TRY(GetDevice()->ValidateObject(indirectBuffer));
+ DAWN_TRY(ValidateCanUseAs(indirectBuffer, wgpu::BufferUsage::Indirect));
- // Indexed dispatches need a compute-shader based validation to check that the dispatch
- // sizes aren't too big. Disallow them as unsafe until the validation is implemented.
- if (GetDevice()->IsToggleEnabled(Toggle::DisallowUnsafeAPIs)) {
- return DAWN_VALIDATION_ERROR(
- "DispatchIndirect is disallowed because it doesn't validate that the dispatch "
- "size is valid yet.");
- }
+ // Indexed dispatches need a compute-shader based validation to check that the
+ // dispatch sizes aren't too big. Disallow them as unsafe until the validation is
+ // implemented.
+ if (GetDevice()->IsToggleEnabled(Toggle::DisallowUnsafeAPIs)) {
+ return DAWN_VALIDATION_ERROR(
+ "DispatchIndirect is disallowed because it doesn't validate that the "
+ "dispatch "
+ "size is valid yet.");
+ }
- if (indirectOffset % 4 != 0) {
- return DAWN_VALIDATION_ERROR("Indirect offset must be a multiple of 4");
- }
+ if (indirectOffset % 4 != 0) {
+ return DAWN_VALIDATION_ERROR("Indirect offset must be a multiple of 4");
+ }
- if (indirectOffset >= indirectBuffer->GetSize() ||
- indirectOffset + kDispatchIndirectSize > indirectBuffer->GetSize()) {
- return DAWN_VALIDATION_ERROR("Indirect offset out of bounds");
+ if (indirectOffset >= indirectBuffer->GetSize() ||
+ indirectOffset + kDispatchIndirectSize > indirectBuffer->GetSize()) {
+ return DAWN_VALIDATION_ERROR("Indirect offset out of bounds");
+ }
}
DispatchIndirectCmd* dispatch =
@@ -101,7 +105,9 @@
void ComputePassEncoder::SetPipeline(ComputePipelineBase* pipeline) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
- DAWN_TRY(GetDevice()->ValidateObject(pipeline));
+ if (IsValidationEnabled()) {
+ DAWN_TRY(GetDevice()->ValidateObject(pipeline));
+ }
SetComputePipelineCmd* cmd =
allocator->Allocate<SetComputePipelineCmd>(Command::SetComputePipeline);
@@ -113,7 +119,7 @@
void ComputePassEncoder::WriteTimestamp(QuerySetBase* querySet, uint32_t queryIndex) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
- if (GetDevice()->IsValidationEnabled()) {
+ if (IsValidationEnabled()) {
DAWN_TRY(GetDevice()->ValidateObject(querySet));
DAWN_TRY(ValidateTimestampQuery(querySet, queryIndex));
}
diff --git a/src/dawn_native/ProgrammablePassEncoder.cpp b/src/dawn_native/ProgrammablePassEncoder.cpp
index ec29c51..32c7bad 100644
--- a/src/dawn_native/ProgrammablePassEncoder.cpp
+++ b/src/dawn_native/ProgrammablePassEncoder.cpp
@@ -84,14 +84,24 @@
ProgrammablePassEncoder::ProgrammablePassEncoder(DeviceBase* device,
EncodingContext* encodingContext,
PassType passType)
- : ObjectBase(device), mEncodingContext(encodingContext), mUsageTracker(passType) {
+ : ObjectBase(device),
+ mEncodingContext(encodingContext),
+ mUsageTracker(passType),
+ mValidationEnabled(device->IsValidationEnabled()) {
}
ProgrammablePassEncoder::ProgrammablePassEncoder(DeviceBase* device,
EncodingContext* encodingContext,
ErrorTag errorTag,
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) {
@@ -135,7 +145,7 @@
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
BindGroupIndex groupIndex(groupIndexIn);
- if (GetDevice()->IsValidationEnabled()) {
+ if (IsValidationEnabled()) {
DAWN_TRY(GetDevice()->ValidateObject(group));
if (groupIndex >= kMaxBindGroupsTyped) {
diff --git a/src/dawn_native/ProgrammablePassEncoder.h b/src/dawn_native/ProgrammablePassEncoder.h
index f2a2918..9f1c56f 100644
--- a/src/dawn_native/ProgrammablePassEncoder.h
+++ b/src/dawn_native/ProgrammablePassEncoder.h
@@ -44,6 +44,8 @@
const uint32_t* dynamicOffsets = nullptr);
protected:
+ bool IsValidationEnabled() const;
+
// Construct an "error" programmable pass encoder.
ProgrammablePassEncoder(DeviceBase* device,
EncodingContext* encodingContext,
@@ -52,6 +54,9 @@
EncodingContext* mEncodingContext = nullptr;
PassResourceUsageTracker mUsageTracker;
+
+ private:
+ const bool mValidationEnabled;
};
} // namespace dawn_native
diff --git a/src/dawn_native/RenderEncoderBase.cpp b/src/dawn_native/RenderEncoderBase.cpp
index fac7822..5d029ae 100644
--- a/src/dawn_native/RenderEncoderBase.cpp
+++ b/src/dawn_native/RenderEncoderBase.cpp
@@ -47,8 +47,10 @@
uint32_t firstVertex,
uint32_t firstInstance) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
- if (mDisableBaseInstance && firstInstance != 0) {
- return DAWN_VALIDATION_ERROR("Non-zero first instance not supported");
+ if (IsValidationEnabled()) {
+ if (mDisableBaseInstance && firstInstance != 0) {
+ return DAWN_VALIDATION_ERROR("Non-zero first instance not supported");
+ }
}
DrawCmd* draw = allocator->Allocate<DrawCmd>(Command::Draw);
@@ -67,11 +69,13 @@
int32_t baseVertex,
uint32_t firstInstance) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
- if (mDisableBaseInstance && firstInstance != 0) {
- return DAWN_VALIDATION_ERROR("Non-zero first instance not supported");
- }
- if (mDisableBaseVertex && baseVertex != 0) {
- return DAWN_VALIDATION_ERROR("Non-zero base vertex not supported");
+ if (IsValidationEnabled()) {
+ if (mDisableBaseInstance && firstInstance != 0) {
+ return DAWN_VALIDATION_ERROR("Non-zero first instance not supported");
+ }
+ if (mDisableBaseVertex && baseVertex != 0) {
+ return DAWN_VALIDATION_ERROR("Non-zero base vertex not supported");
+ }
}
DrawIndexedCmd* draw = allocator->Allocate<DrawIndexedCmd>(Command::DrawIndexed);
@@ -87,16 +91,18 @@
void RenderEncoderBase::DrawIndirect(BufferBase* indirectBuffer, uint64_t indirectOffset) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
- DAWN_TRY(GetDevice()->ValidateObject(indirectBuffer));
- DAWN_TRY(ValidateCanUseAs(indirectBuffer, wgpu::BufferUsage::Indirect));
+ if (IsValidationEnabled()) {
+ DAWN_TRY(GetDevice()->ValidateObject(indirectBuffer));
+ DAWN_TRY(ValidateCanUseAs(indirectBuffer, wgpu::BufferUsage::Indirect));
- if (indirectOffset % 4 != 0) {
- return DAWN_VALIDATION_ERROR("Indirect offset must be a multiple of 4");
- }
+ if (indirectOffset % 4 != 0) {
+ return DAWN_VALIDATION_ERROR("Indirect offset must be a multiple of 4");
+ }
- if (indirectOffset >= indirectBuffer->GetSize() ||
- indirectOffset + kDrawIndirectSize > indirectBuffer->GetSize()) {
- return DAWN_VALIDATION_ERROR("Indirect offset out of bounds");
+ if (indirectOffset >= indirectBuffer->GetSize() ||
+ indirectOffset + kDrawIndirectSize > indirectBuffer->GetSize()) {
+ return DAWN_VALIDATION_ERROR("Indirect offset out of bounds");
+ }
}
DrawIndirectCmd* cmd = allocator->Allocate<DrawIndirectCmd>(Command::DrawIndirect);
@@ -112,25 +118,28 @@
void RenderEncoderBase::DrawIndexedIndirect(BufferBase* indirectBuffer,
uint64_t indirectOffset) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
- DAWN_TRY(GetDevice()->ValidateObject(indirectBuffer));
- DAWN_TRY(ValidateCanUseAs(indirectBuffer, wgpu::BufferUsage::Indirect));
+ if (IsValidationEnabled()) {
+ DAWN_TRY(GetDevice()->ValidateObject(indirectBuffer));
+ DAWN_TRY(ValidateCanUseAs(indirectBuffer, wgpu::BufferUsage::Indirect));
- // Indexed indirect draws need a compute-shader based validation check that the range of
- // indices is contained inside the index buffer on Metal. Disallow them as unsafe until
- // the validation is implemented.
- if (GetDevice()->IsToggleEnabled(Toggle::DisallowUnsafeAPIs)) {
- return DAWN_VALIDATION_ERROR(
- "DrawIndexedIndirect is disallowed because it doesn't validate that the index "
- "range is valid yet.");
- }
+ // Indexed indirect draws need a compute-shader based validation check that the
+ // range of indices is contained inside the index buffer on Metal. Disallow them as
+ // unsafe until the validation is implemented.
+ if (GetDevice()->IsToggleEnabled(Toggle::DisallowUnsafeAPIs)) {
+ return DAWN_VALIDATION_ERROR(
+ "DrawIndexedIndirect is disallowed because it doesn't validate that the "
+ "index "
+ "range is valid yet.");
+ }
- if (indirectOffset % 4 != 0) {
- return DAWN_VALIDATION_ERROR("Indirect offset must be a multiple of 4");
- }
+ if (indirectOffset % 4 != 0) {
+ return DAWN_VALIDATION_ERROR("Indirect offset must be a multiple of 4");
+ }
- if ((indirectOffset >= indirectBuffer->GetSize() ||
- indirectOffset + kDrawIndexedIndirectSize > indirectBuffer->GetSize())) {
- return DAWN_VALIDATION_ERROR("Indirect offset out of bounds");
+ if ((indirectOffset >= indirectBuffer->GetSize() ||
+ indirectOffset + kDrawIndexedIndirectSize > indirectBuffer->GetSize())) {
+ return DAWN_VALIDATION_ERROR("Indirect offset out of bounds");
+ }
}
DrawIndexedIndirectCmd* cmd =
@@ -146,7 +155,9 @@
void RenderEncoderBase::SetPipeline(RenderPipelineBase* pipeline) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
- DAWN_TRY(GetDevice()->ValidateObject(pipeline));
+ if (IsValidationEnabled()) {
+ DAWN_TRY(GetDevice()->ValidateObject(pipeline));
+ }
SetRenderPipelineCmd* cmd =
allocator->Allocate<SetRenderPipelineCmd>(Command::SetRenderPipeline);
@@ -169,25 +180,31 @@
uint64_t offset,
uint64_t size) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
- DAWN_TRY(GetDevice()->ValidateObject(buffer));
- DAWN_TRY(ValidateCanUseAs(buffer, wgpu::BufferUsage::Index));
+ if (IsValidationEnabled()) {
+ DAWN_TRY(GetDevice()->ValidateObject(buffer));
+ DAWN_TRY(ValidateCanUseAs(buffer, wgpu::BufferUsage::Index));
- DAWN_TRY(ValidateIndexFormat(format));
- if (format == wgpu::IndexFormat::Undefined) {
- return DAWN_VALIDATION_ERROR("Index format must be specified");
- }
+ DAWN_TRY(ValidateIndexFormat(format));
+ if (format == wgpu::IndexFormat::Undefined) {
+ return DAWN_VALIDATION_ERROR("Index format must be specified");
+ }
- uint64_t bufferSize = buffer->GetSize();
- if (offset > bufferSize) {
- return DAWN_VALIDATION_ERROR("Offset larger than the buffer size");
- }
- uint64_t remainingSize = bufferSize - offset;
+ uint64_t bufferSize = buffer->GetSize();
+ if (offset > bufferSize) {
+ return DAWN_VALIDATION_ERROR("Offset larger than the buffer size");
+ }
+ uint64_t remainingSize = bufferSize - offset;
- if (size == 0) {
- size = remainingSize;
+ if (size == 0) {
+ size = remainingSize;
+ } else {
+ if (size > remainingSize) {
+ return DAWN_VALIDATION_ERROR("Size + offset larger than the buffer size");
+ }
+ }
} else {
- if (size > remainingSize) {
- return DAWN_VALIDATION_ERROR("Size + offset larger than the buffer size");
+ if (size == 0) {
+ size = buffer->GetSize() - offset;
}
}
@@ -209,24 +226,30 @@
uint64_t offset,
uint64_t size) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
- DAWN_TRY(GetDevice()->ValidateObject(buffer));
- DAWN_TRY(ValidateCanUseAs(buffer, wgpu::BufferUsage::Vertex));
+ if (IsValidationEnabled()) {
+ DAWN_TRY(GetDevice()->ValidateObject(buffer));
+ DAWN_TRY(ValidateCanUseAs(buffer, wgpu::BufferUsage::Vertex));
- if (slot >= kMaxVertexBuffers) {
- return DAWN_VALIDATION_ERROR("Vertex buffer slot out of bounds");
- }
+ if (slot >= kMaxVertexBuffers) {
+ return DAWN_VALIDATION_ERROR("Vertex buffer slot out of bounds");
+ }
- uint64_t bufferSize = buffer->GetSize();
- if (offset > bufferSize) {
- return DAWN_VALIDATION_ERROR("Offset larger than the buffer size");
- }
- uint64_t remainingSize = bufferSize - offset;
+ uint64_t bufferSize = buffer->GetSize();
+ if (offset > bufferSize) {
+ return DAWN_VALIDATION_ERROR("Offset larger than the buffer size");
+ }
+ uint64_t remainingSize = bufferSize - offset;
- if (size == 0) {
- size = remainingSize;
+ if (size == 0) {
+ size = remainingSize;
+ } else {
+ if (size > remainingSize) {
+ return DAWN_VALIDATION_ERROR("Size + offset larger than the buffer size");
+ }
+ }
} else {
- if (size > remainingSize) {
- return DAWN_VALIDATION_ERROR("Size + offset larger than the buffer size");
+ if (size == 0) {
+ size = buffer->GetSize() - offset;
}
}
diff --git a/src/dawn_native/RenderPassEncoder.cpp b/src/dawn_native/RenderPassEncoder.cpp
index 001e348..1b13807 100644
--- a/src/dawn_native/RenderPassEncoder.cpp
+++ b/src/dawn_native/RenderPassEncoder.cpp
@@ -96,7 +96,7 @@
if (mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
allocator->Allocate<EndRenderPassCmd>(Command::EndRenderPass);
- if (GetDevice()->IsValidationEnabled()) {
+ if (IsValidationEnabled()) {
if (mOcclusionQueryActive) {
return DAWN_VALIDATION_ERROR(
"The occlusion query must be ended before endPass.");
@@ -135,24 +135,26 @@
float minDepth,
float maxDepth) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
- if ((isnan(x) || isnan(y) || isnan(width) || isnan(height) || isnan(minDepth) ||
- isnan(maxDepth))) {
- return DAWN_VALIDATION_ERROR("NaN is not allowed.");
- }
+ if (IsValidationEnabled()) {
+ if ((isnan(x) || isnan(y) || isnan(width) || isnan(height) || isnan(minDepth) ||
+ isnan(maxDepth))) {
+ return DAWN_VALIDATION_ERROR("NaN is not allowed.");
+ }
- if (x < 0 || y < 0 || width < 0 || height < 0) {
- return DAWN_VALIDATION_ERROR("X, Y, width and height must be non-negative.");
- }
+ if (x < 0 || y < 0 || width < 0 || height < 0) {
+ return DAWN_VALIDATION_ERROR("X, Y, width and height must be non-negative.");
+ }
- if (x + width > mRenderTargetWidth || y + height > mRenderTargetHeight) {
- return DAWN_VALIDATION_ERROR(
- "The viewport must be contained in the render targets");
- }
+ if (x + width > mRenderTargetWidth || y + height > mRenderTargetHeight) {
+ return DAWN_VALIDATION_ERROR(
+ "The viewport must be contained in the render targets");
+ }
- // Check for depths being in [0, 1] and min <= max in 3 checks instead of 5.
- if (minDepth < 0 || minDepth > maxDepth || maxDepth > 1) {
- return DAWN_VALIDATION_ERROR(
- "minDepth and maxDepth must be in [0, 1] and minDepth <= maxDepth.");
+ // Check for depths being in [0, 1] and min <= max in 3 checks instead of 5.
+ if (minDepth < 0 || minDepth > maxDepth || maxDepth > 1) {
+ return DAWN_VALIDATION_ERROR(
+ "minDepth and maxDepth must be in [0, 1] and minDepth <= maxDepth.");
+ }
}
SetViewportCmd* cmd = allocator->Allocate<SetViewportCmd>(Command::SetViewport);
@@ -172,10 +174,12 @@
uint32_t width,
uint32_t height) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
- if (width > mRenderTargetWidth || height > mRenderTargetHeight ||
- x > mRenderTargetWidth - width || y > mRenderTargetHeight - height) {
- return DAWN_VALIDATION_ERROR(
- "The scissor rect must be contained in the render targets");
+ if (IsValidationEnabled()) {
+ if (width > mRenderTargetWidth || height > mRenderTargetHeight ||
+ x > mRenderTargetWidth - width || y > mRenderTargetHeight - height) {
+ return DAWN_VALIDATION_ERROR(
+ "The scissor rect must be contained in the render targets");
+ }
}
SetScissorRectCmd* cmd =
@@ -191,8 +195,10 @@
void RenderPassEncoder::ExecuteBundles(uint32_t count, RenderBundleBase* const* renderBundles) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
- for (uint32_t i = 0; i < count; ++i) {
- DAWN_TRY(GetDevice()->ValidateObject(renderBundles[i]));
+ if (IsValidationEnabled()) {
+ for (uint32_t i = 0; i < count; ++i) {
+ DAWN_TRY(GetDevice()->ValidateObject(renderBundles[i]));
+ }
}
ExecuteBundlesCmd* cmd =
@@ -219,7 +225,7 @@
void RenderPassEncoder::BeginOcclusionQuery(uint32_t queryIndex) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
- if (GetDevice()->IsValidationEnabled()) {
+ if (IsValidationEnabled()) {
if (mOcclusionQuerySet.Get() == nullptr) {
return DAWN_VALIDATION_ERROR(
"The occlusionQuerySet in RenderPassDescriptor must be set.");
@@ -258,7 +264,7 @@
void RenderPassEncoder::EndOcclusionQuery() {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
- if (GetDevice()->IsValidationEnabled()) {
+ if (IsValidationEnabled()) {
if (!mOcclusionQueryActive) {
return DAWN_VALIDATION_ERROR(
"EndOcclusionQuery cannot be called without corresponding "
@@ -280,7 +286,7 @@
void RenderPassEncoder::WriteTimestamp(QuerySetBase* querySet, uint32_t queryIndex) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
- if (GetDevice()->IsValidationEnabled()) {
+ if (IsValidationEnabled()) {
DAWN_TRY(GetDevice()->ValidateObject(querySet));
DAWN_TRY(ValidateTimestampQuery(querySet, queryIndex));
DAWN_TRY(