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