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 12GrD3DCpuDescriptorManager::GrD3DCpuDescriptorManager(GrD3DGpu* gpu) 13 : fRTVDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_RTV) 14 , fDSVDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_DSV) 15 , fShaderViewDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) 16 , fSamplerDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) {} 17 18GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createRenderTargetView( 19 GrD3DGpu* gpu, ID3D12Resource* textureResource) { 20 const GrD3DDescriptorHeap::CPUHandle& descriptor = fRTVDescriptorPool.allocateHandle(gpu); 21 gpu->device()->CreateRenderTargetView(textureResource, nullptr, descriptor.fHandle); 22 return descriptor; 23} 24 25void GrD3DCpuDescriptorManager::recycleRenderTargetView( 26 const GrD3DDescriptorHeap::CPUHandle& rtvDescriptor) { 27 fRTVDescriptorPool.releaseHandle(rtvDescriptor); 28} 29 30GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createDepthStencilView( 31 GrD3DGpu* gpu, ID3D12Resource* textureResource) { 32 const GrD3DDescriptorHeap::CPUHandle& descriptor = fDSVDescriptorPool.allocateHandle(gpu); 33 gpu->device()->CreateDepthStencilView(textureResource, nullptr, descriptor.fHandle); 34 return descriptor; 35} 36 37void GrD3DCpuDescriptorManager::recycleDepthStencilView( 38 const GrD3DDescriptorHeap::CPUHandle& dsvDescriptor) { 39 fDSVDescriptorPool.releaseHandle(dsvDescriptor); 40} 41 42GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createConstantBufferView( 43 GrD3DGpu* gpu, ID3D12Resource* bufferResource, size_t offset, size_t size) { 44 const GrD3DDescriptorHeap::CPUHandle& descriptor = 45 fShaderViewDescriptorPool.allocateHandle(gpu); 46 D3D12_CONSTANT_BUFFER_VIEW_DESC desc = {}; 47 desc.BufferLocation = bufferResource->GetGPUVirtualAddress() + offset; 48 desc.SizeInBytes = size; 49 gpu->device()->CreateConstantBufferView(&desc, descriptor.fHandle); 50 return descriptor; 51} 52 53GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createShaderResourceView( 54 GrD3DGpu* gpu, ID3D12Resource* resource, 55 unsigned int mostDetailedMip, unsigned int mipLevels) { 56 const GrD3DDescriptorHeap::CPUHandle& descriptor = 57 fShaderViewDescriptorPool.allocateHandle(gpu); 58 // TODO: for 4:2:0 YUV formats we'll need to map two different views, one for Y and one for UV. 59 // For now map the entire resource. 60 D3D12_SHADER_RESOURCE_VIEW_DESC desc = {}; 61 desc.Format = resource->GetDesc().Format; 62 desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; 63 desc.Texture2D.MostDetailedMip = mostDetailedMip; 64 desc.Texture2D.MipLevels = mipLevels; 65 desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; 66 gpu->device()->CreateShaderResourceView(resource, &desc, descriptor.fHandle); 67 return descriptor; 68} 69 70GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createUnorderedAccessView( 71 GrD3DGpu* gpu, ID3D12Resource* resource, unsigned int mipSlice) { 72 const GrD3DDescriptorHeap::CPUHandle& descriptor = 73 fShaderViewDescriptorPool.allocateHandle(gpu); 74 if (resource->GetDesc().Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) { 75 // TODO: figure out buffer setup 76 gpu->device()->CreateUnorderedAccessView(resource, nullptr, nullptr, descriptor.fHandle); 77 } else { 78 D3D12_UNORDERED_ACCESS_VIEW_DESC desc = {}; 79 desc.Format = resource->GetDesc().Format; 80 desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; 81 desc.Texture2D.MipSlice = mipSlice; 82 gpu->device()->CreateUnorderedAccessView(resource, nullptr, &desc, descriptor.fHandle); 83 } 84 return descriptor; 85} 86 87void GrD3DCpuDescriptorManager::recycleShaderView( 88 const GrD3DDescriptorHeap::CPUHandle& view) { 89 fShaderViewDescriptorPool.releaseHandle(view); 90} 91 92GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createSampler( 93 GrD3DGpu* gpu, 94 D3D12_FILTER filter, 95 float maxLOD, 96 D3D12_TEXTURE_ADDRESS_MODE addressModeU, 97 D3D12_TEXTURE_ADDRESS_MODE addressModeV) { 98 const GrD3DDescriptorHeap::CPUHandle& descriptor = fSamplerDescriptorPool.allocateHandle(gpu); 99 D3D12_SAMPLER_DESC desc = {}; 100 desc.Filter = filter; 101 desc.AddressU = addressModeU; 102 desc.AddressV = addressModeV; 103 desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; 104 desc.MipLODBias = 0; 105 desc.MaxAnisotropy = 1; 106 desc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; 107 // desc.BorderColor initialized to { 0, 0, 0, 0 } by default initializer, above. 108 desc.MinLOD = 0; 109 desc.MaxLOD = maxLOD; 110 111 gpu->device()->CreateSampler(&desc, descriptor.fHandle); 112 return descriptor; 113} 114 115void GrD3DCpuDescriptorManager::recycleSampler( 116 const GrD3DDescriptorHeap::CPUHandle& samplerDescriptor) { 117 fSamplerDescriptorPool.releaseHandle(samplerDescriptor); 118} 119 120//////////////////////////////////////////////////////////////////////////////////////////////// 121 122std::unique_ptr<GrD3DCpuDescriptorManager::Heap> GrD3DCpuDescriptorManager::Heap::Make( 123 GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE type, unsigned int numDescriptors) { 124 std::unique_ptr<GrD3DDescriptorHeap> heap = 125 GrD3DDescriptorHeap::Make(gpu, type, numDescriptors, D3D12_DESCRIPTOR_HEAP_FLAG_NONE); 126 if (!heap) { 127 return nullptr; 128 } 129 130 return std::unique_ptr<Heap>(new Heap(heap, numDescriptors)); 131} 132 133GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::Heap::allocateCPUHandle() { 134 SkBitSet::OptionalIndex freeBlock = fFreeBlocks.findFirst(); 135 SkASSERT(freeBlock.has_value()); 136 fFreeBlocks.reset(*freeBlock); 137 --fFreeCount; 138 return fHeap->getCPUHandle(*freeBlock); 139} 140 141void GrD3DCpuDescriptorManager::Heap::freeCPUHandle(const GrD3DDescriptorHeap::CPUHandle& handle) { 142 SkASSERT(this->ownsHandle(handle)); 143 size_t index = fHeap->getIndex(handle); 144 fFreeBlocks.set(index); 145 ++fFreeCount; 146} 147 148//////////////////////////////////////////////////////////////////////////////////////////////// 149 150GrD3DCpuDescriptorManager::HeapPool::HeapPool(GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE heapType) 151 : fMaxAvailableDescriptors(32) 152 , fHeapType(heapType) { 153 std::unique_ptr<GrD3DCpuDescriptorManager::Heap> heap = 154 GrD3DCpuDescriptorManager::Heap::Make(gpu, fHeapType, fMaxAvailableDescriptors); 155 fDescriptorHeaps.push_back(std::move(heap)); 156} 157 158GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::HeapPool::allocateHandle( 159 GrD3DGpu* gpu) { 160 for (unsigned int i = 0; i < fDescriptorHeaps.size(); ++i) { 161 if (fDescriptorHeaps[i]->canAllocate()) { 162 GrD3DDescriptorHeap::CPUHandle handle = fDescriptorHeaps[i]->allocateCPUHandle(); 163 return handle; 164 } 165 } 166 167 // need to allocate more space 168 std::unique_ptr<GrD3DCpuDescriptorManager::Heap> heap = 169 GrD3DCpuDescriptorManager::Heap::Make(gpu, fHeapType, fMaxAvailableDescriptors); 170 // TODO: handle failed heap creation and/or memory restrictions better 171 // skbug.com/11959 172 SkASSERT(heap); 173 174 fDescriptorHeaps.push_back(std::move(heap)); 175 fMaxAvailableDescriptors *= 2; 176 GrD3DDescriptorHeap::CPUHandle handle = 177 fDescriptorHeaps[fDescriptorHeaps.size() - 1]->allocateCPUHandle(); 178 return handle; 179} 180 181void GrD3DCpuDescriptorManager::HeapPool::releaseHandle( 182 const GrD3DDescriptorHeap::CPUHandle& dsvDescriptor) { 183 for (unsigned int i = 0; i < fDescriptorHeaps.size(); ++i) { 184 if (fDescriptorHeaps[i]->ownsHandle(dsvDescriptor)) { 185 fDescriptorHeaps[i]->freeCPUHandle(dsvDescriptor); 186 return; 187 } 188 } 189 SkASSERT(false); 190} 191