diff --git a/src/dawn_native/ComputePassEncoder.cpp b/src/dawn_native/ComputePassEncoder.cpp index 39af70f7c5..37c1322a0c 100644 --- a/src/dawn_native/ComputePassEncoder.cpp +++ b/src/dawn_native/ComputePassEncoder.cpp @@ -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(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)); } diff --git a/src/dawn_native/ProgrammablePassEncoder.cpp b/src/dawn_native/ProgrammablePassEncoder.cpp index ec29c51bdb..32c7bad75d 100644 --- a/src/dawn_native/ProgrammablePassEncoder.cpp +++ b/src/dawn_native/ProgrammablePassEncoder.cpp @@ -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) { diff --git a/src/dawn_native/ProgrammablePassEncoder.h b/src/dawn_native/ProgrammablePassEncoder.h index f2a2918d9d..9f1c56fa85 100644 --- a/src/dawn_native/ProgrammablePassEncoder.h +++ b/src/dawn_native/ProgrammablePassEncoder.h @@ -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 diff --git a/src/dawn_native/RenderEncoderBase.cpp b/src/dawn_native/RenderEncoderBase.cpp index fac7822cc4..5d029ae043 100644 --- a/src/dawn_native/RenderEncoderBase.cpp +++ b/src/dawn_native/RenderEncoderBase.cpp @@ -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(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(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(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(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; } } diff --git a/src/dawn_native/RenderPassEncoder.cpp b/src/dawn_native/RenderPassEncoder.cpp index 001e348b47..1b13807ff8 100644 --- a/src/dawn_native/RenderPassEncoder.cpp +++ b/src/dawn_native/RenderPassEncoder.cpp @@ -96,7 +96,7 @@ namespace dawn_native { if (mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { allocator->Allocate(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(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(