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