blob: aaaab85d2416125720688d167caee8e4f1ad4dfb [file] [log] [blame]
Greg Daniel5fc5c812020-04-23 10:30:23 -04001/*
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/d3d/GrD3DPipelineStateBuilder.h"
11
12#include "include/gpu/GrContext.h"
13#include "include/gpu/d3d/GrD3DTypes.h"
14#include "src/core/SkTraceEvent.h"
15#include "src/gpu/GrAutoLocaleSetter.h"
16#include "src/gpu/GrContextPriv.h"
Brian Osmanb71b6ae2020-06-16 12:41:25 -040017#include "src/gpu/GrPersistentCacheUtils.h"
Greg Daniel5fc5c812020-04-23 10:30:23 -040018#include "src/gpu/GrShaderCaps.h"
19#include "src/gpu/GrShaderUtils.h"
20#include "src/gpu/GrStencilSettings.h"
21#include "src/gpu/d3d/GrD3DGpu.h"
22#include "src/gpu/d3d/GrD3DRenderTarget.h"
Greg Danielc31edc02020-04-23 11:03:02 -040023#include "src/gpu/d3d/GrD3DRootSignature.h"
Greg Daniel5fc5c812020-04-23 10:30:23 -040024#include "src/sksl/SkSLCompiler.h"
25
26#include <d3dcompiler.h>
27
Greg Danielb698ad32020-05-04 10:17:22 -040028sk_sp<GrD3DPipelineState> GrD3DPipelineStateBuilder::MakePipelineState(
Greg Daniel5fc5c812020-04-23 10:30:23 -040029 GrD3DGpu* gpu,
30 GrRenderTarget* renderTarget,
31 const GrProgramDesc& desc,
32 const GrProgramInfo& programInfo) {
33 // ensure that we use "." as a decimal separator when creating SkSL code
34 GrAutoLocaleSetter als("C");
35
36 // create a builder. This will be handed off to effects so they can use it to add
37 // uniforms, varyings, textures, etc
38 GrD3DPipelineStateBuilder builder(gpu, renderTarget, desc, programInfo);
39
40 if (!builder.emitAndInstallProcs()) {
41 return nullptr;
42 }
43
44 return builder.finalize();
45}
46
47GrD3DPipelineStateBuilder::GrD3DPipelineStateBuilder(GrD3DGpu* gpu,
48 GrRenderTarget* renderTarget,
49 const GrProgramDesc& desc,
50 const GrProgramInfo& programInfo)
51 : INHERITED(renderTarget, desc, programInfo)
52 , fGpu(gpu)
53 , fVaryingHandler(this)
54 , fUniformHandler(this) {}
55
56const GrCaps* GrD3DPipelineStateBuilder::caps() const {
57 return fGpu->caps();
58}
59
60void GrD3DPipelineStateBuilder::finalizeFragmentOutputColor(GrShaderVar& outputColor) {
61 outputColor.addLayoutQualifier("location = 0, index = 0");
62}
63
64void GrD3DPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outputColor) {
65 outputColor.addLayoutQualifier("location = 0, index = 1");
66}
67
Brian Osmanb71b6ae2020-06-16 12:41:25 -040068static gr_cp<ID3DBlob> GrCompileHLSLShader(GrD3DGpu* gpu,
69 const SkSL::String& hlsl,
70 SkSL::Program::Kind kind) {
Greg Daniel5fc5c812020-04-23 10:30:23 -040071 const char* compileTarget = nullptr;
72 switch (kind) {
73 case SkSL::Program::kVertex_Kind:
74 compileTarget = "vs_5_1";
75 break;
76 case SkSL::Program::kGeometry_Kind:
77 compileTarget = "gs_5_1";
78 break;
79 case SkSL::Program::kFragment_Kind:
80 compileTarget = "ps_5_1";
81 break;
82 default:
83 SkUNREACHABLE;
84 }
85
86 uint32_t compileFlags = 0;
87#ifdef SK_DEBUG
88 // Enable better shader debugging with the graphics debugging tools.
89 compileFlags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
90#endif
91 // SPRIV-cross does matrix multiplication expecting row major matrices
92 compileFlags |= D3DCOMPILE_PACK_MATRIX_ROW_MAJOR;
93
Brian Osmanb71b6ae2020-06-16 12:41:25 -040094 gr_cp<ID3DBlob> shader;
Greg Daniel5fc5c812020-04-23 10:30:23 -040095 gr_cp<ID3DBlob> errors;
Brian Osmanb71b6ae2020-06-16 12:41:25 -040096 HRESULT hr = D3DCompile(hlsl.c_str(), hlsl.length(), nullptr, nullptr, nullptr, "main",
97 compileTarget, compileFlags, 0, &shader, &errors);
Greg Daniel5fc5c812020-04-23 10:30:23 -040098 if (!SUCCEEDED(hr)) {
Brian Osmanb71b6ae2020-06-16 12:41:25 -040099 gpu->getContext()->priv().getShaderErrorHandler()->compileError(
100 hlsl.c_str(), reinterpret_cast<char*>(errors->GetBufferPointer()));
Greg Daniel5fc5c812020-04-23 10:30:23 -0400101 }
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400102 return shader;
103}
104
105bool GrD3DPipelineStateBuilder::loadHLSLFromCache(SkReadBuffer* reader, gr_cp<ID3DBlob> shaders[]) {
106
107 SkSL::String hlsl[kGrShaderTypeCount];
108 SkSL::Program::Inputs inputs[kGrShaderTypeCount];
109
110 if (!GrPersistentCacheUtils::UnpackCachedShaders(reader, hlsl, inputs, kGrShaderTypeCount)) {
111 return false;
112 }
113
114 auto compile = [&](SkSL::Program::Kind kind, GrShaderType shaderType) {
Greg Danielec3508a2020-06-16 14:23:35 -0400115 if (inputs[shaderType].fRTHeight) {
116 this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
117 }
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400118 shaders[shaderType] = GrCompileHLSLShader(fGpu, hlsl[shaderType], kind);
119 return shaders[shaderType].get();
120 };
121
122 return compile(SkSL::Program::kVertex_Kind, kVertex_GrShaderType) &&
123 compile(SkSL::Program::kFragment_Kind, kFragment_GrShaderType) &&
124 (hlsl[kGeometry_GrShaderType].empty() ||
125 compile(SkSL::Program::kGeometry_Kind, kGeometry_GrShaderType));
126}
127
128gr_cp<ID3DBlob> GrD3DPipelineStateBuilder::compileD3DProgram(
129 SkSL::Program::Kind kind,
130 const SkSL::String& sksl,
131 const SkSL::Program::Settings& settings,
132 SkSL::Program::Inputs* outInputs,
133 SkSL::String* outHLSL) {
134 auto errorHandler = fGpu->getContext()->priv().getShaderErrorHandler();
135 std::unique_ptr<SkSL::Program> program = fGpu->shaderCompiler()->convertProgram(
136 kind, sksl, settings);
137 if (!program) {
138 errorHandler->compileError(sksl.c_str(),
139 fGpu->shaderCompiler()->errorText().c_str());
140 return gr_cp<ID3DBlob>();
141 }
142 *outInputs = program->fInputs;
143 if (!fGpu->shaderCompiler()->toHLSL(*program, outHLSL)) {
144 errorHandler->compileError(sksl.c_str(),
145 fGpu->shaderCompiler()->errorText().c_str());
146 return gr_cp<ID3DBlob>();
147 }
148
Greg Danielec3508a2020-06-16 14:23:35 -0400149 if (program->fInputs.fRTHeight) {
150 this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
151 }
152
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400153 return GrCompileHLSLShader(fGpu, *outHLSL, kind);
Greg Daniel5fc5c812020-04-23 10:30:23 -0400154}
155
Jim Van Verthbe259dc2020-05-19 11:40:31 -0400156static DXGI_FORMAT attrib_type_to_format(GrVertexAttribType type) {
157 switch (type) {
158 case kFloat_GrVertexAttribType:
159 return DXGI_FORMAT_R32_FLOAT;
160 case kFloat2_GrVertexAttribType:
161 return DXGI_FORMAT_R32G32_FLOAT;
162 case kFloat3_GrVertexAttribType:
163 return DXGI_FORMAT_R32G32B32_FLOAT;
164 case kFloat4_GrVertexAttribType:
165 return DXGI_FORMAT_R32G32B32A32_FLOAT;
166 case kHalf_GrVertexAttribType:
167 return DXGI_FORMAT_R16_FLOAT;
168 case kHalf2_GrVertexAttribType:
169 return DXGI_FORMAT_R16G16_FLOAT;
170 case kHalf4_GrVertexAttribType:
171 return DXGI_FORMAT_R16G16B16A16_FLOAT;
172 case kInt2_GrVertexAttribType:
173 return DXGI_FORMAT_R32G32_SINT;
174 case kInt3_GrVertexAttribType:
175 return DXGI_FORMAT_R32G32B32_SINT;
176 case kInt4_GrVertexAttribType:
177 return DXGI_FORMAT_R32G32B32A32_SINT;
178 case kByte_GrVertexAttribType:
179 return DXGI_FORMAT_R8_SINT;
180 case kByte2_GrVertexAttribType:
181 return DXGI_FORMAT_R8G8_SINT;
182 case kByte4_GrVertexAttribType:
183 return DXGI_FORMAT_R8G8B8A8_SINT;
184 case kUByte_GrVertexAttribType:
185 return DXGI_FORMAT_R8_UINT;
186 case kUByte2_GrVertexAttribType:
187 return DXGI_FORMAT_R8G8_UINT;
188 case kUByte4_GrVertexAttribType:
189 return DXGI_FORMAT_R8G8B8A8_UINT;
190 case kUByte_norm_GrVertexAttribType:
191 return DXGI_FORMAT_R8_UNORM;
192 case kUByte4_norm_GrVertexAttribType:
193 return DXGI_FORMAT_R8G8B8A8_UNORM;
194 case kShort2_GrVertexAttribType:
195 return DXGI_FORMAT_R16G16_SINT;
196 case kShort4_GrVertexAttribType:
197 return DXGI_FORMAT_R16G16B16A16_SINT;
198 case kUShort2_GrVertexAttribType:
199 return DXGI_FORMAT_R16G16_UINT;
200 case kUShort2_norm_GrVertexAttribType:
201 return DXGI_FORMAT_R16G16_UNORM;
202 case kInt_GrVertexAttribType:
203 return DXGI_FORMAT_R32_SINT;
204 case kUint_GrVertexAttribType:
205 return DXGI_FORMAT_R32_UINT;
206 case kUShort_norm_GrVertexAttribType:
207 return DXGI_FORMAT_R16_UNORM;
208 case kUShort4_norm_GrVertexAttribType:
209 return DXGI_FORMAT_R16G16B16A16_UNORM;
210 }
211 SK_ABORT("Unknown vertex attrib type");
212}
213
214static void setup_vertex_input_layout(const GrPrimitiveProcessor& primProc,
215 D3D12_INPUT_ELEMENT_DESC* inputElements) {
216 unsigned int slotNumber = 0;
217 unsigned int vertexSlot = 0;
218 unsigned int instanceSlot = 0;
219 if (primProc.hasVertexAttributes()) {
220 vertexSlot = slotNumber++;
221 }
222 if (primProc.hasInstanceAttributes()) {
223 instanceSlot = slotNumber++;
224 }
225
226 unsigned int currentAttrib = 0;
227 unsigned int vertexAttributeOffset = 0;
228
229 for (const auto& attrib : primProc.vertexAttributes()) {
230 // When using SPIRV-Cross it converts the location modifier in SPIRV to be
231 // TEXCOORD<N> where N is the location value for eveery vertext attribute
232 inputElements[currentAttrib] = { "TEXCOORD", currentAttrib,
233 attrib_type_to_format(attrib.cpuType()),
234 vertexSlot, vertexAttributeOffset,
235 D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 };
236 vertexAttributeOffset += attrib.sizeAlign4();
237 currentAttrib++;
238 }
239 SkASSERT(vertexAttributeOffset == primProc.vertexStride());
240
241 unsigned int instanceAttributeOffset = 0;
242 for (const auto& attrib : primProc.instanceAttributes()) {
243 // When using SPIRV-Cross it converts the location modifier in SPIRV to be
244 // TEXCOORD<N> where N is the location value for eveery vertext attribute
245 inputElements[currentAttrib] = { "TEXCOORD", currentAttrib,
246 attrib_type_to_format(attrib.cpuType()),
247 instanceSlot, instanceAttributeOffset,
Greg Daniel5f196bb2020-06-16 13:21:23 -0400248 D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, 0 };
Jim Van Verthbe259dc2020-05-19 11:40:31 -0400249 instanceAttributeOffset += attrib.sizeAlign4();
250 currentAttrib++;
251 }
252 SkASSERT(instanceAttributeOffset == primProc.instanceStride());
253}
254
255static D3D12_BLEND blend_coeff_to_d3d_blend(GrBlendCoeff coeff) {
256 switch (coeff) {
257 case kZero_GrBlendCoeff:
258 return D3D12_BLEND_ZERO;
259 case kOne_GrBlendCoeff:
260 return D3D12_BLEND_ONE;
261 case kSC_GrBlendCoeff:
262 return D3D12_BLEND_SRC_COLOR;
263 case kISC_GrBlendCoeff:
264 return D3D12_BLEND_INV_SRC_COLOR;
265 case kDC_GrBlendCoeff:
266 return D3D12_BLEND_DEST_COLOR;
267 case kIDC_GrBlendCoeff:
268 return D3D12_BLEND_INV_DEST_COLOR;
269 case kSA_GrBlendCoeff:
270 return D3D12_BLEND_SRC_ALPHA;
271 case kISA_GrBlendCoeff:
272 return D3D12_BLEND_INV_SRC_ALPHA;
273 case kDA_GrBlendCoeff:
274 return D3D12_BLEND_DEST_ALPHA;
275 case kIDA_GrBlendCoeff:
276 return D3D12_BLEND_INV_DEST_ALPHA;
277 case kConstC_GrBlendCoeff:
278 return D3D12_BLEND_BLEND_FACTOR;
279 case kIConstC_GrBlendCoeff:
280 return D3D12_BLEND_INV_BLEND_FACTOR;
281 case kS2C_GrBlendCoeff:
282 return D3D12_BLEND_SRC1_COLOR;
283 case kIS2C_GrBlendCoeff:
284 return D3D12_BLEND_INV_SRC1_COLOR;
285 case kS2A_GrBlendCoeff:
286 return D3D12_BLEND_SRC1_ALPHA;
287 case kIS2A_GrBlendCoeff:
288 return D3D12_BLEND_INV_SRC1_ALPHA;
289 case kIllegal_GrBlendCoeff:
290 return D3D12_BLEND_ZERO;
291 }
292 SkUNREACHABLE;
293}
294
295static D3D12_BLEND blend_coeff_to_d3d_blend_for_alpha(GrBlendCoeff coeff) {
296 switch (coeff) {
297 // Force all srcColor used in alpha slot to alpha version.
298 case kSC_GrBlendCoeff:
299 return D3D12_BLEND_SRC_ALPHA;
300 case kISC_GrBlendCoeff:
301 return D3D12_BLEND_INV_SRC_ALPHA;
302 case kDC_GrBlendCoeff:
303 return D3D12_BLEND_DEST_ALPHA;
304 case kIDC_GrBlendCoeff:
305 return D3D12_BLEND_INV_DEST_ALPHA;
306 case kS2C_GrBlendCoeff:
307 return D3D12_BLEND_SRC1_ALPHA;
308 case kIS2C_GrBlendCoeff:
309 return D3D12_BLEND_INV_SRC1_ALPHA;
310
311 default:
312 return blend_coeff_to_d3d_blend(coeff);
313 }
314}
315
316
317static D3D12_BLEND_OP blend_equation_to_d3d_op(GrBlendEquation equation) {
318 switch (equation) {
319 case kAdd_GrBlendEquation:
320 return D3D12_BLEND_OP_ADD;
321 case kSubtract_GrBlendEquation:
322 return D3D12_BLEND_OP_SUBTRACT;
323 case kReverseSubtract_GrBlendEquation:
324 return D3D12_BLEND_OP_REV_SUBTRACT;
325 default:
326 SkUNREACHABLE;
327 }
328}
329
330static void fill_in_blend_state(const GrPipeline& pipeline, D3D12_BLEND_DESC* blendDesc) {
331 blendDesc->AlphaToCoverageEnable = false;
332 blendDesc->IndependentBlendEnable = false;
333
334 const GrXferProcessor::BlendInfo& blendInfo = pipeline.getXferProcessor().getBlendInfo();
335
336 GrBlendEquation equation = blendInfo.fEquation;
337 GrBlendCoeff srcCoeff = blendInfo.fSrcBlend;
338 GrBlendCoeff dstCoeff = blendInfo.fDstBlend;
339 bool blendOff = GrBlendShouldDisable(equation, srcCoeff, dstCoeff);
340
341 auto& rtBlend = blendDesc->RenderTarget[0];
342 rtBlend.BlendEnable = !blendOff;
343 if (!blendOff) {
344 rtBlend.SrcBlend = blend_coeff_to_d3d_blend(srcCoeff);
345 rtBlend.DestBlend = blend_coeff_to_d3d_blend(dstCoeff);
346 rtBlend.BlendOp = blend_equation_to_d3d_op(equation);
347 rtBlend.SrcBlendAlpha = blend_coeff_to_d3d_blend_for_alpha(srcCoeff);
348 rtBlend.DestBlendAlpha = blend_coeff_to_d3d_blend_for_alpha(dstCoeff);
349 rtBlend.BlendOpAlpha = blend_equation_to_d3d_op(equation);
350 }
351
352 if (!blendInfo.fWriteColor) {
353 rtBlend.RenderTargetWriteMask = 0;
354 } else {
355 rtBlend.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
356 }
357}
358
359static void fill_in_rasterizer_state(const GrPipeline& pipeline, const GrCaps* caps,
360 D3D12_RASTERIZER_DESC* rasterizer) {
361 rasterizer->FillMode = (caps->wireframeMode() || pipeline.isWireframe()) ?
362 D3D12_FILL_MODE_WIREFRAME : D3D12_FILL_MODE_SOLID;
363 rasterizer->CullMode = D3D12_CULL_MODE_NONE;
364 rasterizer->FrontCounterClockwise = true;
365 rasterizer->DepthBias = 0;
366 rasterizer->DepthBiasClamp = 0.0f;
367 rasterizer->SlopeScaledDepthBias = 0.0f;
368 rasterizer->DepthClipEnable = false;
369 rasterizer->MultisampleEnable = pipeline.isHWAntialiasState();
370 rasterizer->AntialiasedLineEnable = false;
371 rasterizer->ForcedSampleCount = 0;
372 rasterizer->ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
373}
374
375static D3D12_STENCIL_OP stencil_op_to_d3d_op(GrStencilOp op) {
376 switch (op) {
377 case GrStencilOp::kKeep:
378 return D3D12_STENCIL_OP_KEEP;
379 case GrStencilOp::kZero:
380 return D3D12_STENCIL_OP_ZERO;
381 case GrStencilOp::kReplace:
382 return D3D12_STENCIL_OP_REPLACE;
383 case GrStencilOp::kInvert:
384 return D3D12_STENCIL_OP_INVERT;
385 case GrStencilOp::kIncWrap:
386 return D3D12_STENCIL_OP_INCR;
387 case GrStencilOp::kDecWrap:
388 return D3D12_STENCIL_OP_DECR;
389 case GrStencilOp::kIncClamp:
390 return D3D12_STENCIL_OP_INCR_SAT;
391 case GrStencilOp::kDecClamp:
392 return D3D12_STENCIL_OP_DECR_SAT;
393 }
394 SkUNREACHABLE;
395}
396
397static D3D12_COMPARISON_FUNC stencil_test_to_d3d_func(GrStencilTest test) {
398 switch (test) {
399 case GrStencilTest::kAlways:
400 return D3D12_COMPARISON_FUNC_ALWAYS;
401 case GrStencilTest::kNever:
402 return D3D12_COMPARISON_FUNC_NEVER;
403 case GrStencilTest::kGreater:
404 return D3D12_COMPARISON_FUNC_GREATER;
405 case GrStencilTest::kGEqual:
406 return D3D12_COMPARISON_FUNC_GREATER_EQUAL;
407 case GrStencilTest::kLess:
408 return D3D12_COMPARISON_FUNC_LESS;
409 case GrStencilTest::kLEqual:
410 return D3D12_COMPARISON_FUNC_LESS_EQUAL;
411 case GrStencilTest::kEqual:
412 return D3D12_COMPARISON_FUNC_EQUAL;
413 case GrStencilTest::kNotEqual:
414 return D3D12_COMPARISON_FUNC_NOT_EQUAL;
415 }
416 SkUNREACHABLE;
417}
418
419static void setup_stencilop_desc(D3D12_DEPTH_STENCILOP_DESC* desc,
420 const GrStencilSettings::Face& stencilFace) {
421 desc->StencilFailOp = stencil_op_to_d3d_op(stencilFace.fFailOp);
422 desc->StencilDepthFailOp = desc->StencilFailOp;
423 desc->StencilPassOp = stencil_op_to_d3d_op(stencilFace.fPassOp);
424 desc->StencilFunc = stencil_test_to_d3d_func(stencilFace.fTest);
425}
426
427static void fill_in_depth_stencil_state(const GrProgramInfo& programInfo,
428 D3D12_DEPTH_STENCIL_DESC* dsDesc) {
429 GrStencilSettings stencilSettings = programInfo.nonGLStencilSettings();
430 GrSurfaceOrigin origin = programInfo.origin();
431
432 dsDesc->DepthEnable = false;
433 dsDesc->DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO;
434 dsDesc->DepthFunc = D3D12_COMPARISON_FUNC_NEVER;
435 dsDesc->StencilEnable = !stencilSettings.isDisabled();
436 if (!stencilSettings.isDisabled()) {
437 if (stencilSettings.isTwoSided()) {
438 const auto& frontFace = stencilSettings.postOriginCCWFace(origin);
Greg Daniel90cf5d42020-06-16 09:39:35 -0400439 const auto& backFace = stencilSettings.postOriginCWFace(origin);
Jim Van Verthbe259dc2020-05-19 11:40:31 -0400440
441 SkASSERT(frontFace.fTestMask == backFace.fTestMask);
442 SkASSERT(frontFace.fWriteMask == backFace.fWriteMask);
443 dsDesc->StencilReadMask = frontFace.fTestMask;
444 dsDesc->StencilWriteMask = frontFace.fWriteMask;
445
446 setup_stencilop_desc(&dsDesc->FrontFace, frontFace);
447 setup_stencilop_desc(&dsDesc->BackFace, backFace);
448 } else {
449 dsDesc->StencilReadMask = stencilSettings.singleSidedFace().fTestMask;
Greg Daniel90cf5d42020-06-16 09:39:35 -0400450 dsDesc->StencilWriteMask = stencilSettings.singleSidedFace().fWriteMask;
Jim Van Verthbe259dc2020-05-19 11:40:31 -0400451 setup_stencilop_desc(&dsDesc->FrontFace, stencilSettings.singleSidedFace());
452 dsDesc->BackFace = dsDesc->FrontFace;
453 }
454 }
455}
456
457static D3D12_PRIMITIVE_TOPOLOGY_TYPE gr_primitive_type_to_d3d(GrPrimitiveType primitiveType) {
458 switch (primitiveType) {
Jim Van Verth83ed9572020-05-21 11:53:55 -0400459 case GrPrimitiveType::kTriangles:
460 case GrPrimitiveType::kTriangleStrip: //fall through
461 return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
462 case GrPrimitiveType::kPoints:
463 return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
464 case GrPrimitiveType::kLines: // fall through
465 case GrPrimitiveType::kLineStrip:
466 return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
467 case GrPrimitiveType::kPatches: // fall through, unsupported
468 case GrPrimitiveType::kPath: // fall through, unsupported
469 default:
470 SkUNREACHABLE;
Jim Van Verthbe259dc2020-05-19 11:40:31 -0400471 }
472}
473
474gr_cp<ID3D12PipelineState> create_pipeline_state(
Jim Van Verth83ed9572020-05-21 11:53:55 -0400475 GrD3DGpu* gpu, const GrProgramInfo& programInfo, const sk_sp<GrD3DRootSignature>& rootSig,
Jim Van Verthbe259dc2020-05-19 11:40:31 -0400476 gr_cp<ID3DBlob> vertexShader, gr_cp<ID3DBlob> geometryShader, gr_cp<ID3DBlob> pixelShader,
477 DXGI_FORMAT renderTargetFormat, DXGI_FORMAT depthStencilFormat,
478 unsigned int sampleQualityLevel) {
479 D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
480
481 psoDesc.pRootSignature = rootSig->rootSignature();
482
483 psoDesc.VS = { reinterpret_cast<UINT8*>(vertexShader->GetBufferPointer()),
484 vertexShader->GetBufferSize() };
485 psoDesc.PS = { reinterpret_cast<UINT8*>(pixelShader->GetBufferPointer()),
486 pixelShader->GetBufferSize() };
487
488 if (geometryShader.get()) {
489 psoDesc.GS = { reinterpret_cast<UINT8*>(geometryShader->GetBufferPointer()),
490 geometryShader->GetBufferSize() };
491 }
492
493 psoDesc.StreamOutput = { nullptr, 0, nullptr, 0, 0 };
494
495 fill_in_blend_state(programInfo.pipeline(), &psoDesc.BlendState);
496 psoDesc.SampleMask = UINT_MAX;
497
498 fill_in_rasterizer_state(programInfo.pipeline(), gpu->caps(), &psoDesc.RasterizerState);
499
500 fill_in_depth_stencil_state(programInfo, &psoDesc.DepthStencilState);
501
502 unsigned int totalAttributeCnt = programInfo.primProc().numVertexAttributes() +
503 programInfo.primProc().numInstanceAttributes();
504 SkAutoSTArray<4, D3D12_INPUT_ELEMENT_DESC> inputElements(totalAttributeCnt);
505 setup_vertex_input_layout(programInfo.primProc(), inputElements.get());
506
507 psoDesc.InputLayout = { inputElements.get(), totalAttributeCnt };
508
509 psoDesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;
510
511 // This is for geometry or hull shader primitives
512 psoDesc.PrimitiveTopologyType = gr_primitive_type_to_d3d(programInfo.primitiveType());
513
514 psoDesc.NumRenderTargets = 1;
515
516 psoDesc.RTVFormats[0] = renderTargetFormat;
517
518 psoDesc.DSVFormat = depthStencilFormat;
519
520 unsigned int numRasterSamples = programInfo.numRasterSamples();
521 psoDesc.SampleDesc = { numRasterSamples, sampleQualityLevel };
522
523 // Only used for multi-adapter systems.
524 psoDesc.NodeMask = 0;
525
526 psoDesc.CachedPSO = { nullptr, 0 };
527 psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
528
529 gr_cp<ID3D12PipelineState> pipelineState;
530 SkDEBUGCODE(HRESULT hr = )gpu->device()->CreateGraphicsPipelineState(
531 &psoDesc, IID_PPV_ARGS(&pipelineState));
532 SkASSERT(SUCCEEDED(hr));
533
534 return pipelineState;
535}
536
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400537static constexpr SkFourByteTag kHLSL_Tag = SkSetFourByteTag('H', 'L', 'S', 'L');
538static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L');
539
Greg Danielfd776732020-04-23 12:51:13 -0400540sk_sp<GrD3DPipelineState> GrD3DPipelineStateBuilder::finalize() {
Greg Daniel5fc5c812020-04-23 10:30:23 -0400541 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
542
543 // We need to enable the following extensions so that the compiler can correctly make spir-v
544 // from our glsl shaders.
545 fVS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
546 fFS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
547 fVS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
548 fFS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
549
550 this->finalizeShaders();
551
552 SkSL::Program::Settings settings;
553 settings.fCaps = this->caps()->shaderCaps();
554 settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin;
555 settings.fSharpenTextures =
556 this->gpu()->getContext()->priv().options().fSharpenMipmappedTextures;
557 settings.fRTHeightOffset = fUniformHandler.getRTHeightOffset();
558 settings.fRTHeightBinding = 0;
559 settings.fRTHeightSet = 0;
560
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400561 sk_sp<SkData> cached;
562 SkReadBuffer reader;
563 SkFourByteTag shaderType = 0;
564 auto persistentCache = fGpu->getContext()->priv().getPersistentCache();
565 if (persistentCache) {
566 // Shear off the D3D-specific portion of the Desc to get the persistent key. We only cache
567 // shader code, not entire pipelines.
568 sk_sp<SkData> key =
569 SkData::MakeWithoutCopy(this->desc().asKey(), this->desc().initialKeyLength());
570 cached = persistentCache->load(*key);
571 if (cached) {
572 reader.setMemory(cached->data(), cached->size());
573 shaderType = GrPersistentCacheUtils::GetType(&reader);
574 }
Greg Daniel5fc5c812020-04-23 10:30:23 -0400575 }
576
Jim Van Verth40b4de22020-05-20 09:35:42 -0400577 const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400578 gr_cp<ID3DBlob> shaders[kGrShaderTypeCount];
579
580 if (kHLSL_Tag == shaderType && this->loadHLSLFromCache(&reader, shaders)) {
581 // We successfully loaded and compiled HLSL
582 } else {
583 SkSL::Program::Inputs inputs[kGrShaderTypeCount];
584 SkSL::String* sksl[kGrShaderTypeCount] = {
585 &fVS.fCompilerString,
586 &fGS.fCompilerString,
587 &fFS.fCompilerString,
588 };
589 SkSL::String cached_sksl[kGrShaderTypeCount];
590 SkSL::String hlsl[kGrShaderTypeCount];
591
592 if (kSKSL_Tag == shaderType) {
593 if (GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, inputs,
594 kGrShaderTypeCount)) {
595 for (int i = 0; i < kGrShaderTypeCount; ++i) {
596 sksl[i] = &cached_sksl[i];
597 }
598 }
599 }
600
601 auto compile = [&](SkSL::Program::Kind kind, GrShaderType shaderType) {
602 shaders[shaderType] = this->compileD3DProgram(kind, *sksl[shaderType], settings,
603 &inputs[shaderType], &hlsl[shaderType]);
604 return shaders[shaderType].get();
605 };
606
607 if (!compile(SkSL::Program::kVertex_Kind, kVertex_GrShaderType) ||
608 !compile(SkSL::Program::kFragment_Kind, kFragment_GrShaderType)) {
Greg Daniel5fc5c812020-04-23 10:30:23 -0400609 return nullptr;
610 }
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400611
612 if (primProc.willUseGeoShader()) {
613 if (!compile(SkSL::Program::kGeometry_Kind, kGeometry_GrShaderType)) {
614 return nullptr;
615 }
616 }
617
618 if (persistentCache && !cached) {
619 const bool cacheSkSL = fGpu->getContext()->priv().options().fShaderCacheStrategy ==
620 GrContextOptions::ShaderCacheStrategy::kSkSL;
621 if (cacheSkSL) {
622 // Replace the HLSL with formatted SkSL to be cached. This looks odd, but this is
623 // the last time we're going to use these strings, so it's safe.
624 for (int i = 0; i < kGrShaderTypeCount; ++i) {
625 hlsl[i] = GrShaderUtils::PrettyPrint(*sksl[i]);
626 }
627 }
628 sk_sp<SkData> key =
629 SkData::MakeWithoutCopy(this->desc().asKey(), this->desc().initialKeyLength());
630 sk_sp<SkData> data = GrPersistentCacheUtils::PackCachedShaders(
631 cacheSkSL ? kSKSL_Tag : kSKSL_Tag, hlsl, inputs, kGrShaderTypeCount);
632 persistentCache->store(*key, *data);
633 }
Greg Daniel5fc5c812020-04-23 10:30:23 -0400634 }
635
Greg Danielc31edc02020-04-23 11:03:02 -0400636 sk_sp<GrD3DRootSignature> rootSig =
637 fGpu->resourceProvider().findOrCreateRootSignature(fUniformHandler.fTextures.count());
638 if (!rootSig) {
639 return nullptr;
640 }
Greg Daniel5fc5c812020-04-23 10:30:23 -0400641
642 const GrD3DRenderTarget* rt = static_cast<const GrD3DRenderTarget*>(fRenderTarget);
Jim Van Verthbe259dc2020-05-19 11:40:31 -0400643 gr_cp<ID3D12PipelineState> pipelineState = create_pipeline_state(
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400644 fGpu, fProgramInfo, rootSig, std::move(shaders[kVertex_GrShaderType]),
645 std::move(shaders[kGeometry_GrShaderType]), std::move(shaders[kFragment_GrShaderType]),
646 rt->dxgiFormat(), rt->stencilDxgiFormat(), rt->sampleQualityLevel());
Jim Van Verthbe259dc2020-05-19 11:40:31 -0400647
648 return sk_sp<GrD3DPipelineState>(new GrD3DPipelineState(std::move(pipelineState),
Jim Van Verth83ed9572020-05-21 11:53:55 -0400649 std::move(rootSig),
Jim Van Verthbe259dc2020-05-19 11:40:31 -0400650 fUniformHandles,
651 fUniformHandler.fUniforms,
652 fUniformHandler.fCurrentUBOOffset,
Jim Van Verth40b4de22020-05-20 09:35:42 -0400653 fUniformHandler.fSamplers.count(),
Jim Van Verthbe259dc2020-05-19 11:40:31 -0400654 std::move(fGeometryProcessor),
655 std::move(fXferProcessor),
656 std::move(fFragmentProcessors),
Jim Van Verth40b4de22020-05-20 09:35:42 -0400657 fFragmentProcessorCnt,
658 primProc.vertexStride(),
659 primProc.instanceStride()));
Greg Daniel5fc5c812020-04-23 10:30:23 -0400660}