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,24 +68,28 @@ namespace dawn_native {
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 @@ namespace dawn_native {
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 @@ namespace dawn_native {
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));
}

View File

@ -84,14 +84,24 @@ namespace dawn_native {
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 @@ namespace dawn_native {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
BindGroupIndex groupIndex(groupIndexIn);
if (GetDevice()->IsValidationEnabled()) {
if (IsValidationEnabled()) {
DAWN_TRY(GetDevice()->ValidateObject(group));
if (groupIndex >= kMaxBindGroupsTyped) {

View File

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

View File

@ -47,8 +47,10 @@ namespace dawn_native {
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 @@ namespace dawn_native {
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 @@ namespace dawn_native {
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 @@ namespace dawn_native {
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 @@ namespace dawn_native {
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 @@ namespace dawn_native {
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 @@ namespace dawn_native {
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;
}
}

View File

@ -96,7 +96,7 @@ namespace dawn_native {
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 @@ namespace dawn_native {
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 @@ namespace dawn_native {
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 @@ namespace dawn_native {
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 @@ namespace dawn_native {
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 @@ namespace dawn_native {
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 @@ namespace dawn_native {
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(