xref: /aosp_15_r20/external/skia/src/gpu/ganesh/d3d/GrD3DPipelineStateBuilder.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 <d3dcompiler.h>
9 
10 #include "src/gpu/ganesh/d3d/GrD3DPipelineStateBuilder.h"
11 
12 #include "include/gpu/ganesh/GrDirectContext.h"
13 #include "include/gpu/ganesh/d3d/GrD3DTypes.h"
14 #include "src/core/SkReadBuffer.h"
15 #include "src/core/SkTraceEvent.h"
16 #include "src/gpu/SkSLToBackend.h"
17 #include "src/gpu/ganesh/GrAutoLocaleSetter.h"
18 #include "src/gpu/ganesh/GrDirectContextPriv.h"
19 #include "src/gpu/ganesh/GrPersistentCacheUtils.h"
20 #include "src/gpu/ganesh/GrShaderCaps.h"
21 #include "src/gpu/ganesh/GrStencilSettings.h"
22 #include "src/gpu/ganesh/d3d/GrD3DGpu.h"
23 #include "src/gpu/ganesh/d3d/GrD3DPipeline.h"
24 #include "src/gpu/ganesh/d3d/GrD3DRenderTarget.h"
25 #include "src/gpu/ganesh/d3d/GrD3DRootSignature.h"
26 #include "src/gpu/ganesh/d3d/GrD3DUtil.h"
27 #include "src/sksl/SkSLCompiler.h"
28 #include "src/sksl/SkSLProgramKind.h"
29 #include "src/sksl/SkSLProgramSettings.h"
30 #include "src/utils/SkShaderUtils.h"
31 
32 #include <d3dcompiler.h>
33 
34 using namespace skia_private;
35 
MakePipelineState(GrD3DGpu * gpu,GrD3DRenderTarget * renderTarget,const GrProgramDesc & desc,const GrProgramInfo & programInfo)36 std::unique_ptr<GrD3DPipelineState> GrD3DPipelineStateBuilder::MakePipelineState(
37         GrD3DGpu* gpu,
38         GrD3DRenderTarget* renderTarget,
39         const GrProgramDesc& desc,
40         const GrProgramInfo& programInfo) {
41     // ensure that we use "." as a decimal separator when creating SkSL code
42     GrAutoLocaleSetter als("C");
43 
44     // create a builder.  This will be handed off to effects so they can use it to add
45     // uniforms, varyings, textures, etc
46     GrD3DPipelineStateBuilder builder(gpu, renderTarget, desc, programInfo);
47 
48     if (!builder.emitAndInstallProcs()) {
49         return nullptr;
50     }
51 
52     return builder.finalize();
53 }
54 
GrD3DPipelineStateBuilder(GrD3DGpu * gpu,GrD3DRenderTarget * renderTarget,const GrProgramDesc & desc,const GrProgramInfo & programInfo)55 GrD3DPipelineStateBuilder::GrD3DPipelineStateBuilder(GrD3DGpu* gpu,
56                                                      GrD3DRenderTarget* renderTarget,
57                                                      const GrProgramDesc& desc,
58                                                      const GrProgramInfo& programInfo)
59         : INHERITED(desc, programInfo)
60         , fGpu(gpu)
61         , fVaryingHandler(this)
62         , fUniformHandler(this)
63         , fRenderTarget(renderTarget) {}
64 
caps() const65 const GrCaps* GrD3DPipelineStateBuilder::caps() const {
66     return fGpu->caps();
67 }
68 
finalizeFragmentSecondaryColor(GrShaderVar & outputColor)69 void GrD3DPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outputColor) {
70     outputColor.addLayoutQualifier("location = 0, index = 1");
71 }
72 
GrCompileHLSLShader(GrD3DGpu * gpu,const std::string & hlsl,SkSL::ProgramKind kind)73 static gr_cp<ID3DBlob> GrCompileHLSLShader(GrD3DGpu* gpu,
74                                            const std::string& hlsl,
75                                            SkSL::ProgramKind kind) {
76     TRACE_EVENT0("skia.shaders", "driver_compile_shader");
77     const char* compileTarget = nullptr;
78     switch (kind) {
79         case SkSL::ProgramKind::kVertex:
80             compileTarget = "vs_5_1";
81             break;
82         case SkSL::ProgramKind::kFragment:
83             compileTarget = "ps_5_1";
84             break;
85         default:
86             SkUNREACHABLE;
87     }
88 
89     uint32_t compileFlags = 0;
90 #ifdef SK_DEBUG
91     // Enable better shader debugging with the graphics debugging tools.
92     compileFlags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
93 #endif
94     // SPRIV-cross does matrix multiplication expecting row major matrices
95     compileFlags |= D3DCOMPILE_PACK_MATRIX_ROW_MAJOR;
96 
97     gr_cp<ID3DBlob> shader;
98     gr_cp<ID3DBlob> errors;
99     HRESULT hr = D3DCompile(hlsl.c_str(), hlsl.length(), nullptr, nullptr, nullptr, "main",
100                             compileTarget, compileFlags, 0, &shader, &errors);
101     if (!SUCCEEDED(hr)) {
102         gpu->getContext()->priv().getShaderErrorHandler()->compileError(
103                 hlsl.c_str(), reinterpret_cast<char*>(errors->GetBufferPointer()));
104     }
105     return shader;
106 }
107 
loadHLSLFromCache(SkReadBuffer * reader,gr_cp<ID3DBlob> shaders[])108 bool GrD3DPipelineStateBuilder::loadHLSLFromCache(SkReadBuffer* reader, gr_cp<ID3DBlob> shaders[]) {
109 
110     std::string hlsl[kGrShaderTypeCount];
111     SkSL::Program::Interface intfs[kGrShaderTypeCount];
112 
113     if (!GrPersistentCacheUtils::UnpackCachedShaders(reader, hlsl, intfs, kGrShaderTypeCount)) {
114         return false;
115     }
116 
117     auto compile = [&](SkSL::ProgramKind kind, GrShaderType shaderType) {
118         if (intfs[shaderType].fRTFlipUniform != SkSL::Program::Interface::kRTFlip_None) {
119             this->addRTFlipUniform(SKSL_RTFLIP_NAME);
120         }
121         shaders[shaderType] = GrCompileHLSLShader(fGpu, hlsl[shaderType], kind);
122         return shaders[shaderType].get();
123     };
124 
125     return compile(SkSL::ProgramKind::kVertex, kVertex_GrShaderType) &&
126            compile(SkSL::ProgramKind::kFragment, kFragment_GrShaderType);
127 }
128 
compileD3DProgram(SkSL::ProgramKind kind,const std::string & sksl,const SkSL::ProgramSettings & settings,SkSL::Program::Interface * outInterface,std::string * outHLSL)129 gr_cp<ID3DBlob> GrD3DPipelineStateBuilder::compileD3DProgram(SkSL::ProgramKind kind,
130                                                              const std::string& sksl,
131                                                              const SkSL::ProgramSettings& settings,
132                                                              SkSL::Program::Interface* outInterface,
133                                                              std::string* outHLSL) {
134     if (!skgpu::SkSLToHLSL(this->caps()->shaderCaps(),
135                            sksl,
136                            kind,
137                            settings,
138                            outHLSL,
139                            outInterface,
140                            fGpu->getContext()->priv().getShaderErrorHandler())) {
141         return gr_cp<ID3DBlob>();
142     }
143 
144     if (outInterface->fRTFlipUniform != SkSL::Program::Interface::kRTFlip_None) {
145         this->addRTFlipUniform(SKSL_RTFLIP_NAME);
146     }
147 
148     return GrCompileHLSLShader(fGpu, *outHLSL, kind);
149 }
150 
attrib_type_to_format(GrVertexAttribType type)151 static DXGI_FORMAT attrib_type_to_format(GrVertexAttribType type) {
152     switch (type) {
153     case kFloat_GrVertexAttribType:
154         return DXGI_FORMAT_R32_FLOAT;
155     case kFloat2_GrVertexAttribType:
156         return DXGI_FORMAT_R32G32_FLOAT;
157     case kFloat3_GrVertexAttribType:
158         return DXGI_FORMAT_R32G32B32_FLOAT;
159     case kFloat4_GrVertexAttribType:
160         return DXGI_FORMAT_R32G32B32A32_FLOAT;
161     case kHalf_GrVertexAttribType:
162         return DXGI_FORMAT_R16_FLOAT;
163     case kHalf2_GrVertexAttribType:
164         return DXGI_FORMAT_R16G16_FLOAT;
165     case kHalf4_GrVertexAttribType:
166         return DXGI_FORMAT_R16G16B16A16_FLOAT;
167     case kInt2_GrVertexAttribType:
168         return DXGI_FORMAT_R32G32_SINT;
169     case kInt3_GrVertexAttribType:
170         return DXGI_FORMAT_R32G32B32_SINT;
171     case kInt4_GrVertexAttribType:
172         return DXGI_FORMAT_R32G32B32A32_SINT;
173     case kByte_GrVertexAttribType:
174         return DXGI_FORMAT_R8_SINT;
175     case kByte2_GrVertexAttribType:
176         return DXGI_FORMAT_R8G8_SINT;
177     case kByte4_GrVertexAttribType:
178         return DXGI_FORMAT_R8G8B8A8_SINT;
179     case kUByte_GrVertexAttribType:
180         return DXGI_FORMAT_R8_UINT;
181     case kUByte2_GrVertexAttribType:
182         return DXGI_FORMAT_R8G8_UINT;
183     case kUByte4_GrVertexAttribType:
184         return DXGI_FORMAT_R8G8B8A8_UINT;
185     case kUByte_norm_GrVertexAttribType:
186         return DXGI_FORMAT_R8_UNORM;
187     case kUByte4_norm_GrVertexAttribType:
188         return DXGI_FORMAT_R8G8B8A8_UNORM;
189     case kShort2_GrVertexAttribType:
190         return DXGI_FORMAT_R16G16_SINT;
191     case kShort4_GrVertexAttribType:
192         return DXGI_FORMAT_R16G16B16A16_SINT;
193     case kUShort2_GrVertexAttribType:
194         return DXGI_FORMAT_R16G16_UINT;
195     case kUShort2_norm_GrVertexAttribType:
196         return DXGI_FORMAT_R16G16_UNORM;
197     case kInt_GrVertexAttribType:
198         return DXGI_FORMAT_R32_SINT;
199     case kUInt_GrVertexAttribType:
200         return DXGI_FORMAT_R32_UINT;
201     case kUShort_norm_GrVertexAttribType:
202         return DXGI_FORMAT_R16_UNORM;
203     case kUShort4_norm_GrVertexAttribType:
204         return DXGI_FORMAT_R16G16B16A16_UNORM;
205     }
206     SK_ABORT("Unknown vertex attrib type");
207 }
208 
setup_vertex_input_layout(const GrGeometryProcessor & geomProc,D3D12_INPUT_ELEMENT_DESC * inputElements)209 static void setup_vertex_input_layout(const GrGeometryProcessor& geomProc,
210                                       D3D12_INPUT_ELEMENT_DESC* inputElements) {
211     unsigned int slotNumber = 0;
212     unsigned int vertexSlot = 0;
213     unsigned int instanceSlot = 0;
214     if (geomProc.hasVertexAttributes()) {
215         vertexSlot = slotNumber++;
216     }
217     if (geomProc.hasInstanceAttributes()) {
218         instanceSlot = slotNumber++;
219     }
220 
221     unsigned int currentAttrib = 0;
222 
223     for (auto attrib : geomProc.vertexAttributes()) {
224         // When using SPIRV-Cross it converts the location modifier in SPIRV to be
225         // TEXCOORD<N> where N is the location value for eveery vertext attribute
226         inputElements[currentAttrib] = { "TEXCOORD", currentAttrib,
227                                         attrib_type_to_format(attrib.cpuType()),
228                                         vertexSlot, SkToU32(*attrib.offset()),
229                                         D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 };
230         currentAttrib++;
231     }
232 
233     for (auto attrib : geomProc.instanceAttributes()) {
234         // When using SPIRV-Cross it converts the location modifier in SPIRV to be
235         // TEXCOORD<N> where N is the location value for eveery vertext attribute
236         inputElements[currentAttrib] = { "TEXCOORD", currentAttrib,
237                                         attrib_type_to_format(attrib.cpuType()),
238                                         instanceSlot, SkToU32(*attrib.offset()),
239                                         D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, 1 };
240         currentAttrib++;
241     }
242 }
243 
blend_coeff_to_d3d_blend(skgpu::BlendCoeff coeff)244 static D3D12_BLEND blend_coeff_to_d3d_blend(skgpu::BlendCoeff coeff) {
245     switch (coeff) {
246     case skgpu::BlendCoeff::kZero:
247         return D3D12_BLEND_ZERO;
248     case skgpu::BlendCoeff::kOne:
249         return D3D12_BLEND_ONE;
250     case skgpu::BlendCoeff::kSC:
251         return D3D12_BLEND_SRC_COLOR;
252     case skgpu::BlendCoeff::kISC:
253         return D3D12_BLEND_INV_SRC_COLOR;
254     case skgpu::BlendCoeff::kDC:
255         return D3D12_BLEND_DEST_COLOR;
256     case skgpu::BlendCoeff::kIDC:
257         return D3D12_BLEND_INV_DEST_COLOR;
258     case skgpu::BlendCoeff::kSA:
259         return D3D12_BLEND_SRC_ALPHA;
260     case skgpu::BlendCoeff::kISA:
261         return D3D12_BLEND_INV_SRC_ALPHA;
262     case skgpu::BlendCoeff::kDA:
263         return D3D12_BLEND_DEST_ALPHA;
264     case skgpu::BlendCoeff::kIDA:
265         return D3D12_BLEND_INV_DEST_ALPHA;
266     case skgpu::BlendCoeff::kConstC:
267         return D3D12_BLEND_BLEND_FACTOR;
268     case skgpu::BlendCoeff::kIConstC:
269         return D3D12_BLEND_INV_BLEND_FACTOR;
270     case skgpu::BlendCoeff::kS2C:
271         return D3D12_BLEND_SRC1_COLOR;
272     case skgpu::BlendCoeff::kIS2C:
273         return D3D12_BLEND_INV_SRC1_COLOR;
274     case skgpu::BlendCoeff::kS2A:
275         return D3D12_BLEND_SRC1_ALPHA;
276     case skgpu::BlendCoeff::kIS2A:
277         return D3D12_BLEND_INV_SRC1_ALPHA;
278     case skgpu::BlendCoeff::kIllegal:
279         return D3D12_BLEND_ZERO;
280     }
281     SkUNREACHABLE;
282 }
283 
blend_coeff_to_d3d_blend_for_alpha(skgpu::BlendCoeff coeff)284 static D3D12_BLEND blend_coeff_to_d3d_blend_for_alpha(skgpu::BlendCoeff coeff) {
285     switch (coeff) {
286         // Force all srcColor used in alpha slot to alpha version.
287     case skgpu::BlendCoeff::kSC:
288         return D3D12_BLEND_SRC_ALPHA;
289     case skgpu::BlendCoeff::kISC:
290         return D3D12_BLEND_INV_SRC_ALPHA;
291     case skgpu::BlendCoeff::kDC:
292         return D3D12_BLEND_DEST_ALPHA;
293     case skgpu::BlendCoeff::kIDC:
294         return D3D12_BLEND_INV_DEST_ALPHA;
295     case skgpu::BlendCoeff::kS2C:
296         return D3D12_BLEND_SRC1_ALPHA;
297     case skgpu::BlendCoeff::kIS2C:
298         return D3D12_BLEND_INV_SRC1_ALPHA;
299 
300     default:
301         return blend_coeff_to_d3d_blend(coeff);
302     }
303 }
304 
305 
blend_equation_to_d3d_op(skgpu::BlendEquation equation)306 static D3D12_BLEND_OP blend_equation_to_d3d_op(skgpu::BlendEquation equation) {
307     switch (equation) {
308     case skgpu::BlendEquation::kAdd:
309         return D3D12_BLEND_OP_ADD;
310     case skgpu::BlendEquation::kSubtract:
311         return D3D12_BLEND_OP_SUBTRACT;
312     case skgpu::BlendEquation::kReverseSubtract:
313         return D3D12_BLEND_OP_REV_SUBTRACT;
314     default:
315         SkUNREACHABLE;
316     }
317 }
318 
fill_in_blend_state(const GrPipeline & pipeline,D3D12_BLEND_DESC * blendDesc)319 static void fill_in_blend_state(const GrPipeline& pipeline, D3D12_BLEND_DESC* blendDesc) {
320     blendDesc->AlphaToCoverageEnable = false;
321     blendDesc->IndependentBlendEnable = false;
322 
323     const skgpu::BlendInfo& blendInfo = pipeline.getXferProcessor().getBlendInfo();
324 
325     skgpu::BlendEquation equation = blendInfo.fEquation;
326     skgpu::BlendCoeff srcCoeff = blendInfo.fSrcBlend;
327     skgpu::BlendCoeff dstCoeff = blendInfo.fDstBlend;
328     bool blendOff = skgpu::BlendShouldDisable(equation, srcCoeff, dstCoeff);
329 
330     auto& rtBlend = blendDesc->RenderTarget[0];
331     rtBlend.BlendEnable = !blendOff;
332     if (!blendOff) {
333         rtBlend.SrcBlend = blend_coeff_to_d3d_blend(srcCoeff);
334         rtBlend.DestBlend = blend_coeff_to_d3d_blend(dstCoeff);
335         rtBlend.BlendOp = blend_equation_to_d3d_op(equation);
336         rtBlend.SrcBlendAlpha = blend_coeff_to_d3d_blend_for_alpha(srcCoeff);
337         rtBlend.DestBlendAlpha = blend_coeff_to_d3d_blend_for_alpha(dstCoeff);
338         rtBlend.BlendOpAlpha = blend_equation_to_d3d_op(equation);
339     }
340 
341     if (!blendInfo.fWritesColor) {
342         rtBlend.RenderTargetWriteMask = 0;
343     } else {
344         rtBlend.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
345     }
346 }
347 
fill_in_rasterizer_state(const GrPipeline & pipeline,bool multisampleEnable,const GrCaps * caps,D3D12_RASTERIZER_DESC * rasterizer)348 static void fill_in_rasterizer_state(const GrPipeline& pipeline,
349                                      bool multisampleEnable,
350                                      const GrCaps* caps,
351                                      D3D12_RASTERIZER_DESC* rasterizer) {
352     rasterizer->FillMode = (caps->wireframeMode() || pipeline.isWireframe()) ?
353         D3D12_FILL_MODE_WIREFRAME : D3D12_FILL_MODE_SOLID;
354     rasterizer->CullMode = D3D12_CULL_MODE_NONE;
355     rasterizer->FrontCounterClockwise = true;
356     rasterizer->DepthBias = 0;
357     rasterizer->DepthBiasClamp = 0.0f;
358     rasterizer->SlopeScaledDepthBias = 0.0f;
359     rasterizer->DepthClipEnable = false;
360     rasterizer->MultisampleEnable = multisampleEnable;
361     rasterizer->AntialiasedLineEnable = false;
362     rasterizer->ForcedSampleCount = 0;
363     rasterizer->ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
364 }
365 
stencil_op_to_d3d_op(GrStencilOp op)366 static D3D12_STENCIL_OP stencil_op_to_d3d_op(GrStencilOp op) {
367     switch (op) {
368     case GrStencilOp::kKeep:
369         return D3D12_STENCIL_OP_KEEP;
370     case GrStencilOp::kZero:
371         return D3D12_STENCIL_OP_ZERO;
372     case GrStencilOp::kReplace:
373         return D3D12_STENCIL_OP_REPLACE;
374     case GrStencilOp::kInvert:
375         return D3D12_STENCIL_OP_INVERT;
376     case GrStencilOp::kIncWrap:
377         return D3D12_STENCIL_OP_INCR;
378     case GrStencilOp::kDecWrap:
379         return D3D12_STENCIL_OP_DECR;
380     case GrStencilOp::kIncClamp:
381         return D3D12_STENCIL_OP_INCR_SAT;
382     case GrStencilOp::kDecClamp:
383         return D3D12_STENCIL_OP_DECR_SAT;
384     }
385     SkUNREACHABLE;
386 }
387 
stencil_test_to_d3d_func(GrStencilTest test)388 static D3D12_COMPARISON_FUNC stencil_test_to_d3d_func(GrStencilTest test) {
389     switch (test) {
390     case GrStencilTest::kAlways:
391         return D3D12_COMPARISON_FUNC_ALWAYS;
392     case GrStencilTest::kNever:
393         return D3D12_COMPARISON_FUNC_NEVER;
394     case GrStencilTest::kGreater:
395         return D3D12_COMPARISON_FUNC_GREATER;
396     case GrStencilTest::kGEqual:
397         return D3D12_COMPARISON_FUNC_GREATER_EQUAL;
398     case GrStencilTest::kLess:
399         return D3D12_COMPARISON_FUNC_LESS;
400     case GrStencilTest::kLEqual:
401         return D3D12_COMPARISON_FUNC_LESS_EQUAL;
402     case GrStencilTest::kEqual:
403         return D3D12_COMPARISON_FUNC_EQUAL;
404     case GrStencilTest::kNotEqual:
405         return D3D12_COMPARISON_FUNC_NOT_EQUAL;
406     }
407     SkUNREACHABLE;
408 }
409 
setup_stencilop_desc(D3D12_DEPTH_STENCILOP_DESC * desc,const GrStencilSettings::Face & stencilFace)410 static void setup_stencilop_desc(D3D12_DEPTH_STENCILOP_DESC* desc,
411                                  const GrStencilSettings::Face& stencilFace) {
412     desc->StencilFailOp = stencil_op_to_d3d_op(stencilFace.fFailOp);
413     desc->StencilDepthFailOp = desc->StencilFailOp;
414     desc->StencilPassOp = stencil_op_to_d3d_op(stencilFace.fPassOp);
415     desc->StencilFunc = stencil_test_to_d3d_func(stencilFace.fTest);
416 }
417 
fill_in_depth_stencil_state(const GrProgramInfo & programInfo,D3D12_DEPTH_STENCIL_DESC * dsDesc)418 static void fill_in_depth_stencil_state(const GrProgramInfo& programInfo,
419                                         D3D12_DEPTH_STENCIL_DESC* dsDesc) {
420     GrStencilSettings stencilSettings = programInfo.nonGLStencilSettings();
421     GrSurfaceOrigin origin = programInfo.origin();
422 
423     dsDesc->DepthEnable = false;
424     dsDesc->DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO;
425     dsDesc->DepthFunc = D3D12_COMPARISON_FUNC_NEVER;
426     dsDesc->StencilEnable = !stencilSettings.isDisabled();
427     if (!stencilSettings.isDisabled()) {
428         if (stencilSettings.isTwoSided()) {
429             const auto& frontFace = stencilSettings.postOriginCCWFace(origin);
430             const auto& backFace = stencilSettings.postOriginCWFace(origin);
431 
432             SkASSERT(frontFace.fTestMask == backFace.fTestMask);
433             SkASSERT(frontFace.fWriteMask == backFace.fWriteMask);
434             dsDesc->StencilReadMask = frontFace.fTestMask;
435             dsDesc->StencilWriteMask = frontFace.fWriteMask;
436 
437             setup_stencilop_desc(&dsDesc->FrontFace, frontFace);
438             setup_stencilop_desc(&dsDesc->BackFace, backFace);
439         } else {
440             dsDesc->StencilReadMask = stencilSettings.singleSidedFace().fTestMask;
441             dsDesc->StencilWriteMask = stencilSettings.singleSidedFace().fWriteMask;
442             setup_stencilop_desc(&dsDesc->FrontFace, stencilSettings.singleSidedFace());
443             dsDesc->BackFace = dsDesc->FrontFace;
444         }
445     }
446 }
447 
gr_primitive_type_to_d3d(GrPrimitiveType primitiveType)448 static D3D12_PRIMITIVE_TOPOLOGY_TYPE gr_primitive_type_to_d3d(GrPrimitiveType primitiveType) {
449     switch (primitiveType) {
450         case GrPrimitiveType::kTriangles:
451         case GrPrimitiveType::kTriangleStrip: //fall through
452             return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
453         case GrPrimitiveType::kPoints:
454             return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
455         case GrPrimitiveType::kLines: // fall through
456         case GrPrimitiveType::kLineStrip:
457             return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
458         default:
459             SkUNREACHABLE;
460     }
461 }
462 
create_pipeline_state(GrD3DGpu * gpu,const GrProgramInfo & programInfo,const sk_sp<GrD3DRootSignature> & rootSig,gr_cp<ID3DBlob> vertexShader,gr_cp<ID3DBlob> pixelShader,DXGI_FORMAT renderTargetFormat,DXGI_FORMAT depthStencilFormat,unsigned int sampleQualityPattern)463 gr_cp<ID3D12PipelineState> create_pipeline_state(
464         GrD3DGpu* gpu, const GrProgramInfo& programInfo, const sk_sp<GrD3DRootSignature>& rootSig,
465         gr_cp<ID3DBlob> vertexShader, gr_cp<ID3DBlob> pixelShader,
466         DXGI_FORMAT renderTargetFormat, DXGI_FORMAT depthStencilFormat,
467         unsigned int sampleQualityPattern) {
468     D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
469 
470     psoDesc.pRootSignature = rootSig->rootSignature();
471 
472     psoDesc.VS = { reinterpret_cast<UINT8*>(vertexShader->GetBufferPointer()),
473                    vertexShader->GetBufferSize() };
474     psoDesc.PS = { reinterpret_cast<UINT8*>(pixelShader->GetBufferPointer()),
475                    pixelShader->GetBufferSize() };
476 
477     psoDesc.StreamOutput = { nullptr, 0, nullptr, 0, 0 };
478 
479     fill_in_blend_state(programInfo.pipeline(), &psoDesc.BlendState);
480     psoDesc.SampleMask = UINT_MAX;
481 
482     fill_in_rasterizer_state(programInfo.pipeline(), programInfo.numSamples() > 1, gpu->caps(),
483                              &psoDesc.RasterizerState);
484 
485     fill_in_depth_stencil_state(programInfo, &psoDesc.DepthStencilState);
486 
487     unsigned int totalAttributeCnt = programInfo.geomProc().numVertexAttributes() +
488                                      programInfo.geomProc().numInstanceAttributes();
489     AutoSTArray<4, D3D12_INPUT_ELEMENT_DESC> inputElements(totalAttributeCnt);
490     setup_vertex_input_layout(programInfo.geomProc(), inputElements.get());
491 
492     psoDesc.InputLayout = { inputElements.get(), totalAttributeCnt };
493 
494     psoDesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;
495 
496     // This is for geometry or hull shader primitives
497     psoDesc.PrimitiveTopologyType = gr_primitive_type_to_d3d(programInfo.primitiveType());
498 
499     psoDesc.NumRenderTargets = 1;
500 
501     psoDesc.RTVFormats[0] = renderTargetFormat;
502 
503     psoDesc.DSVFormat = depthStencilFormat;
504 
505     unsigned int numSamples = programInfo.numSamples();
506     psoDesc.SampleDesc = { numSamples, sampleQualityPattern };
507 
508     // Only used for multi-adapter systems.
509     psoDesc.NodeMask = 0;
510 
511     psoDesc.CachedPSO = { nullptr, 0 };
512     psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
513 
514     gr_cp<ID3D12PipelineState> pipelineState;
515     {
516         TRACE_EVENT0("skia.shaders", "CreateGraphicsPipelineState");
517         GR_D3D_CALL_ERRCHECK(
518                 gpu->device()->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&pipelineState)));
519     }
520 
521     return pipelineState;
522 }
523 
524 static constexpr SkFourByteTag kHLSL_Tag = SkSetFourByteTag('H', 'L', 'S', 'L');
525 static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L');
526 
finalize()527 std::unique_ptr<GrD3DPipelineState> GrD3DPipelineStateBuilder::finalize() {
528     TRACE_EVENT0("skia.shaders", TRACE_FUNC);
529 
530     this->finalizeShaders();
531 
532     SkSL::ProgramSettings settings;
533     settings.fSharpenTextures =
534         this->gpu()->getContext()->priv().options().fSharpenMipmappedTextures;
535     settings.fRTFlipOffset = fUniformHandler.getRTFlipOffset();
536     settings.fRTFlipBinding = 0;
537     settings.fRTFlipSet = 0;
538 
539     sk_sp<SkData> cached;
540     SkReadBuffer reader;
541     SkFourByteTag shaderType = 0;
542     auto persistentCache = fGpu->getContext()->priv().getPersistentCache();
543     if (persistentCache) {
544         // Shear off the D3D-specific portion of the Desc to get the persistent key. We only cache
545         // shader code, not entire pipelines.
546         sk_sp<SkData> key =
547                 SkData::MakeWithoutCopy(this->desc().asKey(), this->desc().initialKeyLength());
548         cached = persistentCache->load(*key);
549         if (cached) {
550             reader.setMemory(cached->data(), cached->size());
551             shaderType = GrPersistentCacheUtils::GetType(&reader);
552         }
553     }
554 
555     const GrGeometryProcessor& geomProc = this->geometryProcessor();
556     gr_cp<ID3DBlob> shaders[kGrShaderTypeCount];
557 
558     if (kHLSL_Tag == shaderType && this->loadHLSLFromCache(&reader, shaders)) {
559         // We successfully loaded and compiled HLSL
560     } else {
561         SkSL::Program::Interface intfs[kGrShaderTypeCount];
562         std::string* sksl[kGrShaderTypeCount] = {
563             &fVS.fCompilerString,
564             &fFS.fCompilerString,
565         };
566         std::string cached_sksl[kGrShaderTypeCount];
567         std::string hlsl[kGrShaderTypeCount];
568 
569         if (kSKSL_Tag == shaderType) {
570             if (GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, intfs,
571                                                             kGrShaderTypeCount)) {
572                 for (int i = 0; i < kGrShaderTypeCount; ++i) {
573                     sksl[i] = &cached_sksl[i];
574                 }
575             }
576         }
577 
578         auto compile = [&](SkSL::ProgramKind kind, GrShaderType shaderType) {
579             shaders[shaderType] = this->compileD3DProgram(
580                     kind, *sksl[shaderType], settings, &intfs[shaderType], &hlsl[shaderType]);
581             return shaders[shaderType].get();
582         };
583 
584         if (!compile(SkSL::ProgramKind::kVertex, kVertex_GrShaderType) ||
585             !compile(SkSL::ProgramKind::kFragment, kFragment_GrShaderType)) {
586             return nullptr;
587         }
588 
589         if (persistentCache && !cached) {
590             const bool cacheSkSL = fGpu->getContext()->priv().options().fShaderCacheStrategy ==
591                                    GrContextOptions::ShaderCacheStrategy::kSkSL;
592             if (cacheSkSL) {
593                 // Replace the HLSL with formatted SkSL to be cached. This looks odd, but this is
594                 // the last time we're going to use these strings, so it's safe.
595                 for (int i = 0; i < kGrShaderTypeCount; ++i) {
596                     hlsl[i] = SkShaderUtils::PrettyPrint(*sksl[i]);
597                 }
598             }
599             sk_sp<SkData> key =
600                     SkData::MakeWithoutCopy(this->desc().asKey(), this->desc().initialKeyLength());
601             SkString description = GrProgramDesc::Describe(fProgramInfo, *this->caps());
602             sk_sp<SkData> data = GrPersistentCacheUtils::PackCachedShaders(
603                     cacheSkSL ? kSKSL_Tag : kHLSL_Tag, hlsl, intfs, kGrShaderTypeCount);
604             persistentCache->store(*key, *data, description);
605         }
606     }
607 
608     sk_sp<GrD3DRootSignature> rootSig =
609             fGpu->resourceProvider().findOrCreateRootSignature(fUniformHandler.fSamplers.count());
610     if (!rootSig) {
611         return nullptr;
612     }
613 
614     const GrD3DRenderTarget* rt = static_cast<const GrD3DRenderTarget*>(fRenderTarget);
615     gr_cp<ID3D12PipelineState> pipelineState = create_pipeline_state(
616             fGpu, fProgramInfo, rootSig, std::move(shaders[kVertex_GrShaderType]),
617             std::move(shaders[kFragment_GrShaderType]),
618             rt->dxgiFormat(), rt->stencilDxgiFormat(), rt->sampleQualityPattern());
619     sk_sp<GrD3DPipeline> pipeline = GrD3DPipeline::Make(std::move(pipelineState));
620     if (!pipeline) {
621         return nullptr;
622     }
623 
624     return std::unique_ptr<GrD3DPipelineState>(
625             new GrD3DPipelineState(std::move(pipeline),
626                                    std::move(rootSig),
627                                    fUniformHandles,
628                                    fUniformHandler.fUniforms,
629                                    fUniformHandler.fCurrentUBOOffset,
630                                    fUniformHandler.fSamplers.count(),
631                                    std::move(fGPImpl),
632                                    std::move(fXPImpl),
633                                    std::move(fFPImpls),
634                                    geomProc.vertexStride(),
635                                    geomProc.instanceStride()));
636 }
637 
638 
MakeComputePipeline(GrD3DGpu * gpu,GrD3DRootSignature * rootSig,const char * shader)639 sk_sp<GrD3DPipeline> GrD3DPipelineStateBuilder::MakeComputePipeline(GrD3DGpu* gpu,
640                                                                     GrD3DRootSignature* rootSig,
641                                                                     const char* shader) {
642     D3D12_COMPUTE_PIPELINE_STATE_DESC psoDesc = {};
643     psoDesc.pRootSignature = rootSig->rootSignature();
644 
645     // compile shader
646     gr_cp<ID3DBlob> shaderBlob;
647     {
648         TRACE_EVENT0("skia.shaders", "driver_compile_shader");
649         uint32_t compileFlags = 0;
650 #ifdef SK_DEBUG
651         // Enable better shader debugging with the graphics debugging tools.
652         compileFlags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
653 #endif
654 
655         gr_cp<ID3DBlob> errors;
656         HRESULT hr = D3DCompile(shader, strlen(shader), nullptr, nullptr, nullptr, "main",
657                                 "cs_5_1", compileFlags, 0, &shaderBlob, &errors);
658         if (!SUCCEEDED(hr)) {
659             gpu->getContext()->priv().getShaderErrorHandler()->compileError(
660                 shader, reinterpret_cast<char*>(errors->GetBufferPointer()));
661             return nullptr;
662         }
663         psoDesc.CS = { reinterpret_cast<UINT8*>(shaderBlob->GetBufferPointer()),
664                        shaderBlob->GetBufferSize() };
665     }
666 
667     // Only used for multi-adapter systems.
668     psoDesc.NodeMask = 0;
669 
670     psoDesc.CachedPSO = { nullptr, 0 };
671     psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
672 
673     gr_cp<ID3D12PipelineState> pipelineState;
674     {
675         TRACE_EVENT0("skia.shaders", "CreateComputePipelineState");
676         GR_D3D_CALL_ERRCHECK(
677             gpu->device()->CreateComputePipelineState(&psoDesc, IID_PPV_ARGS(&pipelineState)));
678     }
679 
680     return GrD3DPipeline::Make(std::move(pipelineState));
681 }
682