Direct3D: Be sure to set correct heaps for current descriptor tables.

When binding descriptor tables, their associated heaps need to be bound
as well. Previously we would bind those heaps when allocating from them.
However, if we re-use a descriptor table later, its heap may no longer
be bound. So we need to be sure to bind heaps for the current set.

To avoid unnecessary refs, rather than store a
sk_sp<GrD3DDescriptorTableManager::Heap> in each descriptor table, we
only store its ID3D12DescriptorHeap pointer. The Heap only needs to be
added to the command list once, when it is first used to allocate for
the current submit.

Bug: skia:12359
Change-Id: I70018368e4f08bf7757969b9e878b0ff42059486
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/448836
Commit-Queue: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
diff --git a/src/gpu/d3d/GrD3DCommandList.cpp b/src/gpu/d3d/GrD3DCommandList.cpp
index 0b51b59..7e31b87 100644
--- a/src/gpu/d3d/GrD3DCommandList.cpp
+++ b/src/gpu/d3d/GrD3DCommandList.cpp
@@ -569,9 +569,9 @@
     }
 }
 
-void GrD3DDirectCommandList::setDescriptorHeaps(sk_sp<GrRecycledResource> srvCrvHeapResource,
-                                                ID3D12DescriptorHeap* srvCrvDescriptorHeap,
-                                                sk_sp<GrRecycledResource> samplerHeapResource,
+// We don't need to add these resources to the command list.
+// They're added when we first allocate from a heap in a given submit.
+void GrD3DDirectCommandList::setDescriptorHeaps(ID3D12DescriptorHeap* srvCrvDescriptorHeap,
                                                 ID3D12DescriptorHeap* samplerDescriptorHeap) {
     if (srvCrvDescriptorHeap != fCurrentSRVCRVDescriptorHeap ||
         samplerDescriptorHeap != fCurrentSamplerDescriptorHeap) {
@@ -581,8 +581,6 @@
         };
 
         fCommandList->SetDescriptorHeaps(2, heaps);
-        this->addRecycledResource(std::move(srvCrvHeapResource));
-        this->addRecycledResource(std::move(samplerHeapResource));
         fCurrentSRVCRVDescriptorHeap = srvCrvDescriptorHeap;
         fCurrentSamplerDescriptorHeap = samplerDescriptorHeap;
     }
diff --git a/src/gpu/d3d/GrD3DCommandList.h b/src/gpu/d3d/GrD3DCommandList.h
index 715c52d..3f08f61 100644
--- a/src/gpu/d3d/GrD3DCommandList.h
+++ b/src/gpu/d3d/GrD3DCommandList.h
@@ -100,6 +100,12 @@
         fTrackedGpuBuffers.push_back(std::move(buffer));
     }
 
+    // Add ref-counted resource that will be tracked and released when this command buffer finishes
+    // execution. When it is released, it will signal that the resource can be recycled for reuse.
+    void addRecycledResource(sk_sp<GrRecycledResource> resource) {
+        fTrackedRecycledResources.push_back(std::move(resource));
+    }
+
     void releaseResources();
 
     bool hasWork() const { return fHasWork; }
@@ -120,12 +126,6 @@
         fTrackedResources.push_back(std::move(resource));
     }
 
-    // Add ref-counted resource that will be tracked and released when this command buffer finishes
-    // execution. When it is released, it will signal that the resource can be recycled for reuse.
-    void addRecycledResource(sk_sp<GrRecycledResource> resource) {
-        fTrackedRecycledResources.push_back(std::move(resource));
-    }
-
     void addingWork();
     virtual void onReset() {}
 
@@ -201,9 +201,7 @@
                                           D3D12_GPU_VIRTUAL_ADDRESS bufferLocation);
     void setComputeRootDescriptorTable(unsigned int rootParameterIndex,
                                        D3D12_GPU_DESCRIPTOR_HANDLE bufferLocation);
