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