Jim Van Verth | afd4113 | 2020-05-28 06:44:55 -0400 | [diff] [blame^] | 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/GrD3DCpuDescriptorManager.h" |
| 9 | |
| 10 | #include "src/gpu/d3d/GrD3DGpu.h" |
| 11 | |
| 12 | GrD3DCpuDescriptorManager::GrD3DCpuDescriptorManager(GrD3DGpu* gpu) |
| 13 | : fRTVDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_RTV) |
| 14 | , fDSVDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_DSV) |
| 15 | , fCBVSRVDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) |
| 16 | , fSamplerDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) {} |
| 17 | |
| 18 | D3D12_CPU_DESCRIPTOR_HANDLE GrD3DCpuDescriptorManager::createRenderTargetView( |
| 19 | GrD3DGpu* gpu, ID3D12Resource* textureResource) { |
| 20 | D3D12_CPU_DESCRIPTOR_HANDLE descriptor = fRTVDescriptorPool.allocateHandle(gpu); |
| 21 | gpu->device()->CreateRenderTargetView(textureResource, nullptr, descriptor); |
| 22 | return descriptor; |
| 23 | } |
| 24 | |
| 25 | void GrD3DCpuDescriptorManager::recycleRenderTargetView( |
| 26 | D3D12_CPU_DESCRIPTOR_HANDLE* rtvDescriptor) { |
| 27 | fRTVDescriptorPool.releaseHandle(rtvDescriptor); |
| 28 | } |
| 29 | |
| 30 | D3D12_CPU_DESCRIPTOR_HANDLE GrD3DCpuDescriptorManager::createDepthStencilView( |
| 31 | GrD3DGpu* gpu, ID3D12Resource* textureResource) { |
| 32 | D3D12_CPU_DESCRIPTOR_HANDLE descriptor = fDSVDescriptorPool.allocateHandle(gpu); |
| 33 | gpu->device()->CreateDepthStencilView(textureResource, nullptr, descriptor); |
| 34 | return descriptor; |
| 35 | } |
| 36 | |
| 37 | void GrD3DCpuDescriptorManager::recycleDepthStencilView( |
| 38 | D3D12_CPU_DESCRIPTOR_HANDLE* dsvDescriptor) { |
| 39 | fDSVDescriptorPool.releaseHandle(dsvDescriptor); |
| 40 | } |
| 41 | |
| 42 | D3D12_CPU_DESCRIPTOR_HANDLE GrD3DCpuDescriptorManager::createConstantBufferView( |
| 43 | GrD3DGpu* gpu, ID3D12Resource* bufferResource, size_t offset, size_t size) { |
| 44 | D3D12_CPU_DESCRIPTOR_HANDLE descriptor = fCBVSRVDescriptorPool.allocateHandle(gpu); |
| 45 | D3D12_CONSTANT_BUFFER_VIEW_DESC desc = {}; |
| 46 | desc.BufferLocation = bufferResource->GetGPUVirtualAddress() + offset; |
| 47 | desc.SizeInBytes = size; |
| 48 | gpu->device()->CreateConstantBufferView(&desc, descriptor); |
| 49 | return descriptor; |
| 50 | } |
| 51 | |
| 52 | D3D12_CPU_DESCRIPTOR_HANDLE GrD3DCpuDescriptorManager::createShaderResourceView( |
| 53 | GrD3DGpu* gpu, ID3D12Resource* resource) { |
| 54 | D3D12_CPU_DESCRIPTOR_HANDLE descriptor = fCBVSRVDescriptorPool.allocateHandle(gpu); |
| 55 | // TODO: for 4:2:0 YUV formats we'll need to map two different views, one for Y and one for UV. |
| 56 | // For now map the entire resource. |
| 57 | gpu->device()->CreateShaderResourceView(resource, nullptr, descriptor); |
| 58 | return descriptor; |
| 59 | } |
| 60 | |
| 61 | void GrD3DCpuDescriptorManager::recycleConstantOrShaderView(D3D12_CPU_DESCRIPTOR_HANDLE* view) { |
| 62 | fCBVSRVDescriptorPool.releaseHandle(view); |
| 63 | } |
| 64 | |
| 65 | D3D12_CPU_DESCRIPTOR_HANDLE GrD3DCpuDescriptorManager::createSampler( |
| 66 | GrD3DGpu* gpu, D3D12_FILTER filter, D3D12_TEXTURE_ADDRESS_MODE addressModeU, |
| 67 | D3D12_TEXTURE_ADDRESS_MODE addressModeV) { |
| 68 | D3D12_CPU_DESCRIPTOR_HANDLE descriptor = fSamplerDescriptorPool.allocateHandle(gpu); |
| 69 | D3D12_SAMPLER_DESC desc = {}; |
| 70 | desc.Filter = filter; |
| 71 | desc.AddressU = addressModeU; |
| 72 | desc.AddressV = addressModeV; |
| 73 | desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; |
| 74 | desc.MipLODBias = 0; |
| 75 | desc.MaxAnisotropy = 1; |
| 76 | desc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; |
| 77 | // desc.BorderColor initialized to { 0, 0, 0, 0 } by default initializer, above. |
| 78 | desc.MinLOD = 0; |
| 79 | desc.MaxLOD = SK_ScalarMax; |
| 80 | |
| 81 | gpu->device()->CreateSampler(&desc, descriptor); |
| 82 | return descriptor; |
| 83 | } |
| 84 | |
| 85 | void GrD3DCpuDescriptorManager::recycleSampler(D3D12_CPU_DESCRIPTOR_HANDLE* samplerDescriptor) { |
| 86 | fSamplerDescriptorPool.releaseHandle(samplerDescriptor); |
| 87 | } |
| 88 | |
| 89 | //////////////////////////////////////////////////////////////////////////////////////////////// |
| 90 | |
| 91 | std::unique_ptr<GrD3DCpuDescriptorManager::Heap> GrD3DCpuDescriptorManager::Heap::Make( |
| 92 | GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE type, unsigned int numDescriptors) { |
| 93 | std::unique_ptr<GrD3DDescriptorHeap> heap = |
| 94 | GrD3DDescriptorHeap::Make(gpu, type, numDescriptors, D3D12_DESCRIPTOR_HEAP_FLAG_NONE); |
| 95 | if (!heap) { |
| 96 | return nullptr; |
| 97 | } |
| 98 | |
| 99 | return std::unique_ptr<Heap>(new Heap(heap, numDescriptors)); |
| 100 | } |
| 101 | |
| 102 | D3D12_CPU_DESCRIPTOR_HANDLE GrD3DCpuDescriptorManager::Heap::allocateCPUHandle() { |
| 103 | SkBitSet::OptionalIndex freeBlock = fFreeBlocks.findFirst(); |
| 104 | SkASSERT(freeBlock); |
| 105 | fFreeBlocks.reset(*freeBlock); |
| 106 | --fFreeCount; |
| 107 | return fHeap->getCPUHandle(*freeBlock); |
| 108 | } |
| 109 | |
| 110 | bool GrD3DCpuDescriptorManager::Heap::freeCPUHandle(D3D12_CPU_DESCRIPTOR_HANDLE* handle) { |
| 111 | size_t index; |
| 112 | if (!fHeap->getIndex(*handle, &index)) { |
| 113 | return false; |
| 114 | } |
| 115 | fFreeBlocks.set(index); |
| 116 | ++fFreeCount; |
| 117 | handle->ptr = 0; |
| 118 | return true; |
| 119 | } |
| 120 | |
| 121 | //////////////////////////////////////////////////////////////////////////////////////////////// |
| 122 | |
| 123 | GrD3DCpuDescriptorManager::HeapPool::HeapPool(GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE heapType) |
| 124 | : fMaxAvailableDescriptors(32) |
| 125 | , fHeapType(heapType) { |
| 126 | std::unique_ptr<GrD3DCpuDescriptorManager::Heap> heap = |
| 127 | GrD3DCpuDescriptorManager::Heap::Make(gpu, fHeapType, fMaxAvailableDescriptors); |
| 128 | fDescriptorHeaps.push_back(std::move(heap)); |
| 129 | } |
| 130 | |
| 131 | D3D12_CPU_DESCRIPTOR_HANDLE GrD3DCpuDescriptorManager::HeapPool::allocateHandle(GrD3DGpu* gpu) { |
| 132 | for (unsigned int i = 0; i < fDescriptorHeaps.size(); ++i) { |
| 133 | if (fDescriptorHeaps[i]->canAllocate()) { |
| 134 | D3D12_CPU_DESCRIPTOR_HANDLE handle = fDescriptorHeaps[i]->allocateCPUHandle(); |
| 135 | return handle; |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | // need to allocate more space |
| 140 | std::unique_ptr<GrD3DCpuDescriptorManager::Heap> heap = |
| 141 | GrD3DCpuDescriptorManager::Heap::Make(gpu, fHeapType, fMaxAvailableDescriptors); |
| 142 | |
| 143 | fDescriptorHeaps.push_back(std::move(heap)); |
| 144 | fMaxAvailableDescriptors *= 2; |
| 145 | D3D12_CPU_DESCRIPTOR_HANDLE handle = |
| 146 | fDescriptorHeaps[fDescriptorHeaps.size() - 1]->allocateCPUHandle(); |
| 147 | return handle; |
| 148 | } |
| 149 | |
| 150 | void GrD3DCpuDescriptorManager::HeapPool::releaseHandle( |
| 151 | D3D12_CPU_DESCRIPTOR_HANDLE* dsvDescriptor) { |
| 152 | for (unsigned int i = 0; i < fDescriptorHeaps.size(); ++i) { |
| 153 | if (fDescriptorHeaps[i]->freeCPUHandle(dsvDescriptor)) { |
| 154 | return; |
| 155 | } |
| 156 | } |
| 157 | SkASSERT(false); |
| 158 | } |