-    void setDescriptorHeaps(sk_sp<GrRecycledResource> srvCrvHeapResource,
-                            ID3D12DescriptorHeap* srvDescriptorHeap,
-                            sk_sp<GrRecycledResource> samplerHeapResource,
+    void setDescriptorHeaps(ID3D12DescriptorHeap* srvDescriptorHeap,
                             ID3D12DescriptorHeap* samplerDescriptorHeap);
 
     void addSampledTextureRef(GrD3DTexture*);
diff --git a/src/gpu/d3d/GrD3DDescriptorTableManager.cpp b/src/gpu/d3d/GrD3DDescriptorTableManager.cpp
index ec2ff19..56dcf6b 100644
--- a/src/gpu/d3d/GrD3DDescriptorTableManager.cpp
+++ b/src/gpu/d3d/GrD3DDescriptorTableManager.cpp
@@ -16,27 +16,15 @@
 sk_sp<GrD3DDescriptorTable>
         GrD3DDescriptorTableManager::createShaderViewTable(GrD3DGpu* gpu, unsigned int size) {
     sk_sp<GrD3DDescriptorTable> table = fShaderViewDescriptorPool.allocateTable(gpu, size);
-    this->setHeaps(gpu);
     return table;
 }
 
 sk_sp<GrD3DDescriptorTable> GrD3DDescriptorTableManager::createSamplerTable(
         GrD3DGpu* gpu, unsigned int size) {
     sk_sp<GrD3DDescriptorTable> table = fSamplerDescriptorPool.allocateTable(gpu, size);
-    this->setHeaps(gpu);
     return table;
 }
 
-void GrD3DDescriptorTableManager::setHeaps(GrD3DGpu* gpu) {
-    sk_sp<Heap>& currentCBVSRVHeap = fShaderViewDescriptorPool.currentDescriptorHeap();
-    sk_sp<Heap>& currentSamplerHeap = fSamplerDescriptorPool.currentDescriptorHeap();
-    GrD3DDirectCommandList* commandList = gpu->currentCommandList();
-    commandList->setDescriptorHeaps(currentCBVSRVHeap,
-                                    currentCBVSRVHeap->d3dDescriptorHeap(),
-                                    currentSamplerHeap,
-                                    currentSamplerHeap->d3dDescriptorHeap());
-}
-
 void GrD3DDescriptorTableManager::prepForSubmit(GrD3DGpu* gpu) {
     fShaderViewDescriptorPool.prepForSubmit(gpu);
     fSamplerDescriptorPool.prepForSubmit(gpu);
@@ -80,7 +68,8 @@
     fNextAvailable += count;
     return sk_sp<GrD3DDescriptorTable>(
             new GrD3DDescriptorTable(fHeap->getCPUHandle(startIndex).fHandle,
-                                     fHeap->getGPUHandle(startIndex).fHandle, fType));
+                                     fHeap->getGPUHandle(startIndex).fHandle,
+                                     fHeap->descriptorHeap(), fType));
 }
 
 void GrD3DDescriptorTableManager::Heap::onRecycle() const {
@@ -103,8 +92,12 @@
     // If it was already used, it will have been added to the commandlist,
     // and then later recycled back to us.
     while (fDescriptorHeaps.size() > 0) {
-        if (fDescriptorHeaps[fDescriptorHeaps.size() - 1]->canAllocate(count)) {
-            return fDescriptorHeaps[fDescriptorHeaps.size() - 1]->allocateTable(count);
+        auto& heap = fDescriptorHeaps[fDescriptorHeaps.size() - 1];
+        if (heap->canAllocate(count)) {
+            if (!heap->used()) {
+                gpu->currentCommandList()->addRecycledResource(heap);
+            }
+            return heap->allocateTable(count);
         }
         // No space in current heap, pop off list
         fDescriptorHeaps.pop_back();
@@ -114,6 +107,7 @@
     fCurrentHeapDescriptorCount = std::min(2*fCurrentHeapDescriptorCount, 2048u);
     sk_sp<GrD3DDescriptorTableManager::Heap> heap =
             GrD3DDescriptorTableManager::Heap::Make(gpu, fHeapType, fCurrentHeapDescriptorCount);
+    gpu->currentCommandList()->addRecycledResource(heap);
     fDescriptorHeaps.push_back(heap);
     return fDescriptorHeaps[fDescriptorHeaps.size() - 1]->allocateTable(count);
 }
diff --git a/src/gpu/d3d/GrD3DDescriptorTableManager.h b/src/gpu/d3d/GrD3DDescriptorTableManager.h
index 253f038..fe54a1b 100644
--- a/src/gpu/d3d/GrD3DDescriptorTableManager.h
+++ b/src/gpu/d3d/GrD3DDescriptorTableManager.h
@@ -17,9 +17,10 @@
 class GrD3DDescriptorTable : public SkRefCnt {
 public:
     GrD3DDescriptorTable(D3D12_CPU_DESCRIPTOR_HANDLE baseCPU, D3D12_GPU_DESCRIPTOR_HANDLE baseGPU,
-                         D3D12_DESCRIPTOR_HEAP_TYPE type)
+                         ID3D12DescriptorHeap* heap, D3D12_DESCRIPTOR_HEAP_TYPE type)
         : fDescriptorTableCpuStart(baseCPU)
         , fDescriptorTableGpuStart(baseGPU)
+        , fHeap(heap)
         , fType(type) {}
 
     const D3D12_CPU_DESCRIPTOR_HANDLE* baseCpuDescriptorPtr() {
@@ -30,11 +31,13 @@
         return fDescriptorTableGpuStart;
     }
 
+    ID3D12DescriptorHeap* heap() const { return fHeap; }
     D3D12_DESCRIPTOR_HEAP_TYPE type() const { return fType; }
 
 private:
     D3D12_CPU_DESCRIPTOR_HANDLE fDescriptorTableCpuStart;
     D3D12_GPU_DESCRIPTOR_HANDLE fDescriptorTableGpuStart;
+    ID3D12DescriptorHeap* fHeap;
     D3D12_DESCRIPTOR_HEAP_TYPE fType;
 };
 
@@ -112,7 +115,6 @@
         unsigned int fCurrentHeapDescriptorCount;
     };
 
