D3D12: Track internal buffer usage in D3D12_RESOURCE_STATES

This patch tracks all the internal buffer usage in D3D12_RESOURCE_STATES
instead of wgpu::BufferUsage so that we don't need to specially handle
the case that we translate two wgpu::BufferUsages into one
D3D12_RESOURCE_STATES.

Fixed: dawn:1024
Change-Id: I0a5222e85b8d3ec7d5f1f814d78feeab920147ee
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/139508
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
diff --git a/src/dawn/native/d3d12/BufferD3D12.cpp b/src/dawn/native/d3d12/BufferD3D12.cpp
index 82edbde..5f9f93a 100644
--- a/src/dawn/native/d3d12/BufferD3D12.cpp
+++ b/src/dawn/native/d3d12/BufferD3D12.cpp
@@ -135,27 +135,32 @@
     resourceDescriptor.Flags = D3D12ResourceFlags(GetUsage() | wgpu::BufferUsage::CopyDst);
 
     auto heapType = D3D12HeapType(GetUsage());
-    auto bufferUsage = D3D12_RESOURCE_STATE_COMMON;
+    mLastState = D3D12_RESOURCE_STATE_COMMON;
 
-    // D3D12 requires buffers on the READBACK heap to have the D3D12_RESOURCE_STATE_COPY_DEST
-    // state
-    if (heapType == D3D12_HEAP_TYPE_READBACK) {
-        bufferUsage |= D3D12_RESOURCE_STATE_COPY_DEST;
-        mFixedResourceState = true;
-        mLastUsage = wgpu::BufferUsage::CopyDst;
-    }
-
-    // D3D12 requires buffers on the UPLOAD heap to have the D3D12_RESOURCE_STATE_GENERIC_READ
-    // state
-    if (heapType == D3D12_HEAP_TYPE_UPLOAD) {
-        bufferUsage |= D3D12_RESOURCE_STATE_GENERIC_READ;
-        mFixedResourceState = true;
-        mLastUsage = wgpu::BufferUsage::CopySrc;
+    switch (heapType) {
+        // D3D12 requires buffers on the READBACK heap to have the D3D12_RESOURCE_STATE_COPY_DEST
+        // state
+        case D3D12_HEAP_TYPE_READBACK: {
+            mLastState |= D3D12_RESOURCE_STATE_COPY_DEST;
+            mFixedResourceState = true;
+            break;
+        }
+        // D3D12 requires buffers on the UPLOAD heap to have the D3D12_RESOURCE_STATE_GENERIC_READ
+        // state
+        case D3D12_HEAP_TYPE_UPLOAD: {
+            mLastState |= D3D12_RESOURCE_STATE_GENERIC_READ;
+            mFixedResourceState = true;
+            break;
+        }
+        case D3D12_HEAP_TYPE_DEFAULT:
+        case D3D12_HEAP_TYPE_CUSTOM:
+        default:
+            break;
     }
 
     DAWN_TRY_ASSIGN(
         mResourceAllocation,
-        ToBackend(GetDevice())->AllocateMemory(heapType, resourceDescriptor, bufferUsage, 0));
+        ToBackend(GetDevice())->AllocateMemory(heapType, resourceDescriptor, mLastState, 0));
 
     SetLabelImpl();
 
@@ -207,12 +212,15 @@
 
     // Resources in upload and readback heaps must be kept in the COPY_SOURCE/DEST state
     if (mFixedResourceState) {
-        ASSERT(mLastUsage == newUsage);
+        ASSERT((mLastState == D3D12_RESOURCE_STATE_COPY_DEST &&
+                newUsage == wgpu::BufferUsage::CopyDst) ||
+               (mLastState == D3D12_RESOURCE_STATE_GENERIC_READ &&
+                newUsage == wgpu::BufferUsage::CopySrc));
         return false;
     }
 
-    D3D12_RESOURCE_STATES lastState = D3D12BufferUsage(mLastUsage);
     D3D12_RESOURCE_STATES newState = D3D12BufferUsage(newUsage);
+    D3D12_RESOURCE_STATES lastState = mLastState;
 
     // If the transition is from-UAV-to-UAV, then a UAV barrier is needed.
     // If one of the usages isn't UAV, then other barriers are used.
@@ -224,16 +232,16 @@
         barrier->Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
         barrier->UAV.pResource = GetD3D12Resource();
 
-        mLastUsage = newUsage;
+        mLastState = newState;
         return true;
     }
 
     // We can skip transitions to already current usages.
-    if (IsSubset(newUsage, mLastUsage)) {
+    if (IsSubset(newState, mLastState)) {
         return false;
     }
 
-    mLastUsage = newUsage;
+    mLastState = newState;
 
     // The COMMON state represents a state where no write operations can be pending, which makes
     // it possible to transition to and from some states without synchronizaton (i.e. without an
@@ -264,13 +272,6 @@
         return false;
     }
 
-    // TODO(crbug.com/dawn/1024): The before and after states must be different. Remove this
-    // workaround and use D3D12 states instead of WebGPU usages to manage the tracking of
-    // barrier state.
-    if (lastState == newState) {
-        return false;
-    }
-
     barrier->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
     barrier->Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
     barrier->Transition.pResource = GetD3D12Resource();
diff --git a/src/dawn/native/d3d12/BufferD3D12.h b/src/dawn/native/d3d12/BufferD3D12.h
index 4913fbd..2063b8d 100644
--- a/src/dawn/native/d3d12/BufferD3D12.h
+++ b/src/dawn/native/d3d12/BufferD3D12.h
@@ -75,7 +75,7 @@
 
     ResourceHeapAllocation mResourceAllocation;
     bool mFixedResourceState = false;
-    wgpu::BufferUsage mLastUsage = wgpu::BufferUsage::None;
+    D3D12_RESOURCE_STATES mLastState = D3D12_RESOURCE_STATE_COMMON;
     ExecutionSerial mLastUsedSerial = std::numeric_limits<ExecutionSerial>::max();
 
     D3D12_RANGE mWrittenMappedRange = {0, 0};