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(