xref: /aosp_15_r20/external/skia/src/gpu/ganesh/d3d/GrD3DResourceProvider.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2020 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/d3d/GrD3DResourceProvider.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrContextOptions.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDirectContextPriv.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/d3d/GrD3DBuffer.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/d3d/GrD3DCommandList.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/d3d/GrD3DGpu.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/d3d/GrD3DPipelineState.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/d3d/GrD3DPipelineStateBuilder.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/d3d/GrD3DRenderTarget.h"
19*c8dee2aaSAndroid Build Coastguard Worker 
GrD3DResourceProvider(GrD3DGpu * gpu)20*c8dee2aaSAndroid Build Coastguard Worker GrD3DResourceProvider::GrD3DResourceProvider(GrD3DGpu* gpu)
21*c8dee2aaSAndroid Build Coastguard Worker         : fGpu(gpu)
22*c8dee2aaSAndroid Build Coastguard Worker         , fCpuDescriptorManager(gpu)
23*c8dee2aaSAndroid Build Coastguard Worker         , fDescriptorTableManager(gpu)
24*c8dee2aaSAndroid Build Coastguard Worker         , fPipelineStateCache(new PipelineStateCache(gpu))
25*c8dee2aaSAndroid Build Coastguard Worker         , fShaderResourceDescriptorTableCache(gpu)
26*c8dee2aaSAndroid Build Coastguard Worker         , fSamplerDescriptorTableCache(gpu) {
27*c8dee2aaSAndroid Build Coastguard Worker }
28*c8dee2aaSAndroid Build Coastguard Worker 
destroyResources()29*c8dee2aaSAndroid Build Coastguard Worker void GrD3DResourceProvider::destroyResources() {
30*c8dee2aaSAndroid Build Coastguard Worker     fSamplers.reset();
31*c8dee2aaSAndroid Build Coastguard Worker 
32*c8dee2aaSAndroid Build Coastguard Worker     fPipelineStateCache->release();
33*c8dee2aaSAndroid Build Coastguard Worker }
34*c8dee2aaSAndroid Build Coastguard Worker 
findOrCreateDirectCommandList()35*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<GrD3DDirectCommandList> GrD3DResourceProvider::findOrCreateDirectCommandList() {
36*c8dee2aaSAndroid Build Coastguard Worker     if (fAvailableDirectCommandLists.size()) {
37*c8dee2aaSAndroid Build Coastguard Worker         std::unique_ptr<GrD3DDirectCommandList> list =
38*c8dee2aaSAndroid Build Coastguard Worker                 std::move(fAvailableDirectCommandLists.back());
39*c8dee2aaSAndroid Build Coastguard Worker         fAvailableDirectCommandLists.pop_back();
40*c8dee2aaSAndroid Build Coastguard Worker         return list;
41*c8dee2aaSAndroid Build Coastguard Worker     }
42*c8dee2aaSAndroid Build Coastguard Worker     return GrD3DDirectCommandList::Make(fGpu);
43*c8dee2aaSAndroid Build Coastguard Worker }
44*c8dee2aaSAndroid Build Coastguard Worker 
recycleDirectCommandList(std::unique_ptr<GrD3DDirectCommandList> commandList)45*c8dee2aaSAndroid Build Coastguard Worker void GrD3DResourceProvider::recycleDirectCommandList(
46*c8dee2aaSAndroid Build Coastguard Worker         std::unique_ptr<GrD3DDirectCommandList> commandList) {
47*c8dee2aaSAndroid Build Coastguard Worker     commandList->reset();
48*c8dee2aaSAndroid Build Coastguard Worker     fAvailableDirectCommandLists.push_back(std::move(commandList));
49*c8dee2aaSAndroid Build Coastguard Worker }
50*c8dee2aaSAndroid Build Coastguard Worker 
findOrCreateRootSignature(int numTextureSamplers,int numUAVs)51*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrD3DRootSignature> GrD3DResourceProvider::findOrCreateRootSignature(int numTextureSamplers,
52*c8dee2aaSAndroid Build Coastguard Worker                                                                            int numUAVs) {
53*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < fRootSignatures.size(); ++i) {
54*c8dee2aaSAndroid Build Coastguard Worker         if (fRootSignatures[i]->isCompatible(numTextureSamplers, numUAVs)) {
55*c8dee2aaSAndroid Build Coastguard Worker             return fRootSignatures[i];
56*c8dee2aaSAndroid Build Coastguard Worker         }
57*c8dee2aaSAndroid Build Coastguard Worker     }
58*c8dee2aaSAndroid Build Coastguard Worker 
59*c8dee2aaSAndroid Build Coastguard Worker     auto rootSig = GrD3DRootSignature::Make(fGpu, numTextureSamplers, numUAVs);
60*c8dee2aaSAndroid Build Coastguard Worker     if (!rootSig) {
61*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
62*c8dee2aaSAndroid Build Coastguard Worker     }
63*c8dee2aaSAndroid Build Coastguard Worker     fRootSignatures.push_back(rootSig);
64*c8dee2aaSAndroid Build Coastguard Worker     return rootSig;
65*c8dee2aaSAndroid Build Coastguard Worker }
66*c8dee2aaSAndroid Build Coastguard Worker 
findOrCreateCommandSignature(GrD3DCommandSignature::ForIndexed indexed,unsigned int slot)67*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrD3DCommandSignature> GrD3DResourceProvider::findOrCreateCommandSignature(
68*c8dee2aaSAndroid Build Coastguard Worker         GrD3DCommandSignature::ForIndexed indexed, unsigned int slot) {
69*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < fCommandSignatures.size(); ++i) {
70*c8dee2aaSAndroid Build Coastguard Worker         if (fCommandSignatures[i]->isCompatible(indexed, slot)) {
71*c8dee2aaSAndroid Build Coastguard Worker             return fCommandSignatures[i];
72*c8dee2aaSAndroid Build Coastguard Worker         }
73*c8dee2aaSAndroid Build Coastguard Worker     }
74*c8dee2aaSAndroid Build Coastguard Worker 
75*c8dee2aaSAndroid Build Coastguard Worker     auto commandSig = GrD3DCommandSignature::Make(fGpu, indexed, slot);
76*c8dee2aaSAndroid Build Coastguard Worker     if (!commandSig) {
77*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
78*c8dee2aaSAndroid Build Coastguard Worker     }
79*c8dee2aaSAndroid Build Coastguard Worker     fCommandSignatures.push_back(commandSig);
80*c8dee2aaSAndroid Build Coastguard Worker     return commandSig;
81*c8dee2aaSAndroid Build Coastguard Worker }
82*c8dee2aaSAndroid Build Coastguard Worker 
createRenderTargetView(ID3D12Resource * textureResource)83*c8dee2aaSAndroid Build Coastguard Worker GrD3DDescriptorHeap::CPUHandle GrD3DResourceProvider::createRenderTargetView(
84*c8dee2aaSAndroid Build Coastguard Worker         ID3D12Resource* textureResource) {
85*c8dee2aaSAndroid Build Coastguard Worker     return fCpuDescriptorManager.createRenderTargetView(fGpu, textureResource);
86*c8dee2aaSAndroid Build Coastguard Worker }
87*c8dee2aaSAndroid Build Coastguard Worker 
recycleRenderTargetView(const GrD3DDescriptorHeap::CPUHandle & rtvDescriptor)88*c8dee2aaSAndroid Build Coastguard Worker void GrD3DResourceProvider::recycleRenderTargetView(
89*c8dee2aaSAndroid Build Coastguard Worker         const GrD3DDescriptorHeap::CPUHandle& rtvDescriptor) {
90*c8dee2aaSAndroid Build Coastguard Worker     fCpuDescriptorManager.recycleRenderTargetView(rtvDescriptor);
91*c8dee2aaSAndroid Build Coastguard Worker }
92*c8dee2aaSAndroid Build Coastguard Worker 
createDepthStencilView(ID3D12Resource * textureResource)93*c8dee2aaSAndroid Build Coastguard Worker GrD3DDescriptorHeap::CPUHandle GrD3DResourceProvider::createDepthStencilView(
94*c8dee2aaSAndroid Build Coastguard Worker         ID3D12Resource* textureResource) {
95*c8dee2aaSAndroid Build Coastguard Worker     return fCpuDescriptorManager.createDepthStencilView(fGpu, textureResource);
96*c8dee2aaSAndroid Build Coastguard Worker }
97*c8dee2aaSAndroid Build Coastguard Worker 
recycleDepthStencilView(const GrD3DDescriptorHeap::CPUHandle & dsvDescriptor)98*c8dee2aaSAndroid Build Coastguard Worker void GrD3DResourceProvider::recycleDepthStencilView(
99*c8dee2aaSAndroid Build Coastguard Worker         const GrD3DDescriptorHeap::CPUHandle& dsvDescriptor) {
100*c8dee2aaSAndroid Build Coastguard Worker     fCpuDescriptorManager.recycleDepthStencilView(dsvDescriptor);
101*c8dee2aaSAndroid Build Coastguard Worker }
102*c8dee2aaSAndroid Build Coastguard Worker 
createConstantBufferView(ID3D12Resource * bufferResource,size_t offset,size_t size)103*c8dee2aaSAndroid Build Coastguard Worker GrD3DDescriptorHeap::CPUHandle GrD3DResourceProvider::createConstantBufferView(
104*c8dee2aaSAndroid Build Coastguard Worker         ID3D12Resource* bufferResource, size_t offset, size_t size) {
105*c8dee2aaSAndroid Build Coastguard Worker     return fCpuDescriptorManager.createConstantBufferView(fGpu, bufferResource, offset, size);
106*c8dee2aaSAndroid Build Coastguard Worker }
107*c8dee2aaSAndroid Build Coastguard Worker 
createShaderResourceView(ID3D12Resource * resource,unsigned int highestMip,unsigned int mipLevels)108*c8dee2aaSAndroid Build Coastguard Worker GrD3DDescriptorHeap::CPUHandle GrD3DResourceProvider::createShaderResourceView(
109*c8dee2aaSAndroid Build Coastguard Worker         ID3D12Resource* resource, unsigned int highestMip, unsigned int mipLevels) {
110*c8dee2aaSAndroid Build Coastguard Worker     return fCpuDescriptorManager.createShaderResourceView(fGpu, resource, highestMip, mipLevels);
111*c8dee2aaSAndroid Build Coastguard Worker }
112*c8dee2aaSAndroid Build Coastguard Worker 
createUnorderedAccessView(ID3D12Resource * resource,unsigned int mipSlice)113*c8dee2aaSAndroid Build Coastguard Worker GrD3DDescriptorHeap::CPUHandle GrD3DResourceProvider::createUnorderedAccessView(
114*c8dee2aaSAndroid Build Coastguard Worker         ID3D12Resource* resource, unsigned int mipSlice) {
115*c8dee2aaSAndroid Build Coastguard Worker     return fCpuDescriptorManager.createUnorderedAccessView(fGpu, resource, mipSlice);
116*c8dee2aaSAndroid Build Coastguard Worker }
117*c8dee2aaSAndroid Build Coastguard Worker 
recycleShaderView(const GrD3DDescriptorHeap::CPUHandle & view)118*c8dee2aaSAndroid Build Coastguard Worker void GrD3DResourceProvider::recycleShaderView(
119*c8dee2aaSAndroid Build Coastguard Worker         const GrD3DDescriptorHeap::CPUHandle& view) {
120*c8dee2aaSAndroid Build Coastguard Worker     fCpuDescriptorManager.recycleShaderView(view);
121*c8dee2aaSAndroid Build Coastguard Worker }
122*c8dee2aaSAndroid Build Coastguard Worker 
wrap_mode_to_d3d_address_mode(GrSamplerState::WrapMode wrapMode)123*c8dee2aaSAndroid Build Coastguard Worker static D3D12_TEXTURE_ADDRESS_MODE wrap_mode_to_d3d_address_mode(GrSamplerState::WrapMode wrapMode) {
124*c8dee2aaSAndroid Build Coastguard Worker     switch (wrapMode) {
125*c8dee2aaSAndroid Build Coastguard Worker     case GrSamplerState::WrapMode::kClamp:
126*c8dee2aaSAndroid Build Coastguard Worker         return D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
127*c8dee2aaSAndroid Build Coastguard Worker     case GrSamplerState::WrapMode::kRepeat:
128*c8dee2aaSAndroid Build Coastguard Worker         return D3D12_TEXTURE_ADDRESS_MODE_WRAP;
129*c8dee2aaSAndroid Build Coastguard Worker     case GrSamplerState::WrapMode::kMirrorRepeat:
130*c8dee2aaSAndroid Build Coastguard Worker         return D3D12_TEXTURE_ADDRESS_MODE_MIRROR;
131*c8dee2aaSAndroid Build Coastguard Worker     case GrSamplerState::WrapMode::kClampToBorder:
132*c8dee2aaSAndroid Build Coastguard Worker         return D3D12_TEXTURE_ADDRESS_MODE_BORDER;
133*c8dee2aaSAndroid Build Coastguard Worker     }
134*c8dee2aaSAndroid Build Coastguard Worker     SK_ABORT("Unknown wrap mode.");
135*c8dee2aaSAndroid Build Coastguard Worker }
136*c8dee2aaSAndroid Build Coastguard Worker 
d3d_filter(GrSamplerState sampler)137*c8dee2aaSAndroid Build Coastguard Worker static D3D12_FILTER d3d_filter(GrSamplerState sampler) {
138*c8dee2aaSAndroid Build Coastguard Worker     if (sampler.isAniso()) {
139*c8dee2aaSAndroid Build Coastguard Worker         return D3D12_FILTER_ANISOTROPIC;
140*c8dee2aaSAndroid Build Coastguard Worker     }
141*c8dee2aaSAndroid Build Coastguard Worker     switch (sampler.mipmapMode()) {
142*c8dee2aaSAndroid Build Coastguard Worker         // When the mode is kNone we disable filtering using maxLOD.
143*c8dee2aaSAndroid Build Coastguard Worker         case GrSamplerState::MipmapMode::kNone:
144*c8dee2aaSAndroid Build Coastguard Worker         case GrSamplerState::MipmapMode::kNearest:
145*c8dee2aaSAndroid Build Coastguard Worker             switch (sampler.filter()) {
146*c8dee2aaSAndroid Build Coastguard Worker                 case GrSamplerState::Filter::kNearest: return D3D12_FILTER_MIN_MAG_MIP_POINT;
147*c8dee2aaSAndroid Build Coastguard Worker                 case GrSamplerState::Filter::kLinear:  return D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT;
148*c8dee2aaSAndroid Build Coastguard Worker             }
149*c8dee2aaSAndroid Build Coastguard Worker             SkUNREACHABLE;
150*c8dee2aaSAndroid Build Coastguard Worker         case GrSamplerState::MipmapMode::kLinear:
151*c8dee2aaSAndroid Build Coastguard Worker             switch (sampler.filter()) {
152*c8dee2aaSAndroid Build Coastguard Worker                 case GrSamplerState::Filter::kNearest: return D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR;
153*c8dee2aaSAndroid Build Coastguard Worker                 case GrSamplerState::Filter::kLinear:  return D3D12_FILTER_MIN_MAG_MIP_LINEAR;
154*c8dee2aaSAndroid Build Coastguard Worker             }
155*c8dee2aaSAndroid Build Coastguard Worker             SkUNREACHABLE;
156*c8dee2aaSAndroid Build Coastguard Worker     }
157*c8dee2aaSAndroid Build Coastguard Worker     SkUNREACHABLE;
158*c8dee2aaSAndroid Build Coastguard Worker }
159*c8dee2aaSAndroid Build Coastguard Worker 
findOrCreateCompatibleSampler(const GrSamplerState & params)160*c8dee2aaSAndroid Build Coastguard Worker D3D12_CPU_DESCRIPTOR_HANDLE GrD3DResourceProvider::findOrCreateCompatibleSampler(
161*c8dee2aaSAndroid Build Coastguard Worker         const GrSamplerState& params) {
162*c8dee2aaSAndroid Build Coastguard Worker     // In D3D anisotropic filtering uses the same field (D3D12_SAMPLER_DESC::Filter) as min/mag/mip
163*c8dee2aaSAndroid Build Coastguard Worker     // settings and so is not orthogonal to them.
164*c8dee2aaSAndroid Build Coastguard Worker     uint32_t key = params.asKey(/*anisoIsOrthogonal=*/false);
165*c8dee2aaSAndroid Build Coastguard Worker     D3D12_CPU_DESCRIPTOR_HANDLE* samplerPtr = fSamplers.find(key);
166*c8dee2aaSAndroid Build Coastguard Worker     if (samplerPtr) {
167*c8dee2aaSAndroid Build Coastguard Worker         return *samplerPtr;
168*c8dee2aaSAndroid Build Coastguard Worker     }
169*c8dee2aaSAndroid Build Coastguard Worker 
170*c8dee2aaSAndroid Build Coastguard Worker     D3D12_FILTER filter = d3d_filter(params);
171*c8dee2aaSAndroid Build Coastguard Worker     // We disable MIP filtering using maxLOD. Otherwise, we want the max LOD to be unbounded.
172*c8dee2aaSAndroid Build Coastguard Worker     float maxLOD =
173*c8dee2aaSAndroid Build Coastguard Worker             params.mipmapped() == skgpu::Mipmapped::kYes ? std::numeric_limits<float>::max() : 0.f;
174*c8dee2aaSAndroid Build Coastguard Worker     D3D12_TEXTURE_ADDRESS_MODE addressModeU = wrap_mode_to_d3d_address_mode(params.wrapModeX());
175*c8dee2aaSAndroid Build Coastguard Worker     D3D12_TEXTURE_ADDRESS_MODE addressModeV = wrap_mode_to_d3d_address_mode(params.wrapModeY());
176*c8dee2aaSAndroid Build Coastguard Worker     unsigned int maxAnisotropy = params.maxAniso();
177*c8dee2aaSAndroid Build Coastguard Worker     D3D12_CPU_DESCRIPTOR_HANDLE sampler =
178*c8dee2aaSAndroid Build Coastguard Worker             fCpuDescriptorManager.createSampler(
179*c8dee2aaSAndroid Build Coastguard Worker             fGpu, filter, maxLOD, maxAnisotropy, addressModeU, addressModeV).fHandle;
180*c8dee2aaSAndroid Build Coastguard Worker     fSamplers.set(key, sampler);
181*c8dee2aaSAndroid Build Coastguard Worker     return sampler;
182*c8dee2aaSAndroid Build Coastguard Worker }
183*c8dee2aaSAndroid Build Coastguard Worker 
findOrCreateShaderViewTable(const std::vector<D3D12_CPU_DESCRIPTOR_HANDLE> & shaderViews)184*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrD3DDescriptorTable> GrD3DResourceProvider::findOrCreateShaderViewTable(
185*c8dee2aaSAndroid Build Coastguard Worker     const std::vector<D3D12_CPU_DESCRIPTOR_HANDLE>& shaderViews) {
186*c8dee2aaSAndroid Build Coastguard Worker 
187*c8dee2aaSAndroid Build Coastguard Worker     auto createFunc = [this](GrD3DGpu* gpu, unsigned int numDesc) {
188*c8dee2aaSAndroid Build Coastguard Worker         return this->fDescriptorTableManager.createShaderViewTable(gpu, numDesc);
189*c8dee2aaSAndroid Build Coastguard Worker     };
190*c8dee2aaSAndroid Build Coastguard Worker     return fShaderResourceDescriptorTableCache.findOrCreateDescTable(shaderViews, createFunc);
191*c8dee2aaSAndroid Build Coastguard Worker }
192*c8dee2aaSAndroid Build Coastguard Worker 
findOrCreateSamplerTable(const std::vector<D3D12_CPU_DESCRIPTOR_HANDLE> & samplers)193*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrD3DDescriptorTable> GrD3DResourceProvider::findOrCreateSamplerTable(
194*c8dee2aaSAndroid Build Coastguard Worker         const std::vector<D3D12_CPU_DESCRIPTOR_HANDLE>& samplers) {
195*c8dee2aaSAndroid Build Coastguard Worker     auto createFunc = [this](GrD3DGpu* gpu, unsigned int numDesc) {
196*c8dee2aaSAndroid Build Coastguard Worker         return this->fDescriptorTableManager.createSamplerTable(gpu, numDesc);
197*c8dee2aaSAndroid Build Coastguard Worker     };
198*c8dee2aaSAndroid Build Coastguard Worker     return fShaderResourceDescriptorTableCache.findOrCreateDescTable(samplers, createFunc);
199*c8dee2aaSAndroid Build Coastguard Worker }
200*c8dee2aaSAndroid Build Coastguard Worker 
findOrCreateCompatiblePipelineState(GrD3DRenderTarget * rt,const GrProgramInfo & info)201*c8dee2aaSAndroid Build Coastguard Worker GrD3DPipelineState* GrD3DResourceProvider::findOrCreateCompatiblePipelineState(
202*c8dee2aaSAndroid Build Coastguard Worker         GrD3DRenderTarget* rt, const GrProgramInfo& info) {
203*c8dee2aaSAndroid Build Coastguard Worker     return fPipelineStateCache->refPipelineState(rt, info);
204*c8dee2aaSAndroid Build Coastguard Worker }
205*c8dee2aaSAndroid Build Coastguard Worker 
findOrCreateMipmapPipeline()206*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrD3DPipeline> GrD3DResourceProvider::findOrCreateMipmapPipeline() {
207*c8dee2aaSAndroid Build Coastguard Worker     if (!fMipmapPipeline) {
208*c8dee2aaSAndroid Build Coastguard Worker         // Note: filtering for non-even widths and heights samples at the 0.25 and 0.75
209*c8dee2aaSAndroid Build Coastguard Worker         // locations and averages the result. As the initial samples are bilerped this is
210*c8dee2aaSAndroid Build Coastguard Worker         // approximately a triangle filter. We should look into doing a better kernel but
211*c8dee2aaSAndroid Build Coastguard Worker         // this should hold us for now.
212*c8dee2aaSAndroid Build Coastguard Worker         const char* shader =
213*c8dee2aaSAndroid Build Coastguard Worker             "SamplerState textureSampler : register(s0, space1);\n"
214*c8dee2aaSAndroid Build Coastguard Worker             "Texture2D<float4> inputTexture : register(t1, space1);\n"
215*c8dee2aaSAndroid Build Coastguard Worker             "RWTexture2D<float4> outUAV : register(u2, space1);\n"
216*c8dee2aaSAndroid Build Coastguard Worker             "\n"
217*c8dee2aaSAndroid Build Coastguard Worker             "cbuffer UniformBuffer : register(b0, space0) {\n"
218*c8dee2aaSAndroid Build Coastguard Worker             "    float2 inverseDims;\n"
219*c8dee2aaSAndroid Build Coastguard Worker             "    uint mipLevel;\n"
220*c8dee2aaSAndroid Build Coastguard Worker             "    uint sampleMode;\n"
221*c8dee2aaSAndroid Build Coastguard Worker             "}\n"
222*c8dee2aaSAndroid Build Coastguard Worker             "\n"
223*c8dee2aaSAndroid Build Coastguard Worker             "[numthreads(8, 8, 1)]\n"
224*c8dee2aaSAndroid Build Coastguard Worker             "void main(uint groupIndex : SV_GroupIndex, uint3 threadID : SV_DispatchThreadID) {\n"
225*c8dee2aaSAndroid Build Coastguard Worker             "    float2 uv = inverseDims * (threadID.xy + 0.5);\n"
226*c8dee2aaSAndroid Build Coastguard Worker             "    float4 mipVal;\n"
227*c8dee2aaSAndroid Build Coastguard Worker             "    switch (sampleMode) {\n"
228*c8dee2aaSAndroid Build Coastguard Worker             "        case 0: {\n"
229*c8dee2aaSAndroid Build Coastguard Worker             "            mipVal = inputTexture.SampleLevel(textureSampler, uv, mipLevel);\n"
230*c8dee2aaSAndroid Build Coastguard Worker             "            break;\n"
231*c8dee2aaSAndroid Build Coastguard Worker             "        }\n"
232*c8dee2aaSAndroid Build Coastguard Worker             "        case 1: {\n"
233*c8dee2aaSAndroid Build Coastguard Worker             "            float2 uvdiff = inverseDims * 0.25;\n"
234*c8dee2aaSAndroid Build Coastguard Worker             "            mipVal = inputTexture.SampleLevel(textureSampler, uv-uvdiff, mipLevel);\n"
235*c8dee2aaSAndroid Build Coastguard Worker             "            mipVal += inputTexture.SampleLevel(textureSampler, uv+uvdiff, mipLevel);\n"
236*c8dee2aaSAndroid Build Coastguard Worker             "            uvdiff.y = -uvdiff.y;\n"
237*c8dee2aaSAndroid Build Coastguard Worker             "            mipVal += inputTexture.SampleLevel(textureSampler, uv-uvdiff, mipLevel);\n"
238*c8dee2aaSAndroid Build Coastguard Worker             "            mipVal += inputTexture.SampleLevel(textureSampler, uv+uvdiff, mipLevel);\n"
239*c8dee2aaSAndroid Build Coastguard Worker             "            mipVal *= 0.25;\n"
240*c8dee2aaSAndroid Build Coastguard Worker             "            break;\n"
241*c8dee2aaSAndroid Build Coastguard Worker             "        }\n"
242*c8dee2aaSAndroid Build Coastguard Worker             "        case 2: {\n"
243*c8dee2aaSAndroid Build Coastguard Worker             "            float2 uvdiff = float2(inverseDims.x * 0.25, 0);\n"
244*c8dee2aaSAndroid Build Coastguard Worker             "            mipVal = inputTexture.SampleLevel(textureSampler, uv-uvdiff, mipLevel);\n"
245*c8dee2aaSAndroid Build Coastguard Worker             "            mipVal += inputTexture.SampleLevel(textureSampler, uv+uvdiff, mipLevel);\n"
246*c8dee2aaSAndroid Build Coastguard Worker             "            mipVal *= 0.5;\n"
247*c8dee2aaSAndroid Build Coastguard Worker             "            break;\n"
248*c8dee2aaSAndroid Build Coastguard Worker             "        }\n"
249*c8dee2aaSAndroid Build Coastguard Worker             "        case 3: {\n"
250*c8dee2aaSAndroid Build Coastguard Worker             "            float2 uvdiff = float2(0, inverseDims.y * 0.25);\n"
251*c8dee2aaSAndroid Build Coastguard Worker             "            mipVal = inputTexture.SampleLevel(textureSampler, uv-uvdiff, mipLevel);\n"
252*c8dee2aaSAndroid Build Coastguard Worker             "            mipVal += inputTexture.SampleLevel(textureSampler, uv+uvdiff, mipLevel);\n"
253*c8dee2aaSAndroid Build Coastguard Worker             "            mipVal *= 0.5;\n"
254*c8dee2aaSAndroid Build Coastguard Worker             "            break;\n"
255*c8dee2aaSAndroid Build Coastguard Worker             "        }\n"
256*c8dee2aaSAndroid Build Coastguard Worker             "    }\n"
257*c8dee2aaSAndroid Build Coastguard Worker             "\n"
258*c8dee2aaSAndroid Build Coastguard Worker             "    outUAV[threadID.xy] = mipVal;\n"
259*c8dee2aaSAndroid Build Coastguard Worker             "}\n";
260*c8dee2aaSAndroid Build Coastguard Worker 
261*c8dee2aaSAndroid Build Coastguard Worker         sk_sp<GrD3DRootSignature> rootSig = this->findOrCreateRootSignature(1, 1);
262*c8dee2aaSAndroid Build Coastguard Worker 
263*c8dee2aaSAndroid Build Coastguard Worker         fMipmapPipeline =
264*c8dee2aaSAndroid Build Coastguard Worker                 GrD3DPipelineStateBuilder::MakeComputePipeline(fGpu, rootSig.get(), shader);
265*c8dee2aaSAndroid Build Coastguard Worker     }
266*c8dee2aaSAndroid Build Coastguard Worker 
267*c8dee2aaSAndroid Build Coastguard Worker     return fMipmapPipeline;
268*c8dee2aaSAndroid Build Coastguard Worker }
269*c8dee2aaSAndroid Build Coastguard Worker 
uploadConstantData(void * data,size_t size)270*c8dee2aaSAndroid Build Coastguard Worker D3D12_GPU_VIRTUAL_ADDRESS GrD3DResourceProvider::uploadConstantData(void* data, size_t size) {
271*c8dee2aaSAndroid Build Coastguard Worker     // constant size has to be aligned to 256
272*c8dee2aaSAndroid Build Coastguard Worker     constexpr int kConstantAlignment = 256;
273*c8dee2aaSAndroid Build Coastguard Worker 
274*c8dee2aaSAndroid Build Coastguard Worker     // upload the data
275*c8dee2aaSAndroid Build Coastguard Worker     size_t paddedSize = SkAlignTo(size, kConstantAlignment);
276*c8dee2aaSAndroid Build Coastguard Worker     GrRingBuffer::Slice slice = fGpu->uniformsRingBuffer()->suballocate(paddedSize);
277*c8dee2aaSAndroid Build Coastguard Worker     char* destPtr = static_cast<char*>(slice.fBuffer->map()) + slice.fOffset;
278*c8dee2aaSAndroid Build Coastguard Worker     memcpy(destPtr, data, size);
279*c8dee2aaSAndroid Build Coastguard Worker 
280*c8dee2aaSAndroid Build Coastguard Worker     // create the associated constant buffer view descriptor
281*c8dee2aaSAndroid Build Coastguard Worker     GrD3DBuffer* d3dBuffer = static_cast<GrD3DBuffer*>(slice.fBuffer);
282*c8dee2aaSAndroid Build Coastguard Worker     D3D12_GPU_VIRTUAL_ADDRESS gpuAddress = d3dBuffer->d3dResource()->GetGPUVirtualAddress();
283*c8dee2aaSAndroid Build Coastguard Worker     return gpuAddress + slice.fOffset;
284*c8dee2aaSAndroid Build Coastguard Worker }
285*c8dee2aaSAndroid Build Coastguard Worker 
prepForSubmit()286*c8dee2aaSAndroid Build Coastguard Worker void GrD3DResourceProvider::prepForSubmit() {
287*c8dee2aaSAndroid Build Coastguard Worker     fDescriptorTableManager.prepForSubmit(fGpu);
288*c8dee2aaSAndroid Build Coastguard Worker     // Any heap memory used for these will be returned when the command buffer finishes,
289*c8dee2aaSAndroid Build Coastguard Worker     // so we have to invalidate all entries.
290*c8dee2aaSAndroid Build Coastguard Worker     fShaderResourceDescriptorTableCache.release();
291*c8dee2aaSAndroid Build Coastguard Worker     fSamplerDescriptorTableCache.release();
292*c8dee2aaSAndroid Build Coastguard Worker }
293*c8dee2aaSAndroid Build Coastguard Worker 
294*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////////////////////
295*c8dee2aaSAndroid Build Coastguard Worker 
296*c8dee2aaSAndroid Build Coastguard Worker #ifdef GR_PIPELINE_STATE_CACHE_STATS
297*c8dee2aaSAndroid Build Coastguard Worker // Display pipeline state cache usage
298*c8dee2aaSAndroid Build Coastguard Worker static const bool c_DisplayMtlPipelineCache{false};
299*c8dee2aaSAndroid Build Coastguard Worker #endif
300*c8dee2aaSAndroid Build Coastguard Worker 
301*c8dee2aaSAndroid Build Coastguard Worker struct GrD3DResourceProvider::PipelineStateCache::Entry {
EntryGrD3DResourceProvider::PipelineStateCache::Entry302*c8dee2aaSAndroid Build Coastguard Worker     Entry(GrD3DGpu* gpu, std::unique_ptr<GrD3DPipelineState> pipelineState)
303*c8dee2aaSAndroid Build Coastguard Worker             : fGpu(gpu), fPipelineState(std::move(pipelineState)) {}
304*c8dee2aaSAndroid Build Coastguard Worker 
305*c8dee2aaSAndroid Build Coastguard Worker     GrD3DGpu* fGpu;
306*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<GrD3DPipelineState> fPipelineState;
307*c8dee2aaSAndroid Build Coastguard Worker };
308*c8dee2aaSAndroid Build Coastguard Worker 
PipelineStateCache(GrD3DGpu * gpu)309*c8dee2aaSAndroid Build Coastguard Worker GrD3DResourceProvider::PipelineStateCache::PipelineStateCache(GrD3DGpu* gpu)
310*c8dee2aaSAndroid Build Coastguard Worker         : fMap(gpu->getContext()->priv().options().fRuntimeProgramCacheSize)
311*c8dee2aaSAndroid Build Coastguard Worker         , fGpu(gpu)
312*c8dee2aaSAndroid Build Coastguard Worker #ifdef GR_PIPELINE_STATE_CACHE_STATS
313*c8dee2aaSAndroid Build Coastguard Worker         , fTotalRequests(0)
314*c8dee2aaSAndroid Build Coastguard Worker         , fCacheMisses(0)
315*c8dee2aaSAndroid Build Coastguard Worker #endif
316*c8dee2aaSAndroid Build Coastguard Worker {
317*c8dee2aaSAndroid Build Coastguard Worker }
318*c8dee2aaSAndroid Build Coastguard Worker 
~PipelineStateCache()319*c8dee2aaSAndroid Build Coastguard Worker GrD3DResourceProvider::PipelineStateCache::~PipelineStateCache() {
320*c8dee2aaSAndroid Build Coastguard Worker     // dump stats
321*c8dee2aaSAndroid Build Coastguard Worker #ifdef GR_PIPELINE_STATE_CACHE_STATS
322*c8dee2aaSAndroid Build Coastguard Worker     if (c_DisplayMtlPipelineCache) {
323*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("--- Pipeline State Cache ---\n");
324*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Total requests: %d\n", fTotalRequests);
325*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Cache misses: %d\n", fCacheMisses);
326*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Cache miss %%: %f\n",
327*c8dee2aaSAndroid Build Coastguard Worker                  (fTotalRequests > 0) ? 100.f * fCacheMisses / fTotalRequests : 0.f);
328*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("---------------------\n");
329*c8dee2aaSAndroid Build Coastguard Worker     }
330*c8dee2aaSAndroid Build Coastguard Worker #endif
331*c8dee2aaSAndroid Build Coastguard Worker }
332*c8dee2aaSAndroid Build Coastguard Worker 
release()333*c8dee2aaSAndroid Build Coastguard Worker void GrD3DResourceProvider::PipelineStateCache::release() {
334*c8dee2aaSAndroid Build Coastguard Worker     fMap.reset();
335*c8dee2aaSAndroid Build Coastguard Worker }
336*c8dee2aaSAndroid Build Coastguard Worker 
refPipelineState(GrD3DRenderTarget * renderTarget,const GrProgramInfo & programInfo)337*c8dee2aaSAndroid Build Coastguard Worker GrD3DPipelineState* GrD3DResourceProvider::PipelineStateCache::refPipelineState(
338*c8dee2aaSAndroid Build Coastguard Worker         GrD3DRenderTarget* renderTarget, const GrProgramInfo& programInfo) {
339*c8dee2aaSAndroid Build Coastguard Worker #ifdef GR_PIPELINE_STATE_CACHE_STATS
340*c8dee2aaSAndroid Build Coastguard Worker     ++fTotalRequests;
341*c8dee2aaSAndroid Build Coastguard Worker #endif
342*c8dee2aaSAndroid Build Coastguard Worker 
343*c8dee2aaSAndroid Build Coastguard Worker     const GrCaps* caps = fGpu->caps();
344*c8dee2aaSAndroid Build Coastguard Worker 
345*c8dee2aaSAndroid Build Coastguard Worker     GrProgramDesc desc = caps->makeDesc(renderTarget, programInfo);
346*c8dee2aaSAndroid Build Coastguard Worker     if (!desc.isValid()) {
347*c8dee2aaSAndroid Build Coastguard Worker         GrCapsDebugf(fGpu->caps(), "Failed to build mtl program descriptor!\n");
348*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
349*c8dee2aaSAndroid Build Coastguard Worker     }
350*c8dee2aaSAndroid Build Coastguard Worker 
351*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<Entry>* entry = fMap.find(desc);
352*c8dee2aaSAndroid Build Coastguard Worker     if (!entry) {
353*c8dee2aaSAndroid Build Coastguard Worker #ifdef GR_PIPELINE_STATE_CACHE_STATS
354*c8dee2aaSAndroid Build Coastguard Worker         ++fCacheMisses;
355*c8dee2aaSAndroid Build Coastguard Worker #endif
356*c8dee2aaSAndroid Build Coastguard Worker         std::unique_ptr<GrD3DPipelineState> pipelineState =
357*c8dee2aaSAndroid Build Coastguard Worker                 GrD3DPipelineStateBuilder::MakePipelineState(fGpu, renderTarget, desc, programInfo);
358*c8dee2aaSAndroid Build Coastguard Worker         if (!pipelineState) {
359*c8dee2aaSAndroid Build Coastguard Worker             return nullptr;
360*c8dee2aaSAndroid Build Coastguard Worker         }
361*c8dee2aaSAndroid Build Coastguard Worker         entry = fMap.insert(desc, std::unique_ptr<Entry>(
362*c8dee2aaSAndroid Build Coastguard Worker                 new Entry(fGpu, std::move(pipelineState))));
363*c8dee2aaSAndroid Build Coastguard Worker         return ((*entry)->fPipelineState).get();
364*c8dee2aaSAndroid Build Coastguard Worker     }
365*c8dee2aaSAndroid Build Coastguard Worker     return ((*entry)->fPipelineState).get();
366*c8dee2aaSAndroid Build Coastguard Worker }
367*c8dee2aaSAndroid Build Coastguard Worker 
markPipelineStateUniformsDirty()368*c8dee2aaSAndroid Build Coastguard Worker void GrD3DResourceProvider::PipelineStateCache::markPipelineStateUniformsDirty() {
369*c8dee2aaSAndroid Build Coastguard Worker     fMap.foreach ([](const GrProgramDesc*, std::unique_ptr<Entry>* entry) {
370*c8dee2aaSAndroid Build Coastguard Worker         (*entry)->fPipelineState->markUniformsDirty();
371*c8dee2aaSAndroid Build Coastguard Worker     });
372*c8dee2aaSAndroid Build Coastguard Worker }
373*c8dee2aaSAndroid Build Coastguard Worker 
374*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////////////////////
375*c8dee2aaSAndroid Build Coastguard Worker 
release()376*c8dee2aaSAndroid Build Coastguard Worker void GrD3DResourceProvider::DescriptorTableCache::release() {
377*c8dee2aaSAndroid Build Coastguard Worker     fMap.reset();
378*c8dee2aaSAndroid Build Coastguard Worker }
379*c8dee2aaSAndroid Build Coastguard Worker 
findOrCreateDescTable(const std::vector<D3D12_CPU_DESCRIPTOR_HANDLE> & cpuDescriptors,std::function<sk_sp<GrD3DDescriptorTable> (GrD3DGpu *,unsigned int numDesc)> createFunc)380*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrD3DDescriptorTable> GrD3DResourceProvider::DescriptorTableCache::findOrCreateDescTable(
381*c8dee2aaSAndroid Build Coastguard Worker         const std::vector<D3D12_CPU_DESCRIPTOR_HANDLE>& cpuDescriptors,
382*c8dee2aaSAndroid Build Coastguard Worker         std::function<sk_sp<GrD3DDescriptorTable>(GrD3DGpu*, unsigned int numDesc)> createFunc) {
383*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<GrD3DDescriptorTable>* entry = fMap.find(cpuDescriptors);
384*c8dee2aaSAndroid Build Coastguard Worker     if (entry) {
385*c8dee2aaSAndroid Build Coastguard Worker         return *entry;
386*c8dee2aaSAndroid Build Coastguard Worker     }
387*c8dee2aaSAndroid Build Coastguard Worker 
388*c8dee2aaSAndroid Build Coastguard Worker     unsigned int numDescriptors = cpuDescriptors.size();
389*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(numDescriptors <= kRangeSizesCount);
390*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<GrD3DDescriptorTable> descTable = createFunc(fGpu, numDescriptors);
391*c8dee2aaSAndroid Build Coastguard Worker     fGpu->device()->CopyDescriptors(1, descTable->baseCpuDescriptorPtr(), &numDescriptors,
392*c8dee2aaSAndroid Build Coastguard Worker                                     numDescriptors, cpuDescriptors.data(), fRangeSizes,
393*c8dee2aaSAndroid Build Coastguard Worker                                     descTable->type());
394*c8dee2aaSAndroid Build Coastguard Worker     entry = fMap.insert(cpuDescriptors, std::move(descTable));
395*c8dee2aaSAndroid Build Coastguard Worker     return *entry;
396*c8dee2aaSAndroid Build Coastguard Worker }
397