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 12GrD3DDescriptorTableManager::GrD3DDescriptorTableManager(GrD3DGpu* gpu) 13 : fShaderViewDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) 14 , fSamplerDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) {} 15 16sk_sp<GrD3DDescriptorTable> 17 GrD3DDescriptorTableManager::createShaderViewTable(GrD3DGpu* gpu, unsigned int size) { 18 sk_sp<GrD3DDescriptorTable> table = fShaderViewDescriptorPool.allocateTable(gpu, size); 19 return table; 20} 21 22sk_sp<GrD3DDescriptorTable> GrD3DDescriptorTableManager::createSamplerTable( 23 GrD3DGpu* gpu, unsigned int size) { 24 sk_sp<GrD3DDescriptorTable> table = fSamplerDescriptorPool.allocateTable(gpu, size); 25 return table; 26} 27 28void GrD3DDescriptorTableManager::prepForSubmit(GrD3DGpu* gpu) { 29 fShaderViewDescriptorPool.prepForSubmit(gpu); 30 fSamplerDescriptorPool.prepForSubmit(gpu); 31} 32 33void 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 52sk_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 64sk_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 75void GrD3DDescriptorTableManager::Heap::onRecycle() const { 76 fGpu->resourceProvider().descriptorTableMgr()->recycle(const_cast<Heap*>(this)); 77} 78 79//////////////////////////////////////////////////////////////////////////////////////////////// 80 81GrD3DDescriptorTableManager::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 88sk_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 115sk_sp<GrD3DDescriptorTableManager::Heap>& 116 GrD3DDescriptorTableManager::HeapPool::currentDescriptorHeap() { 117 SkASSERT(fDescriptorHeaps.size() > 0); 118 return fDescriptorHeaps[fDescriptorHeaps.size() - 1]; 119} 120 121void 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 135void 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