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