blob: 03616735b4fc438def395560a7c36ca0b579004e [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
Adlai Holler3d0359a2020-07-09 15:35:55 -040012#include "include/gpu/GrDirectContext.h"
Greg Daniel5fc5c812020-04-23 10:30:23 -040013#include "include/gpu/d3d/GrD3DTypes.h"
14#include "src/core/SkTraceEvent.h"
15#include "src/gpu/GrAutoLocaleSetter.h"
Adlai Hollera0693042020-10-14 11:23:11 -040016#include "src/gpu/GrDirectContextPriv.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
Ethan Nicholasee9cb6a2021-02-02 11:59:09 -050061SkSL::Compiler* GrD3DPipelineStateBuilder::shaderCompiler() const {
62 return fGpu->shaderCompiler();
63}
64
Greg Daniel5fc5c812020-04-23 10:30:23 -040065void GrD3DPipelineStateBuilder::finalizeFragmentOutputColor(GrShaderVar& outputColor) {
66 outputColor.addLayoutQualifier("location = 0, index = 0");
67}
68
69void GrD3DPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outputColor) {
70 outputColor.addLayoutQualifier("location = 0, index = 1");
71}
72
Jim Van Verth5fba9ae2020-09-21 17:18:04 -040073static gr_cp<ID3DBlob> GrCompileHLSLShader(GrD3DGpu* gpu,
Brian Osmanb71b6ae2020-06-16 12:41:25 -040074 const SkSL::String& hlsl,
John Stilesdbd4e6f2021-02-16 13:29:15 -050075 SkSL::ProgramKind kind) {
Greg Daniel5fc5c812020-04-23 10:30:23 -040076 const char* compileTarget = nullptr;
77 switch (kind) {
John Stilesdbd4e6f2021-02-16 13:29:15 -050078 case SkSL::ProgramKind::kVertex:
Greg Daniel5fc5c812020-04-23 10:30:23 -040079 compileTarget = "vs_5_1";
80 break;
John Stilesdbd4e6f2021-02-16 13:29:15 -050081 case SkSL::ProgramKind::kGeometry:
Greg Daniel5fc5c812020-04-23 10:30:23 -040082 compileTarget = "gs_5_1";
83 break;
John Stilesdbd4e6f2021-02-16 13:29:15 -050084 case SkSL::ProgramKind::kFragment:
Greg Daniel5fc5c812020-04-23 10:30:23 -040085 compileTarget = "ps_5_1";
86 break;
87 default:
88 SkUNREACHABLE;
89 }
90
91 uint32_t compileFlags = 0;
92#ifdef SK_DEBUG
93 // Enable better shader debugging with the graphics debugging tools.
94 compileFlags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
95#endif
96 // SPRIV-cross does matrix multiplication expecting row major matrices
97 compileFlags |= D3DCOMPILE_PACK_MATRIX_ROW_MAJOR;
98
Jim Van Verth5fba9ae2020-09-21 17:18:04 -040099 gr_cp<ID3DBlob> shader;
100 gr_cp<ID3DBlob> errors;
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400101 HRESULT hr = D3DCompile(hlsl.c_str(), hlsl.length(), nullptr, nullptr, nullptr, "main",
102 compileTarget, compileFlags, 0, &shader, &errors);
Greg Daniel5fc5c812020-04-23 10:30:23 -0400103 if (!SUCCEEDED(hr)) {
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400104 gpu->getContext()->priv().getShaderErrorHandler()->compileError(
105 hlsl.c_str(), reinterpret_cast<char*>(errors->GetBufferPointer()));
Greg Daniel5fc5c812020-04-23 10:30:23 -0400106 }
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400107 return shader;
108}
109
Jim Van Verth5fba9ae2020-09-21 17:18:04 -0400110bool GrD3DPipelineStateBuilder::loadHLSLFromCache(SkReadBuffer* reader, gr_cp<ID3DBlob> shaders[]) {
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400111
112 SkSL::String hlsl[kGrShaderTypeCount];
113 SkSL::Program::Inputs inputs[kGrShaderTypeCount];
114
115 if (!GrPersistentCacheUtils::UnpackCachedShaders(reader, hlsl, inputs, kGrShaderTypeCount)) {
116 return false;
117 }
118
John Stilesdbd4e6f2021-02-16 13:29:15 -0500119 auto compile = [&](SkSL::ProgramKind kind, GrShaderType shaderType) {
Greg Danielec3508a2020-06-16 14:23:35 -0400120 if (inputs[shaderType].fRTHeight) {
121 this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
122 }
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400123 shaders[shaderType] = GrCompileHLSLShader(fGpu, hlsl[shaderType], kind);
Jim Van Verth5fba9ae2020-09-21 17:18:04 -0400124 return shaders[shaderType].get();
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400125 };
126
John Stilesdbd4e6f2021-02-16 13:29:15 -0500127 return compile(SkSL::ProgramKind::kVertex, kVertex_GrShaderType) &&
128 compile(SkSL::ProgramKind::kFragment, kFragment_GrShaderType) &&
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400129 (hlsl[kGeometry_GrShaderType].empty() ||
John Stilesdbd4e6f2021-02-16 13:29:15 -0500130 compile(SkSL::ProgramKind::kGeometry, kGeometry_GrShaderType));
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400131}
132
Jim Van Verth5fba9ae2020-09-21 17:18:04 -0400133gr_cp<ID3DBlob> GrD3DPipelineStateBuilder::compileD3DProgram(
John Stilesdbd4e6f2021-02-16 13:29:15 -0500134 SkSL::ProgramKind kind,
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400135 const SkSL::String& sksl,
136 const SkSL::Program::Settings& settings,
137 SkSL::Program::Inputs* outInputs,
138 SkSL::String* outHLSL) {
139 auto errorHandler = fGpu->getContext()->priv().getShaderErrorHandler();
140 std::unique_ptr<SkSL::Program> program = fGpu->shaderCompiler()->convertProgram(
141 kind, sksl, settings);
142 if (!program) {
143 errorHandler->compileError(sksl.c_str(),
144 fGpu->shaderCompiler()->errorText().c_str());
Jim Van Verth5fba9ae2020-09-21 17:18:04 -0400145 return gr_cp<ID3DBlob>();
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400146 }
147 *outInputs = program->fInputs;
148 if (!fGpu->shaderCompiler()->toHLSL(*program, outHLSL)) {
149 errorHandler->compileError(sksl.c_str(),
150 fGpu->shaderCompiler()->errorText().c_str());
Jim Van Verth5fba9ae2020-09-21 17:18:04 -0400151 return gr_cp<ID3DBlob>();
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400152 }
153
Greg Danielec3508a2020-06-16 14:23:35 -0400154 if (program->fInputs.fRTHeight) {
155 this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
156 }
157
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400158 return GrCompileHLSLShader(fGpu, *outHLSL, kind);
Greg Daniel5fc5c812020-04-23 10:30:23 -0400159}
160
Jim Van Verthbe259dc2020-05-19 11:40:31 -0400161static DXGI_FORMAT attrib_type_to_format(GrVertexAttribType type) {
162 switch (type) {
163 case kFloat_GrVertexAttribType:
164 return DXGI_FORMAT_R32_FLOAT;
165 case kFloat2_GrVertexAttribType:
166 return DXGI_FORMAT_R32G32_FLOAT;
167 case kFloat3_GrVertexAttribType:
168 return DXGI_FORMAT_R32G32B32_FLOAT;
169 case kFloat4_GrVertexAttribType:
170 return DXGI_FORMAT_R32G32B32A32_FLOAT;
171 case kHalf_GrVertexAttribType:
172 return DXGI_FORMAT_R16_FLOAT;
173 case kHalf2_GrVertexAttribType:
174 return DXGI_FORMAT_R16G16_FLOAT;
175 case kHalf4_GrVertexAttribType:
176 return DXGI_FORMAT_R16G16B16A16_FLOAT;
177 case kInt2_GrVertexAttribType:
178 return DXGI_FORMAT_R32G32_SINT;
179 case kInt3_GrVertexAttribType:
180 return DXGI_FORMAT_R32G32B32_SINT;
181 case kInt4_GrVertexAttribType:
182 return DXGI_FORMAT_R32G32B32A32_SINT;
183 case kByte_GrVertexAttribType:
184 return DXGI_FORMAT_R8_SINT;
185 case kByte2_GrVertexAttribType:
186 return DXGI_FORMAT_R8G8_SINT;
187 case kByte4_GrVertexAttribType:
188 return DXGI_FORMAT_R8G8B8A8_SINT;
189 case kUByte_GrVertexAttribType:
190 return DXGI_FORMAT_R8_UINT;
191 case kUByte2_GrVertexAttribType:
192 return DXGI_FORMAT_R8G8_UINT;
193 case kUByte4_GrVertexAttribType:
194 return DXGI_FORMAT_R8G8B8A8_UINT;
195 case kUByte_norm_GrVertexAttribType:
196 return DXGI_FORMAT_R8_UNORM;
197 case kUByte4_norm_GrVertexAttribType:
198 return DXGI_FORMAT_R8G8B8A8_UNORM;
199 case kShort2_GrVertexAttribType:
200 return DXGI_FORMAT_R16G16_SINT;
201 case kShort4_GrVertexAttribType:
202 return DXGI_FORMAT_R16G16B16A16_SINT;
203 case kUShort2_GrVertexAttribType:
204 return DXGI_FORMAT_R16G16_UINT;
205 case kUShort2_norm_GrVertexAttribType:
206 return DXGI_FORMAT_R16G16_UNORM;
207 case kInt_GrVertexAttribType:
208 return DXGI_FORMAT_R32_SINT;
209 case kUint_GrVertexAttribType:
210 return DXGI_FORMAT_R32_UINT;
211 case kUShort_norm_GrVertexAttribType:
212 return DXGI_FORMAT_R16_UNORM;
213 case kUShort4_norm_GrVertexAttribType:
214 return DXGI_FORMAT_R16G16B16A16_UNORM;
215 }
216 SK_ABORT("Unknown vertex attrib type");
217}
218
219static void setup_vertex_input_layout(const GrPrimitiveProcessor& primProc,
220 D3D12_INPUT_ELEMENT_DESC* inputElements) {
221 unsigned int slotNumber = 0;
222 unsigned int vertexSlot = 0;
223 unsigned int instanceSlot = 0;
224 if (primProc.hasVertexAttributes()) {
225 vertexSlot = slotNumber++;
226 }
227 if (primProc.hasInstanceAttributes()) {
228 instanceSlot = slotNumber++;
229 }
230
231 unsigned int currentAttrib = 0;
232 unsigned int vertexAttributeOffset = 0;
233
234 for (const auto& attrib : primProc.vertexAttributes()) {
235 // When using SPIRV-Cross it converts the location modifier in SPIRV to be
236 // TEXCOORD<N> where N is the location value for eveery vertext attribute
237 inputElements[currentAttrib] = { "TEXCOORD", currentAttrib,
238 attrib_type_to_format(attrib.cpuType()),
239 vertexSlot, vertexAttributeOffset,
240 D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 };
241 vertexAttributeOffset += attrib.sizeAlign4();
242 currentAttrib++;
243 }
244 SkASSERT(vertexAttributeOffset == primProc.vertexStride());
245
246 unsigned int instanceAttributeOffset = 0;
247 for (const auto& attrib : primProc.instanceAttributes()) {
248 // When using SPIRV-Cross it converts the location modifier in SPIRV to be
249 // TEXCOORD<N> where N is the location value for eveery vertext attribute
250 inputElements[currentAttrib] = { "TEXCOORD", currentAttrib,
251 attrib_type_to_format(attrib.cpuType()),
252 instanceSlot, instanceAttributeOffset,
Greg Daniel83468342020-06-17 11:49:06 -0400253 D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, 1 };
Jim Van Verthbe259dc2020-05-19 11:40:31 -0400254 instanceAttributeOffset += attrib.sizeAlign4();
255 currentAttrib++;
256 }
257 SkASSERT(instanceAttributeOffset == primProc.instanceStride());
258}
259
260static D3D12_BLEND blend_coeff_to_d3d_blend(GrBlendCoeff coeff) {
261 switch (coeff) {
262 case kZero_GrBlendCoeff:
263 return D3D12_BLEND_ZERO;
264 case kOne_GrBlendCoeff:
265 return D3D12_BLEND_ONE;
266 case kSC_GrBlendCoeff:
267 return D3D12_BLEND_SRC_COLOR;
268 case kISC_GrBlendCoeff:
269 return D3D12_BLEND_INV_SRC_COLOR;
270 case kDC_GrBlendCoeff:
271 return D3D12_BLEND_DEST_COLOR;
272 case kIDC_GrBlendCoeff:
273 return D3D12_BLEND_INV_DEST_COLOR;
274 case kSA_GrBlendCoeff:
275 return D3D12_BLEND_SRC_ALPHA;
276 case kISA_GrBlendCoeff:
277 return D3D12_BLEND_INV_SRC_ALPHA;
278 case kDA_GrBlendCoeff:
279 return D3D12_BLEND_DEST_ALPHA;
280 case kIDA_GrBlendCoeff:
281 return D3D12_BLEND_INV_DEST_ALPHA;
282 case kConstC_GrBlendCoeff:
283 return D3D12_BLEND_BLEND_FACTOR;
284 case kIConstC_GrBlendCoeff:
285 return D3D12_BLEND_INV_BLEND_FACTOR;
286 case kS2C_GrBlendCoeff:
287 return D3D12_BLEND_SRC1_COLOR;
288 case kIS2C_GrBlendCoeff:
289 return D3D12_BLEND_INV_SRC1_COLOR;
290 case kS2A_GrBlendCoeff:
291 return D3D12_BLEND_SRC1_ALPHA;
292 case kIS2A_GrBlendCoeff:
293 return D3D12_BLEND_INV_SRC1_ALPHA;
294 case kIllegal_GrBlendCoeff:
295 return D3D12_BLEND_ZERO;
296 }
297 SkUNREACHABLE;
298}
299
300static D3D12_BLEND blend_coeff_to_d3d_blend_for_alpha(GrBlendCoeff coeff) {
301 switch (coeff) {
302 // Force all srcColor used in alpha slot to alpha version.
303 case kSC_GrBlendCoeff:
304 return D3D12_BLEND_SRC_ALPHA;
305 case kISC_GrBlendCoeff:
306 return D3D12_BLEND_INV_SRC_ALPHA;
307 case kDC_GrBlendCoeff:
308 return D3D12_BLEND_DEST_ALPHA;
309 case kIDC_GrBlendCoeff:
310 return D3D12_BLEND_INV_DEST_ALPHA;
311 case kS2C_GrBlendCoeff:
312 return D3D12_BLEND_SRC1_ALPHA;
313 case kIS2C_GrBlendCoeff:
314 return D3D12_BLEND_INV_SRC1_ALPHA;
315
316 default:
317 return blend_coeff_to_d3d_blend(coeff);
318 }
319}
320
321
322static D3D12_BLEND_OP blend_equation_to_d3d_op(GrBlendEquation equation) {
323 switch (equation) {
324 case kAdd_GrBlendEquation:
325 return D3D12_BLEND_OP_ADD;
326 case kSubtract_GrBlendEquation:
327 return D3D12_BLEND_OP_SUBTRACT;
328 case kReverseSubtract_GrBlendEquation:
329 return D3D12_BLEND_OP_REV_SUBTRACT;
330 default:
331 SkUNREACHABLE;
332 }
333}
334
335static void fill_in_blend_state(const GrPipeline& pipeline, D3D12_BLEND_DESC* blendDesc) {
336 blendDesc->AlphaToCoverageEnable = false;
337 blendDesc->IndependentBlendEnable = false;
338
339 const GrXferProcessor::BlendInfo& blendInfo = pipeline.getXferProcessor().getBlendInfo();
340
341 GrBlendEquation equation = blendInfo.fEquation;
342 GrBlendCoeff srcCoeff = blendInfo.fSrcBlend;
343 GrBlendCoeff dstCoeff = blendInfo.fDstBlend;
344 bool blendOff = GrBlendShouldDisable(equation, srcCoeff, dstCoeff);
345
346 auto& rtBlend = blendDesc->RenderTarget[0];
347 rtBlend.BlendEnable = !blendOff;
348 if (!blendOff) {
349 rtBlend.SrcBlend = blend_coeff_to_d3d_blend(srcCoeff);
350 rtBlend.DestBlend = blend_coeff_to_d3d_blend(dstCoeff);
351 rtBlend.BlendOp = blend_equation_to_d3d_op(equation);
352 rtBlend.SrcBlendAlpha = blend_coeff_to_d3d_blend_for_alpha(srcCoeff);
353 rtBlend.DestBlendAlpha = blend_coeff_to_d3d_blend_for_alpha(dstCoeff);
354 rtBlend.BlendOpAlpha = blend_equation_to_d3d_op(equation);
355 }
356
357 if (!blendInfo.fWriteColor) {
358 rtBlend.RenderTargetWriteMask = 0;
359 } else {
360 rtBlend.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
361 }
362}
363
364static void fill_in_rasterizer_state(const GrPipeline& pipeline, const GrCaps* caps,
365 D3D12_RASTERIZER_DESC* rasterizer) {
366 rasterizer->FillMode = (caps->wireframeMode() || pipeline.isWireframe()) ?
367 D3D12_FILL_MODE_WIREFRAME : D3D12_FILL_MODE_SOLID;
368 rasterizer->CullMode = D3D12_CULL_MODE_NONE;
369 rasterizer->FrontCounterClockwise = true;
370 rasterizer->DepthBias = 0;
371 rasterizer->DepthBiasClamp = 0.0f;
372 rasterizer->SlopeScaledDepthBias = 0.0f;
373 rasterizer->DepthClipEnable = false;
374 rasterizer->MultisampleEnable = pipeline.isHWAntialiasState();
375 rasterizer->AntialiasedLineEnable = false;
376 rasterizer->ForcedSampleCount = 0;
377 rasterizer->ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
378}
379
380static D3D12_STENCIL_OP stencil_op_to_d3d_op(GrStencilOp op) {
381 switch (op) {
382 case GrStencilOp::kKeep:
383 return D3D12_STENCIL_OP_KEEP;
384 case GrStencilOp::kZero:
385 return D3D12_STENCIL_OP_ZERO;
386 case GrStencilOp::kReplace:
387 return D3D12_STENCIL_OP_REPLACE;
388 case GrStencilOp::kInvert:
389 return D3D12_STENCIL_OP_INVERT;
390 case GrStencilOp::kIncWrap:
391 return D3D12_STENCIL_OP_INCR;
392 case GrStencilOp::kDecWrap:
393 return D3D12_STENCIL_OP_DECR;
394 case GrStencilOp::kIncClamp:
395 return D3D12_STENCIL_OP_INCR_SAT;
396 case GrStencilOp::kDecClamp:
397 return D3D12_STENCIL_OP_DECR_SAT;
398 }
399 SkUNREACHABLE;
400}
401
402static D3D12_COMPARISON_FUNC stencil_test_to_d3d_func(GrStencilTest test) {
403 switch (test) {
404 case GrStencilTest::kAlways:
405 return D3D12_COMPARISON_FUNC_ALWAYS;
406 case GrStencilTest::kNever:
407 return D3D12_COMPARISON_FUNC_NEVER;
408 case GrStencilTest::kGreater:
409 return D3D12_COMPARISON_FUNC_GREATER;
410 case GrStencilTest::kGEqual:
411 return D3D12_COMPARISON_FUNC_GREATER_EQUAL;
412 case GrStencilTest::kLess:
413 return D3D12_COMPARISON_FUNC_LESS;
414 case GrStencilTest::kLEqual:
415 return D3D12_COMPARISON_FUNC_LESS_EQUAL;
416 case GrStencilTest::kEqual:
417 return D3D12_COMPARISON_FUNC_EQUAL;
418 case GrStencilTest::kNotEqual:
419 return D3D12_COMPARISON_FUNC_NOT_EQUAL;
420 }
421 SkUNREACHABLE;
422}
423
424static void setup_stencilop_desc(D3D12_DEPTH_STENCILOP_DESC* desc,
425 const GrStencilSettings::Face& stencilFace) {
426 desc->StencilFailOp = stencil_op_to_d3d_op(stencilFace.fFailOp);
427 desc->StencilDepthFailOp = desc->StencilFailOp;
428 desc->StencilPassOp = stencil_op_to_d3d_op(stencilFace.fPassOp);
429 desc->StencilFunc = stencil_test_to_d3d_func(stencilFace.fTest);
430}
431
432static void fill_in_depth_stencil_state(const GrProgramInfo& programInfo,
433 D3D12_DEPTH_STENCIL_DESC* dsDesc) {
434 GrStencilSettings stencilSettings = programInfo.nonGLStencilSettings();
435 GrSurfaceOrigin origin = programInfo.origin();
436
437 dsDesc->DepthEnable = false;
438 dsDesc->DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO;
439 dsDesc->DepthFunc = D3D12_COMPARISON_FUNC_NEVER;
440 dsDesc->StencilEnable = !stencilSettings.isDisabled();
441 if (!stencilSettings.isDisabled()) {
442 if (stencilSettings.isTwoSided()) {
443 const auto& frontFace = stencilSettings.postOriginCCWFace(origin);
Greg Daniel90cf5d42020-06-16 09:39:35 -0400444 const auto& backFace = stencilSettings.postOriginCWFace(origin);
Jim Van Verthbe259dc2020-05-19 11:40:31 -0400445
446 SkASSERT(frontFace.fTestMask == backFace.fTestMask);
447 SkASSERT(frontFace.fWriteMask == backFace.fWriteMask);
448 dsDesc->StencilReadMask = frontFace.fTestMask;
449 dsDesc->StencilWriteMask = frontFace.fWriteMask;
450
451 setup_stencilop_desc(&dsDesc->FrontFace, frontFace);
452 setup_stencilop_desc(&dsDesc->BackFace, backFace);
453 } else {
454 dsDesc->StencilReadMask = stencilSettings.singleSidedFace().fTestMask;
Greg Daniel90cf5d42020-06-16 09:39:35 -0400455 dsDesc->StencilWriteMask = stencilSettings.singleSidedFace().fWriteMask;
Jim Van Verthbe259dc2020-05-19 11:40:31 -0400456 setup_stencilop_desc(&dsDesc->FrontFace, stencilSettings.singleSidedFace());
457 dsDesc->BackFace = dsDesc->FrontFace;
458 }
459 }
460}
461
462static D3D12_PRIMITIVE_TOPOLOGY_TYPE gr_primitive_type_to_d3d(GrPrimitiveType primitiveType) {
463 switch (primitiveType) {
Jim Van Verth83ed9572020-05-21 11:53:55 -0400464 case GrPrimitiveType::kTriangles:
465 case GrPrimitiveType::kTriangleStrip: //fall through
466 return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
467 case GrPrimitiveType::kPoints:
468 return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
469 case GrPrimitiveType::kLines: // fall through
470 case GrPrimitiveType::kLineStrip:
471 return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
472 case GrPrimitiveType::kPatches: // fall through, unsupported
473 case GrPrimitiveType::kPath: // fall through, unsupported
474 default:
475 SkUNREACHABLE;
Jim Van Verthbe259dc2020-05-19 11:40:31 -0400476 }
477}
478
Jim Van Verth5fba9ae2020-09-21 17:18:04 -0400479gr_cp<ID3D12PipelineState> create_pipeline_state(
Jim Van Verth765c5922020-08-10 17:23:50 -0400480 GrD3DGpu* gpu, const GrProgramInfo& programInfo, const sk_sp<GrD3DRootSignature>& rootSig,
Jim Van Verth5fba9ae2020-09-21 17:18:04 -0400481 gr_cp<ID3DBlob> vertexShader, gr_cp<ID3DBlob> geometryShader, gr_cp<ID3DBlob> pixelShader,
482 DXGI_FORMAT renderTargetFormat, DXGI_FORMAT depthStencilFormat,
483 unsigned int sampleQualityPattern) {
Jim Van Verthbe259dc2020-05-19 11:40:31 -0400484 D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
485
486 psoDesc.pRootSignature = rootSig->rootSignature();
487
488 psoDesc.VS = { reinterpret_cast<UINT8*>(vertexShader->GetBufferPointer()),
489 vertexShader->GetBufferSize() };
490 psoDesc.PS = { reinterpret_cast<UINT8*>(pixelShader->GetBufferPointer()),
491 pixelShader->GetBufferSize() };
492
Jim Van Verth5fba9ae2020-09-21 17:18:04 -0400493 if (geometryShader.get()) {
Jim Van Verthbe259dc2020-05-19 11:40:31 -0400494 psoDesc.GS = { reinterpret_cast<UINT8*>(geometryShader->GetBufferPointer()),
495 geometryShader->GetBufferSize() };
496 }
497
498 psoDesc.StreamOutput = { nullptr, 0, nullptr, 0, 0 };
499
500 fill_in_blend_state(programInfo.pipeline(), &psoDesc.BlendState);
501 psoDesc.SampleMask = UINT_MAX;
502
503 fill_in_rasterizer_state(programInfo.pipeline(), gpu->caps(), &psoDesc.RasterizerState);
504
505 fill_in_depth_stencil_state(programInfo, &psoDesc.DepthStencilState);
506
507 unsigned int totalAttributeCnt = programInfo.primProc().numVertexAttributes() +
508 programInfo.primProc().numInstanceAttributes();
509 SkAutoSTArray<4, D3D12_INPUT_ELEMENT_DESC> inputElements(totalAttributeCnt);
510 setup_vertex_input_layout(programInfo.primProc(), inputElements.get());
511
512 psoDesc.InputLayout = { inputElements.get(), totalAttributeCnt };
513
514 psoDesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;
515
516 // This is for geometry or hull shader primitives
517 psoDesc.PrimitiveTopologyType = gr_primitive_type_to_d3d(programInfo.primitiveType());
518
519 psoDesc.NumRenderTargets = 1;
520
521 psoDesc.RTVFormats[0] = renderTargetFormat;
522
523 psoDesc.DSVFormat = depthStencilFormat;
524
525 unsigned int numRasterSamples = programInfo.numRasterSamples();
Jim Van Verth765c5922020-08-10 17:23:50 -0400526 psoDesc.SampleDesc = { numRasterSamples, sampleQualityPattern };
Jim Van Verthbe259dc2020-05-19 11:40:31 -0400527
528 // Only used for multi-adapter systems.
529 psoDesc.NodeMask = 0;
530
531 psoDesc.CachedPSO = { nullptr, 0 };
532 psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
533
Jim Van Verth5fba9ae2020-09-21 17:18:04 -0400534 gr_cp<ID3D12PipelineState> pipelineState;
Jim Van Verth8bf01942020-07-01 13:46:57 -0400535 GR_D3D_CALL_ERRCHECK(gpu->device()->CreateGraphicsPipelineState(
536 &psoDesc, IID_PPV_ARGS(&pipelineState)));
Jim Van Verthbe259dc2020-05-19 11:40:31 -0400537
538 return pipelineState;
539}
540
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400541static constexpr SkFourByteTag kHLSL_Tag = SkSetFourByteTag('H', 'L', 'S', 'L');
542static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L');
543
Greg Danielfd776732020-04-23 12:51:13 -0400544sk_sp<GrD3DPipelineState> GrD3DPipelineStateBuilder::finalize() {
Greg Daniel5fc5c812020-04-23 10:30:23 -0400545 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
546
547 // We need to enable the following extensions so that the compiler can correctly make spir-v
548 // from our glsl shaders.
549 fVS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
550 fFS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
551 fVS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
552 fFS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
553
554 this->finalizeShaders();
555
556 SkSL::Program::Settings settings;
Greg Daniel5fc5c812020-04-23 10:30:23 -0400557 settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin;
558 settings.fSharpenTextures =
559 this->gpu()->getContext()->priv().options().fSharpenMipmappedTextures;
560 settings.fRTHeightOffset = fUniformHandler.getRTHeightOffset();
561 settings.fRTHeightBinding = 0;
562 settings.fRTHeightSet = 0;
563
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400564 sk_sp<SkData> cached;
565 SkReadBuffer reader;
566 SkFourByteTag shaderType = 0;
567 auto persistentCache = fGpu->getContext()->priv().getPersistentCache();
568 if (persistentCache) {
569 // Shear off the D3D-specific portion of the Desc to get the persistent key. We only cache
570 // shader code, not entire pipelines.
571 sk_sp<SkData> key =
572 SkData::MakeWithoutCopy(this->desc().asKey(), this->desc().initialKeyLength());
573 cached = persistentCache->load(*key);
574 if (cached) {
575 reader.setMemory(cached->data(), cached->size());
576 shaderType = GrPersistentCacheUtils::GetType(&reader);
577 }
Greg Daniel5fc5c812020-04-23 10:30:23 -0400578 }
579
Jim Van Verth40b4de22020-05-20 09:35:42 -0400580 const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
Jim Van Verth5fba9ae2020-09-21 17:18:04 -0400581 gr_cp<ID3DBlob> shaders[kGrShaderTypeCount];
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400582
583 if (kHLSL_Tag == shaderType && this->loadHLSLFromCache(&reader, shaders)) {
584 // We successfully loaded and compiled HLSL
585 } else {
586 SkSL::Program::Inputs inputs[kGrShaderTypeCount];
587 SkSL::String* sksl[kGrShaderTypeCount] = {
588 &fVS.fCompilerString,
589 &fGS.fCompilerString,
590 &fFS.fCompilerString,
591 };
592 SkSL::String cached_sksl[kGrShaderTypeCount];
593 SkSL::String hlsl[kGrShaderTypeCount];
594
595 if (kSKSL_Tag == shaderType) {
596 if (GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, inputs,
597 kGrShaderTypeCount)) {
598 for (int i = 0; i < kGrShaderTypeCount; ++i) {
599 sksl[i] = &cached_sksl[i];
600 }
601 }
602 }
603
John Stilesdbd4e6f2021-02-16 13:29:15 -0500604 auto compile = [&](SkSL::ProgramKind kind, GrShaderType shaderType) {
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400605 shaders[shaderType] = this->compileD3DProgram(kind, *sksl[shaderType], settings,
606 &inputs[shaderType], &hlsl[shaderType]);
Jim Van Verth5fba9ae2020-09-21 17:18:04 -0400607 return shaders[shaderType].get();
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400608 };
609
John Stilesdbd4e6f2021-02-16 13:29:15 -0500610 if (!compile(SkSL::ProgramKind::kVertex, kVertex_GrShaderType) ||
611 !compile(SkSL::ProgramKind::kFragment, kFragment_GrShaderType)) {
Greg Daniel5fc5c812020-04-23 10:30:23 -0400612 return nullptr;
613 }
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400614
615 if (primProc.willUseGeoShader()) {
John Stilesdbd4e6f2021-02-16 13:29:15 -0500616 if (!compile(SkSL::ProgramKind::kGeometry, kGeometry_GrShaderType)) {
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400617 return nullptr;
618 }
619 }
620
621 if (persistentCache && !cached) {
622 const bool cacheSkSL = fGpu->getContext()->priv().options().fShaderCacheStrategy ==
623 GrContextOptions::ShaderCacheStrategy::kSkSL;
624 if (cacheSkSL) {
625 // Replace the HLSL with formatted SkSL to be cached. This looks odd, but this is
626 // the last time we're going to use these strings, so it's safe.
627 for (int i = 0; i < kGrShaderTypeCount; ++i) {
628 hlsl[i] = GrShaderUtils::PrettyPrint(*sksl[i]);
629 }
630 }
631 sk_sp<SkData> key =
632 SkData::MakeWithoutCopy(this->desc().asKey(), this->desc().initialKeyLength());
633 sk_sp<SkData> data = GrPersistentCacheUtils::PackCachedShaders(
Brian Osman5ca9d1a2020-06-16 15:25:33 -0400634 cacheSkSL ? kSKSL_Tag : kHLSL_Tag, hlsl, inputs, kGrShaderTypeCount);
Brian Osmanacf26502021-03-03 13:35:04 +0000635 persistentCache->store(*key, *data);
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400636 }
Greg Daniel5fc5c812020-04-23 10:30:23 -0400637 }
638
Greg Danielc31edc02020-04-23 11:03:02 -0400639 sk_sp<GrD3DRootSignature> rootSig =
640 fGpu->resourceProvider().findOrCreateRootSignature(fUniformHandler.fTextures.count());
641 if (!rootSig) {
642 return nullptr;
643 }
Greg Daniel5fc5c812020-04-23 10:30:23 -0400644
645 const GrD3DRenderTarget* rt = static_cast<const GrD3DRenderTarget*>(fRenderTarget);
Jim Van Verth5fba9ae2020-09-21 17:18:04 -0400646 gr_cp<ID3D12PipelineState> pipelineState = create_pipeline_state(
Brian Osmanb71b6ae2020-06-16 12:41:25 -0400647 fGpu, fProgramInfo, rootSig, std::move(shaders[kVertex_GrShaderType]),
648 std::move(shaders[kGeometry_GrShaderType]), std::move(shaders[kFragment_GrShaderType]),
Jim Van Verth765c5922020-08-10 17:23:50 -0400649 rt->dxgiFormat(), rt->stencilDxgiFormat(), rt->sampleQualityPattern());
Jim Van Verthbe259dc2020-05-19 11:40:31 -0400650
651 return sk_sp<GrD3DPipelineState>(new GrD3DPipelineState(std::move(pipelineState),
Jim Van Verth83ed9572020-05-21 11:53:55 -0400652 std::move(rootSig),
Jim Van Verthbe259dc2020-05-19 11:40:31 -0400653 fUniformHandles,
654 fUniformHandler.fUniforms,
655 fUniformHandler.fCurrentUBOOffset,
Jim Van Verth40b4de22020-05-20 09:35:42 -0400656 fUniformHandler.fSamplers.count(),
Jim Van Verthbe259dc2020-05-19 11:40:31 -0400657 std::move(fGeometryProcessor),
658 std::move(fXferProcessor),
Brian Salomon17f95b12021-02-23 09:35:08 -0500659 std::move(fFPImpls),
Jim Van Verth40b4de22020-05-20 09:35:42 -0400660 primProc.vertexStride(),
661 primProc.instanceStride()));
Greg Daniel5fc5c812020-04-23 10:30:23 -0400662}