• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "src/gpu/d3d/GrD3DDescriptorTableManager.h"
9 
10 #include "src/gpu/d3d/GrD3DGpu.h"
11 
GrD3DDescriptorTableManager(GrD3DGpu * gpu)12 GrD3DDescriptorTableManager::GrD3DDescriptorTableManager(GrD3DGpu* gpu)
13     : fShaderViewDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)
14     , fSamplerDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) {}
15 
16 sk_sp<GrD3DDescriptorTable>
createShaderViewTable(GrD3DGpu * gpu,unsigned int size)17         GrD3DDescriptorTableManager::createShaderViewTable(GrD3DGpu* gpu, unsigned int size) {
18     sk_sp<GrD3DDescriptorTable> table = fShaderViewDescriptorPool.allocateTable(gpu, size);
19     return table;
20 }
21 
createSamplerTable(GrD3DGpu * gpu,unsigned int size)22 sk_sp<GrD3DDescriptorTable> GrD3DDescriptorTableManager::createSamplerTable(
23         GrD3DGpu* gpu, unsigned int size) {
24     sk_sp<GrD3DDescriptorTable> table = fSamplerDescriptorPool.allocateTable(gpu, size);
25     return table;
26 }
27 
prepForSubmit(GrD3DGpu * gpu)28 void GrD3DDescriptorTableManager::prepForSubmit(GrD3DGpu* gpu) {
29     fShaderViewDescriptorPool.prepForSubmit(gpu);
30     fSamplerDescriptorPool.prepForSubmit(gpu);
31 }
32 
recycle(Heap * heap)33 void GrD3DDescriptorTableManager::recycle(Heap* heap) {
34     // wrap the heap in an sk_sp and take ownership of it
35     sk_sp<Heap> wrappedHeap(heap);
36 
37     SkASSERT(heap);
38     switch (heap->type()) {
39         case D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV:
40             fShaderViewDescriptorPool.recycle(std::move(wrappedHeap));
41             break;
42         case D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER:
43             fSamplerDescriptorPool.recycle(std::move(wrappedHeap));
44             break;
45         default:
46             SkUNREACHABLE;
47     }
48 }
49 
50 ////////////////////////////////////////////////////////////////////////////////////////////////
51 
Make(GrD3DGpu * gpu,D3D12_DESCRIPTOR_HEAP_TYPE type,unsigned int descriptorCount)52 sk_sp<GrD3DDescriptorTableManager::Heap> GrD3DDescriptorTableManager::Heap::Make(
53         GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE type, unsigned int descriptorCount) {
54     std::unique_ptr<GrD3DDescriptorHeap> heap =
55             GrD3DDescriptorHeap::Make(gpu, type, descriptorCount,
56                                       D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE);
57     if (!heap) {
58         return nullptr;
59     }
60 
61     return sk_sp< GrD3DDescriptorTableManager::Heap>(new Heap(gpu, heap, type, descriptorCount));
62 }
63 
allocateTable(unsigned int count)64 sk_sp<GrD3DDescriptorTable> GrD3DDescriptorTableManager::Heap::allocateTable(
65         unsigned int count) {
66     SkASSERT(fDescriptorCount - fNextAvailable >= count);
67     unsigned int startIndex = fNextAvailable;
68     fNextAvailable += count;
69     return sk_sp<GrD3DDescriptorTable>(
70             new GrD3DDescriptorTable(fHeap->getCPUHandle(startIndex).fHandle,
71                                      fHeap->getGPUHandle(startIndex).fHandle,
72                                      fHeap->descriptorHeap(), fType));
73 }
74 
onRecycle() const75 void GrD3DDescriptorTableManager::Heap::onRecycle() const {
76     fGpu->resourceProvider().descriptorTableMgr()->recycle(const_cast<Heap*>(this));
77 }
78 
79 ////////////////////////////////////////////////////////////////////////////////////////////////
80 
HeapPool(GrD3DGpu * gpu,D3D12_DESCRIPTOR_HEAP_TYPE heapType)81 GrD3DDescriptorTableManager::HeapPool::HeapPool(GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE heapType)
82     : fHeapType(heapType)
83     , fCurrentHeapDescriptorCount(kInitialHeapDescriptorCount) {
84     sk_sp<Heap> heap = Heap::Make(gpu, fHeapType, fCurrentHeapDescriptorCount);
85     fDescriptorHeaps.push_back(heap);
86 }
87 
allocateTable(GrD3DGpu * gpu,unsigned int count)88 sk_sp<GrD3DDescriptorTable> GrD3DDescriptorTableManager::HeapPool::allocateTable(
89         GrD3DGpu* gpu, unsigned int count) {
90     // In back-to-front order, iterate through heaps until we find one we can allocate from.
91     // Any heap we can't allocate from gets removed from the list.
92     // If it was already used, it will have been added to the commandlist,
93     // and then later recycled back to us.
94     while (fDescriptorHeaps.size() > 0) {
95         auto& heap = fDescriptorHeaps[fDescriptorHeaps.size() - 1];
96         if (heap->canAllocate(count)) {
97             if (!heap->used()) {
98                 gpu->currentCommandList()->addRecycledResource(heap);
99             }
100             return heap->allocateTable(count);
101         }
102         // No space in current heap, pop off list
103         fDescriptorHeaps.pop_back();
104     }
105 
106     // Out of available heaps, need to allocate a new one
107     fCurrentHeapDescriptorCount = std::min(2*fCurrentHeapDescriptorCount, 2048u);
108     sk_sp<GrD3DDescriptorTableManager::Heap> heap =
109             GrD3DDescriptorTableManager::Heap::Make(gpu, fHeapType, fCurrentHeapDescriptorCount);
110     gpu->currentCommandList()->addRecycledResource(heap);
111     fDescriptorHeaps.push_back(heap);
112     return fDescriptorHeaps[fDescriptorHeaps.size() - 1]->allocateTable(count);
113 }
114 
115 sk_sp<GrD3DDescriptorTableManager::Heap>&
currentDescriptorHeap()116         GrD3DDescriptorTableManager::HeapPool::currentDescriptorHeap() {
117     SkASSERT(fDescriptorHeaps.size() > 0);
118     return fDescriptorHeaps[fDescriptorHeaps.size() - 1];
119 }
120 
prepForSubmit(GrD3DGpu * gpu)121 void GrD3DDescriptorTableManager::HeapPool::prepForSubmit(GrD3DGpu* gpu) {
122     // Pop off the current descriptor heap
123     if (fDescriptorHeaps[fDescriptorHeaps.size() - 1]->used()) {
124         fDescriptorHeaps.pop_back();
125     }
126 
127     if (fDescriptorHeaps.size() == 0) {
128         fCurrentHeapDescriptorCount = std::min(fCurrentHeapDescriptorCount, 2048u);
129         sk_sp<GrD3DDescriptorTableManager::Heap> heap =
130             GrD3DDescriptorTableManager::Heap::Make(gpu, fHeapType, fCurrentHeapDescriptorCount);
131         fDescriptorHeaps.push_back(heap);
132     }
133 }
134 
recycle(sk_sp<Heap> heap)135 void GrD3DDescriptorTableManager::HeapPool::recycle(sk_sp<Heap> heap) {
136     SkASSERT(heap);
137     // only add heaps back if they match our current size
138     // this purges any smaller heaps we no longer need
139     if (heap->descriptorCount() == fCurrentHeapDescriptorCount) {
140         heap->reset();
141         fDescriptorHeaps.push_back(heap);
142     }
143 }
144