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 
GrD3DCpuDescriptorManager(GrD3DGpu * gpu)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 
createRenderTargetView(GrD3DGpu * gpu,ID3D12Resource * textureResource)18 GrD3DDescriptorHeap::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 
recycleRenderTargetView(const GrD3DDescriptorHeap::CPUHandle & rtvDescriptor)25 void GrD3DCpuDescriptorManager::recycleRenderTargetView(
26         const GrD3DDescriptorHeap::CPUHandle& rtvDescriptor) {
27     fRTVDescriptorPool.releaseHandle(rtvDescriptor);
28 }
29 
createDepthStencilView(GrD3DGpu * gpu,ID3D12Resource * textureResource)30 GrD3DDescriptorHeap::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 
recycleDepthStencilView(const GrD3DDescriptorHeap::CPUHandle & dsvDescriptor)37 void GrD3DCpuDescriptorManager::recycleDepthStencilView(
38         const GrD3DDescriptorHeap::CPUHandle& dsvDescriptor) {
39     fDSVDescriptorPool.releaseHandle(dsvDescriptor);
40 }
41 
createConstantBufferView(GrD3DGpu * gpu,ID3D12Resource * bufferResource,size_t offset,size_t size)42 GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createConstantBufferView(
43         GrD3DGpu* gpu, ID3D12Resource* bufferResource, size_t offset, size_t size) {
44     const GrD3DDescriptorHeap::CPUHandle& 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.fHandle);
49     return descriptor;
50 }
51 
createShaderResourceView(GrD3DGpu * gpu,ID3D12Resource * resource)52 GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createShaderResourceView(
53         GrD3DGpu* gpu, ID3D12Resource* resource) {
54     const GrD3DDescriptorHeap::CPUHandle& 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.fHandle);
58     return descriptor;
59 }
60 
recycleConstantOrShaderView(const GrD3DDescriptorHeap::CPUHandle & view)61 void GrD3DCpuDescriptorManager::recycleConstantOrShaderView(
62         const GrD3DDescriptorHeap::CPUHandle& view) {
63     fCBVSRVDescriptorPool.releaseHandle(view);
64 }
65 
createSampler(GrD3DGpu * gpu,D3D12_FILTER filter,float maxLOD,D3D12_TEXTURE_ADDRESS_MODE addressModeU,D3D12_TEXTURE_ADDRESS_MODE addressModeV)66 GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createSampler(
67         GrD3DGpu* gpu,
68         D3D12_FILTER filter,
69         float maxLOD,
70         D3D12_TEXTURE_ADDRESS_MODE addressModeU,
71         D3D12_TEXTURE_ADDRESS_MODE addressModeV) {
72     const GrD3DDescriptorHeap::CPUHandle& descriptor = fSamplerDescriptorPool.allocateHandle(gpu);
73     D3D12_SAMPLER_DESC desc = {};
74     desc.Filter = filter;
75     desc.AddressU = addressModeU;
76     desc.AddressV = addressModeV;
77     desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
78     desc.MipLODBias = 0;
79     desc.MaxAnisotropy = 1;
80     desc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
81     // desc.BorderColor initialized to { 0, 0, 0, 0 } by default initializer, above.
82     desc.MinLOD = 0;
83     desc.MaxLOD = maxLOD;
84 
85     gpu->device()->CreateSampler(&desc, descriptor.fHandle);
86     return descriptor;
87 }
88 
recycleSampler(const GrD3DDescriptorHeap::CPUHandle & samplerDescriptor)89 void GrD3DCpuDescriptorManager::recycleSampler(
90         const GrD3DDescriptorHeap::CPUHandle& samplerDescriptor) {
91     fSamplerDescriptorPool.releaseHandle(samplerDescriptor);
92 }
93 
94 ////////////////////////////////////////////////////////////////////////////////////////////////
95 
Make(GrD3DGpu * gpu,D3D12_DESCRIPTOR_HEAP_TYPE type,unsigned int numDescriptors)96 std::unique_ptr<GrD3DCpuDescriptorManager::Heap> GrD3DCpuDescriptorManager::Heap::Make(
97         GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE type, unsigned int numDescriptors) {
98     std::unique_ptr<GrD3DDescriptorHeap> heap =
99             GrD3DDescriptorHeap::Make(gpu, type, numDescriptors, D3D12_DESCRIPTOR_HEAP_FLAG_NONE);
100     if (!heap) {
101         return nullptr;
102     }
103 
104     return std::unique_ptr<Heap>(new Heap(heap, numDescriptors));
105 }
106 
allocateCPUHandle()107 GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::Heap::allocateCPUHandle() {
108     SkBitSet::OptionalIndex freeBlock = fFreeBlocks.findFirst();
109     SkASSERT(freeBlock);
110     fFreeBlocks.reset(*freeBlock);
111     --fFreeCount;
112     return fHeap->getCPUHandle(*freeBlock);
113 }
114 
freeCPUHandle(const GrD3DDescriptorHeap::CPUHandle & handle)115 void GrD3DCpuDescriptorManager::Heap::freeCPUHandle(const GrD3DDescriptorHeap::CPUHandle& handle) {
116     SkASSERT(this->ownsHandle(handle));
117     size_t index = fHeap->getIndex(handle);
118     fFreeBlocks.set(index);
119     ++fFreeCount;
120 }
121 
122 ////////////////////////////////////////////////////////////////////////////////////////////////
123 
HeapPool(GrD3DGpu * gpu,D3D12_DESCRIPTOR_HEAP_TYPE heapType)124 GrD3DCpuDescriptorManager::HeapPool::HeapPool(GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE heapType)
125     : fMaxAvailableDescriptors(32)
126     , fHeapType(heapType) {
127     std::unique_ptr<GrD3DCpuDescriptorManager::Heap> heap =
128             GrD3DCpuDescriptorManager::Heap::Make(gpu, fHeapType, fMaxAvailableDescriptors);
129     fDescriptorHeaps.push_back(std::move(heap));
130 }
131 
allocateHandle(GrD3DGpu * gpu)132 GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::HeapPool::allocateHandle(
133         GrD3DGpu* gpu) {
134     for (unsigned int i = 0; i < fDescriptorHeaps.size(); ++i) {
135         if (fDescriptorHeaps[i]->canAllocate()) {
136             GrD3DDescriptorHeap::CPUHandle handle = fDescriptorHeaps[i]->allocateCPUHandle();
137             return handle;
138         }
139     }
140 
141     // need to allocate more space
142     std::unique_ptr<GrD3DCpuDescriptorManager::Heap> heap =
143         GrD3DCpuDescriptorManager::Heap::Make(gpu, fHeapType, fMaxAvailableDescriptors);
144 
145     fDescriptorHeaps.push_back(std::move(heap));
146     fMaxAvailableDescriptors *= 2;
147     GrD3DDescriptorHeap::CPUHandle handle =
148             fDescriptorHeaps[fDescriptorHeaps.size() - 1]->allocateCPUHandle();
149     return handle;
150 }
151 
releaseHandle(const GrD3DDescriptorHeap::CPUHandle & dsvDescriptor)152 void GrD3DCpuDescriptorManager::HeapPool::releaseHandle(
153         const GrD3DDescriptorHeap::CPUHandle& dsvDescriptor) {
154     for (unsigned int i = 0; i < fDescriptorHeaps.size(); ++i) {
155         if (fDescriptorHeaps[i]->ownsHandle(dsvDescriptor)) {
156             fDescriptorHeaps[i]->freeCPUHandle(dsvDescriptor);
157             return;
158         }
159     }
160     SkASSERT(false);
161 }
162