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 , fShaderViewDescriptorPool(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 =
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
createShaderResourceView(GrD3DGpu * gpu,ID3D12Resource * resource,unsigned int mostDetailedMip,unsigned int mipLevels)53 GrD3DDescriptorHeap::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
createUnorderedAccessView(GrD3DGpu * gpu,ID3D12Resource * resource,unsigned int mipSlice)70 GrD3DDescriptorHeap::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
recycleShaderView(const GrD3DDescriptorHeap::CPUHandle & view)87 void GrD3DCpuDescriptorManager::recycleShaderView(
88 const GrD3DDescriptorHeap::CPUHandle& view) {
89 fShaderViewDescriptorPool.releaseHandle(view);
90 }
91
createSampler(GrD3DGpu * gpu,D3D12_FILTER filter,float maxLOD,D3D12_TEXTURE_ADDRESS_MODE addressModeU,D3D12_TEXTURE_ADDRESS_MODE addressModeV)92 GrD3DDescriptorHeap::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
recycleSampler(const GrD3DDescriptorHeap::CPUHandle & samplerDescriptor)115 void GrD3DCpuDescriptorManager::recycleSampler(
116 const GrD3DDescriptorHeap::CPUHandle& samplerDescriptor) {
117 fSamplerDescriptorPool.releaseHandle(samplerDescriptor);
118 }
119
120 ////////////////////////////////////////////////////////////////////////////////////////////////
121
Make(GrD3DGpu * gpu,D3D12_DESCRIPTOR_HEAP_TYPE type,unsigned int numDescriptors)122 std::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
allocateCPUHandle()133 GrD3DDescriptorHeap::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
freeCPUHandle(const GrD3DDescriptorHeap::CPUHandle & handle)141 void 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
HeapPool(GrD3DGpu * gpu,D3D12_DESCRIPTOR_HEAP_TYPE heapType)150 GrD3DCpuDescriptorManager::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
allocateHandle(GrD3DGpu * gpu)158 GrD3DDescriptorHeap::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
releaseHandle(const GrD3DDescriptorHeap::CPUHandle & dsvDescriptor)181 void 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