-    void setHeaps(GrD3DGpu*);
     void recycle(Heap*);
 
     HeapPool fShaderViewDescriptorPool;
diff --git a/src/gpu/d3d/GrD3DPipelineState.cpp b/src/gpu/d3d/GrD3DPipelineState.cpp
index 9db5ddf..916df8a2 100644
--- a/src/gpu/d3d/GrD3DPipelineState.cpp
+++ b/src/gpu/d3d/GrD3DPipelineState.cpp
@@ -131,16 +131,19 @@
 
     // fill in descriptor tables and bind to root signature
     if (fNumSamplers > 0) {
-        // set up and bind shader resource view table
+        // set up descriptor tables and bind heaps
         sk_sp<GrD3DDescriptorTable> srvTable =
                 gpu->resourceProvider().findOrCreateShaderViewTable(shaderResourceViews);
+        sk_sp<GrD3DDescriptorTable> samplerTable =
+            gpu->resourceProvider().findOrCreateSamplerTable(samplers);
+        gpu->currentCommandList()->setDescriptorHeaps(srvTable->heap(), samplerTable->heap());
+
+        // bind shader resource view table
         gpu->currentCommandList()->setGraphicsRootDescriptorTable(
                 (unsigned int)GrD3DRootSignature::ParamIndex::kShaderViewDescriptorTable,
                 srvTable->baseGpuDescriptor());
 
-        // set up and bind sampler table
-        sk_sp<GrD3DDescriptorTable> samplerTable =
-                gpu->resourceProvider().findOrCreateSamplerTable(samplers);
+        // bind sampler table
         gpu->currentCommandList()->setGraphicsRootDescriptorTable(
                 (unsigned int)GrD3DRootSignature::ParamIndex::kSamplerDescriptorTable,
                 samplerTable->baseGpuDescriptor());