Skip validation during command recording when skip_validation is on

This patch factors resource usage tracking so it is separate from
command validation, allowing the bulk of command validation to be
completely skipped.

In DrawCallPerfRun/Vulkan_DynamicPipeline_DynamicBindGroup, disabling
validation cuts roughly 74 nanoseconds (20%) of CPU time, per draw.

In DrawCallPerfRun/Vulkan_DynamicBindGroup, disabling validation
cuts roughly 35 nanoseconds (17%) of CPU time, per draw.

In DrawCallPerfRun/Vulkan_MultipleBindGroups, disabling validation
cuts roughly 45 nanoseconds (14%) of CPU time, per draw.

Bug: dawn:271
Change-Id: I517b85840ba18c6a554b83f34a1d0aef1a8c56a6
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/13520
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn_native/EncodingContext.cpp b/src/dawn_native/EncodingContext.cpp
index ea156a6..b8be069 100644
--- a/src/dawn_native/EncodingContext.cpp
+++ b/src/dawn_native/EncodingContext.cpp
@@ -15,9 +15,11 @@
 #include "dawn_native/EncodingContext.h"
 
 #include "common/Assert.h"
+#include "dawn_native/CommandEncoder.h"
 #include "dawn_native/Commands.h"
 #include "dawn_native/Device.h"
 #include "dawn_native/ErrorData.h"
+#include "dawn_native/RenderBundleEncoder.h"
 
 namespace dawn_native {
 
@@ -32,17 +34,23 @@
     }
 
     CommandIterator EncodingContext::AcquireCommands() {
+        MoveToIterator();
         ASSERT(!mWereCommandsAcquired);
         mWereCommandsAcquired = true;
         return std::move(mIterator);
     }
 
     CommandIterator* EncodingContext::GetIterator() {
+        MoveToIterator();
+        ASSERT(!mWereCommandsAcquired);
+        return &mIterator;
+    }
+
+    void EncodingContext::MoveToIterator() {
         if (!mWasMovedToIterator) {
             mIterator = std::move(mAllocator);
             mWasMovedToIterator = true;
         }
-        return &mIterator;
     }
 
     void EncodingContext::HandleError(wgpu::ErrorType type, const char* message) {
@@ -66,13 +74,25 @@
         mCurrentEncoder = passEncoder;
     }
 
-    void EncodingContext::ExitPass(const ObjectBase* passEncoder) {
+    void EncodingContext::ExitPass(const ObjectBase* passEncoder, PassResourceUsage passUsage) {
         // Assert we're not at the top level.
         ASSERT(mCurrentEncoder != mTopLevelEncoder);
         // Assert the pass encoder is current.
         ASSERT(mCurrentEncoder == passEncoder);
 
         mCurrentEncoder = mTopLevelEncoder;
+        mPassUsages.push_back(std::move(passUsage));
+    }
+
+    const PerPassUsages& EncodingContext::GetPassUsages() const {
+        ASSERT(!mWerePassUsagesAcquired);
+        return mPassUsages;
+    }
+
+    PerPassUsages EncodingContext::AcquirePassUsages() {
+        ASSERT(!mWerePassUsagesAcquired);
+        mWerePassUsagesAcquired = true;
+        return std::move(mPassUsages);
     }
 
     MaybeError EncodingContext::Finish() {