xref: /aosp_15_r20/external/skia/src/gpu/ganesh/d3d/GrD3DCpuDescriptorManager.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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/ganesh/d3d/GrD3DCpuDescriptorManager.h"
9 
10 #include "src/gpu/ganesh/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,unsigned int maxAnisotropy,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         unsigned int maxAnisotropy,
97         D3D12_TEXTURE_ADDRESS_MODE addressModeU,
98         D3D12_TEXTURE_ADDRESS_MODE addressModeV) {
99     const GrD3DDescriptorHeap::CPUHandle& descriptor = fSamplerDescriptorPool.allocateHandle(gpu);
100     D3D12_SAMPLER_DESC desc = {};
101     desc.Filter = filter;
102     desc.AddressU = addressModeU;
103     desc.AddressV = addressModeV;
104     desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
105     desc.MipLODBias = 0;
106     desc.MaxAnisotropy = maxAnisotropy;
107     desc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
108     // desc.BorderColor initialized to { 0, 0, 0, 0 } by default initializer, above.
109     desc.MinLOD = 0;
110     desc.MaxLOD = maxLOD;
111 
112     gpu->device()->CreateSampler(&desc, descriptor.fHandle);
113     return descriptor;
114 }
115 
recycleSampler(const GrD3DDescriptorHeap::CPUHandle & samplerDescriptor)116 void GrD3DCpuDescriptorManager::recycleSampler(
117         const GrD3DDescriptorHeap::CPUHandle& samplerDescriptor) {
118     fSamplerDescriptorPool.releaseHandle(samplerDescriptor);
119 }
120 
121 ////////////////////////////////////////////////////////////////////////////////////////////////
122 
Make(GrD3DGpu * gpu,D3D12_DESCRIPTOR_HEAP_TYPE type,unsigned int numDescriptors)123 std::unique_ptr<GrD3DCpuDescriptorManager::Heap> GrD3DCpuDescriptorManager::Heap::Make(
124         GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE type, unsigned int numDescriptors) {
125     std::unique_ptr<GrD3DDescriptorHeap> heap =
126             GrD3DDescriptorHeap::Make(gpu, type, numDescriptors, D3D12_DESCRIPTOR_HEAP_FLAG_NONE);
127     if (!heap) {
128         return nullptr;
129     }
130 
131     return std::unique_ptr<Heap>(new Heap(heap, numDescriptors));
132 }
133 
allocateCPUHandle()134 GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::Heap::allocateCPUHandle() {
135     SkBitSet::OptionalIndex freeBlock = fFreeBlocks.findFirst();
136     SkASSERT(freeBlock.has_value());
137     fFreeBlocks.reset(*freeBlock);
138     --fFreeCount;
139     return fHeap->getCPUHandle(*freeBlock);
140 }
141 
freeCPUHandle(const GrD3DDescriptorHeap::CPUHandle & handle)142 void GrD3DCpuDescriptorManager::Heap::freeCPUHandle(const GrD3DDescriptorHeap::CPUHandle& handle) {
143     SkASSERT(this->ownsHandle(handle));
144     size_t index = fHeap->getIndex(handle);
145     fFreeBlocks.set(index);
146     ++fFreeCount;
147 }
148 
149 ////////////////////////////////////////////////////////////////////////////////////////////////
150 
HeapPool(GrD3DGpu * gpu,D3D12_DESCRIPTOR_HEAP_TYPE heapType)151 GrD3DCpuDescriptorManager::HeapPool::HeapPool(GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE heapType)
152     : fMaxAvailableDescriptors(32)
153     , fHeapType(heapType) {
154     std::unique_ptr<GrD3DCpuDescriptorManager::Heap> heap =
155             GrD3DCpuDescriptorManager::Heap::Make(gpu, fHeapType, fMaxAvailableDescriptors);
156     fDescriptorHeaps.push_back(std::move(heap));
157 }
158 
allocateHandle(GrD3DGpu * gpu)159 GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::HeapPool::allocateHandle(
160         GrD3DGpu* gpu) {
161     for (unsigned int i = 0; i < fDescriptorHeaps.size(); ++i) {
162         if (fDescriptorHeaps[i]->canAllocate()) {
163             GrD3DDescriptorHeap::CPUHandle handle = fDescriptorHeaps[i]->allocateCPUHandle();
164             return handle;
165         }
166     }
167 
168     // need to allocate more space
169     std::unique_ptr<GrD3DCpuDescriptorManager::Heap> heap =
170             GrD3DCpuDescriptorManager::Heap::Make(gpu, fHeapType, fMaxAvailableDescriptors);
171     // TODO: handle failed heap creation and/or memory restrictions better
172     // skbug.com/11959
173     SkASSERT(heap);
174 
175     fDescriptorHeaps.push_back(std::move(heap));
176     fMaxAvailableDescriptors *= 2;
177     GrD3DDescriptorHeap::CPUHandle handle =
178             fDescriptorHeaps[fDescriptorHeaps.size() - 1]->allocateCPUHandle();
179     return handle;
180 }
181 
releaseHandle(const GrD3DDescriptorHeap::CPUHandle & dsvDescriptor)182 void GrD3DCpuDescriptorManager::HeapPool::releaseHandle(
183         const GrD3DDescriptorHeap::CPUHandle& dsvDescriptor) {
184     for (unsigned int i = 0; i < fDescriptorHeaps.size(); ++i) {
185         if (fDescriptorHeaps[i]->ownsHandle(dsvDescriptor)) {
186             fDescriptorHeaps[i]->freeCPUHandle(dsvDescriptor);
187             return;
188         }
189     }
190     SkASSERT(false);
191 }
192