Greg Daniel | 5fc5c81 | 2020-04-23 10:30:23 -0400 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2020 Google LLC |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license that can be |
| 5 | * found in the LICENSE file. |
| 6 | */ |
| 7 | |
| 8 | //#include <d3dcompiler.h> |
| 9 | |
| 10 | #include "src/gpu/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" |
| 17 | #include "src/gpu/GrShaderCaps.h" |
| 18 | #include "src/gpu/GrShaderUtils.h" |
| 19 | #include "src/gpu/GrStencilSettings.h" |
| 20 | #include "src/gpu/d3d/GrD3DGpu.h" |
| 21 | #include "src/gpu/d3d/GrD3DRenderTarget.h" |
Greg Daniel | c31edc0 | 2020-04-23 11:03:02 -0400 | [diff] [blame] | 22 | #include "src/gpu/d3d/GrD3DRootSignature.h" |
Greg Daniel | 5fc5c81 | 2020-04-23 10:30:23 -0400 | [diff] [blame] | 23 | #include "src/sksl/SkSLCompiler.h" |
| 24 | |
| 25 | #include <d3dcompiler.h> |
| 26 | |
| 27 | typedef size_t shader_size; |
| 28 | |
Greg Daniel | b698ad3 | 2020-05-04 10:17:22 -0400 | [diff] [blame] | 29 | sk_sp<GrD3DPipelineState> GrD3DPipelineStateBuilder::MakePipelineState( |
Greg Daniel | 5fc5c81 | 2020-04-23 10:30:23 -0400 | [diff] [blame] | 30 | 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 | |
| 48 | GrD3DPipelineStateBuilder::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 | |
| 57 | const GrCaps* GrD3DPipelineStateBuilder::caps() const { |
| 58 | return fGpu->caps(); |
| 59 | } |
| 60 | |
| 61 | void GrD3DPipelineStateBuilder::finalizeFragmentOutputColor(GrShaderVar& outputColor) { |
| 62 | outputColor.addLayoutQualifier("location = 0, index = 0"); |
| 63 | } |
| 64 | |
| 65 | void GrD3DPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outputColor) { |
| 66 | outputColor.addLayoutQualifier("location = 0, index = 1"); |
| 67 | } |
| 68 | |
| 69 | void GrD3DPipelineStateBuilder::compileD3DProgram(SkSL::Program::Kind kind, |
| 70 | const SkSL::String& sksl, |
| 71 | const SkSL::Program::Settings& settings, |
| 72 | ID3DBlob** shader, |
| 73 | SkSL::Program::Inputs* outInputs) { |
| 74 | auto errorHandler = fGpu->getContext()->priv().getShaderErrorHandler(); |
| 75 | std::unique_ptr<SkSL::Program> program = fGpu->shaderCompiler()->convertProgram( |
| 76 | kind, sksl, settings); |
| 77 | if (!program) { |
| 78 | errorHandler->compileError(sksl.c_str(), |
| 79 | fGpu->shaderCompiler()->errorText().c_str()); |
| 80 | return; |
| 81 | } |
| 82 | *outInputs = program->fInputs; |
| 83 | SkSL::String outHLSL; |
| 84 | if (!fGpu->shaderCompiler()->toHLSL(*program, &outHLSL)) { |
| 85 | errorHandler->compileError(sksl.c_str(), |
| 86 | fGpu->shaderCompiler()->errorText().c_str()); |
| 87 | return; |
| 88 | } |
| 89 | |
| 90 | const char* compileTarget = nullptr; |
| 91 | switch (kind) { |
| 92 | case SkSL::Program::kVertex_Kind: |
| 93 | compileTarget = "vs_5_1"; |
| 94 | break; |
| 95 | case SkSL::Program::kGeometry_Kind: |
| 96 | compileTarget = "gs_5_1"; |
| 97 | break; |
| 98 | case SkSL::Program::kFragment_Kind: |
| 99 | compileTarget = "ps_5_1"; |
| 100 | break; |
| 101 | default: |
| 102 | SkUNREACHABLE; |
| 103 | } |
| 104 | |
| 105 | uint32_t compileFlags = 0; |
| 106 | #ifdef SK_DEBUG |
| 107 | // Enable better shader debugging with the graphics debugging tools. |
| 108 | compileFlags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION; |
| 109 | #endif |
| 110 | // SPRIV-cross does matrix multiplication expecting row major matrices |
| 111 | compileFlags |= D3DCOMPILE_PACK_MATRIX_ROW_MAJOR; |
| 112 | |
| 113 | // TODO: D3D Static Function |
| 114 | gr_cp<ID3DBlob> errors; |
| 115 | HRESULT hr = D3DCompile(outHLSL.c_str(), outHLSL.length(), nullptr, nullptr, nullptr, "main", |
| 116 | compileTarget, compileFlags, 0, shader, &errors); |
| 117 | if (!SUCCEEDED(hr)) { |
| 118 | errorHandler->compileError(outHLSL.c_str(), |
| 119 | reinterpret_cast<char*>(errors->GetBufferPointer())); |
| 120 | } |
| 121 | } |
| 122 | |
Jim Van Verth | be259dc | 2020-05-19 11:40:31 -0400 | [diff] [blame] | 123 | static DXGI_FORMAT attrib_type_to_format(GrVertexAttribType type) { |
| 124 | switch (type) { |
| 125 | case kFloat_GrVertexAttribType: |
| 126 | return DXGI_FORMAT_R32_FLOAT; |
| 127 | case kFloat2_GrVertexAttribType: |
| 128 | return DXGI_FORMAT_R32G32_FLOAT; |
| 129 | case kFloat3_GrVertexAttribType: |
| 130 | return DXGI_FORMAT_R32G32B32_FLOAT; |
| 131 | case kFloat4_GrVertexAttribType: |
| 132 | return DXGI_FORMAT_R32G32B32A32_FLOAT; |
| 133 | case kHalf_GrVertexAttribType: |
| 134 | return DXGI_FORMAT_R16_FLOAT; |
| 135 | case kHalf2_GrVertexAttribType: |
| 136 | return DXGI_FORMAT_R16G16_FLOAT; |
| 137 | case kHalf4_GrVertexAttribType: |
| 138 | return DXGI_FORMAT_R16G16B16A16_FLOAT; |
| 139 | case kInt2_GrVertexAttribType: |
| 140 | return DXGI_FORMAT_R32G32_SINT; |
| 141 | case kInt3_GrVertexAttribType: |
| 142 | return DXGI_FORMAT_R32G32B32_SINT; |
| 143 | case kInt4_GrVertexAttribType: |
| 144 | return DXGI_FORMAT_R32G32B32A32_SINT; |
| 145 | case kByte_GrVertexAttribType: |
| 146 | return DXGI_FORMAT_R8_SINT; |
| 147 | case kByte2_GrVertexAttribType: |
| 148 | return DXGI_FORMAT_R8G8_SINT; |
| 149 | case kByte4_GrVertexAttribType: |
| 150 | return DXGI_FORMAT_R8G8B8A8_SINT; |
| 151 | case kUByte_GrVertexAttribType: |
| 152 | return DXGI_FORMAT_R8_UINT; |
| 153 | case kUByte2_GrVertexAttribType: |
| 154 | return DXGI_FORMAT_R8G8_UINT; |
| 155 | case kUByte4_GrVertexAttribType: |
| 156 | return DXGI_FORMAT_R8G8B8A8_UINT; |
| 157 | case kUByte_norm_GrVertexAttribType: |
| 158 | return DXGI_FORMAT_R8_UNORM; |
| 159 | case kUByte4_norm_GrVertexAttribType: |
| 160 | return DXGI_FORMAT_R8G8B8A8_UNORM; |
| 161 | case kShort2_GrVertexAttribType: |
| 162 | return DXGI_FORMAT_R16G16_SINT; |
| 163 | case kShort4_GrVertexAttribType: |
| 164 | return DXGI_FORMAT_R16G16B16A16_SINT; |
| 165 | case kUShort2_GrVertexAttribType: |
| 166 | return DXGI_FORMAT_R16G16_UINT; |
| 167 | case kUShort2_norm_GrVertexAttribType: |
| 168 | return DXGI_FORMAT_R16G16_UNORM; |
| 169 | case kInt_GrVertexAttribType: |
| 170 | return DXGI_FORMAT_R32_SINT; |
| 171 | case kUint_GrVertexAttribType: |
| 172 | return DXGI_FORMAT_R32_UINT; |
| 173 | case kUShort_norm_GrVertexAttribType: |
| 174 | return DXGI_FORMAT_R16_UNORM; |
| 175 | case kUShort4_norm_GrVertexAttribType: |
| 176 | return DXGI_FORMAT_R16G16B16A16_UNORM; |
| 177 | } |
| 178 | SK_ABORT("Unknown vertex attrib type"); |
| 179 | } |
| 180 | |
| 181 | static void setup_vertex_input_layout(const GrPrimitiveProcessor& primProc, |
| 182 | D3D12_INPUT_ELEMENT_DESC* inputElements) { |
| 183 | unsigned int slotNumber = 0; |
| 184 | unsigned int vertexSlot = 0; |
| 185 | unsigned int instanceSlot = 0; |
| 186 | if (primProc.hasVertexAttributes()) { |
| 187 | vertexSlot = slotNumber++; |
| 188 | } |
| 189 | if (primProc.hasInstanceAttributes()) { |
| 190 | instanceSlot = slotNumber++; |
| 191 | } |
| 192 | |
| 193 | unsigned int currentAttrib = 0; |
| 194 | unsigned int vertexAttributeOffset = 0; |
| 195 | |
| 196 | for (const auto& attrib : primProc.vertexAttributes()) { |
| 197 | // When using SPIRV-Cross it converts the location modifier in SPIRV to be |
| 198 | // TEXCOORD<N> where N is the location value for eveery vertext attribute |
| 199 | inputElements[currentAttrib] = { "TEXCOORD", currentAttrib, |
| 200 | attrib_type_to_format(attrib.cpuType()), |
| 201 | vertexSlot, vertexAttributeOffset, |
| 202 | D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }; |
| 203 | vertexAttributeOffset += attrib.sizeAlign4(); |
| 204 | currentAttrib++; |
| 205 | } |
| 206 | SkASSERT(vertexAttributeOffset == primProc.vertexStride()); |
| 207 | |
| 208 | unsigned int instanceAttributeOffset = 0; |
| 209 | for (const auto& attrib : primProc.instanceAttributes()) { |
| 210 | // When using SPIRV-Cross it converts the location modifier in SPIRV to be |
| 211 | // TEXCOORD<N> where N is the location value for eveery vertext attribute |
| 212 | inputElements[currentAttrib] = { "TEXCOORD", currentAttrib, |
| 213 | attrib_type_to_format(attrib.cpuType()), |
| 214 | instanceSlot, instanceAttributeOffset, |
| 215 | D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }; |
| 216 | instanceAttributeOffset += attrib.sizeAlign4(); |
| 217 | currentAttrib++; |
| 218 | } |
| 219 | SkASSERT(instanceAttributeOffset == primProc.instanceStride()); |
| 220 | } |
| 221 | |
| 222 | static D3D12_BLEND blend_coeff_to_d3d_blend(GrBlendCoeff coeff) { |
| 223 | switch (coeff) { |
| 224 | case kZero_GrBlendCoeff: |
| 225 | return D3D12_BLEND_ZERO; |
| 226 | case kOne_GrBlendCoeff: |
| 227 | return D3D12_BLEND_ONE; |
| 228 | case kSC_GrBlendCoeff: |
| 229 | return D3D12_BLEND_SRC_COLOR; |
| 230 | case kISC_GrBlendCoeff: |
| 231 | return D3D12_BLEND_INV_SRC_COLOR; |
| 232 | case kDC_GrBlendCoeff: |
| 233 | return D3D12_BLEND_DEST_COLOR; |
| 234 | case kIDC_GrBlendCoeff: |
| 235 | return D3D12_BLEND_INV_DEST_COLOR; |
| 236 | case kSA_GrBlendCoeff: |
| 237 | return D3D12_BLEND_SRC_ALPHA; |
| 238 | case kISA_GrBlendCoeff: |
| 239 | return D3D12_BLEND_INV_SRC_ALPHA; |
| 240 | case kDA_GrBlendCoeff: |
| 241 | return D3D12_BLEND_DEST_ALPHA; |
| 242 | case kIDA_GrBlendCoeff: |
| 243 | return D3D12_BLEND_INV_DEST_ALPHA; |
| 244 | case kConstC_GrBlendCoeff: |
| 245 | return D3D12_BLEND_BLEND_FACTOR; |
| 246 | case kIConstC_GrBlendCoeff: |
| 247 | return D3D12_BLEND_INV_BLEND_FACTOR; |
| 248 | case kS2C_GrBlendCoeff: |
| 249 | return D3D12_BLEND_SRC1_COLOR; |
| 250 | case kIS2C_GrBlendCoeff: |
| 251 | return D3D12_BLEND_INV_SRC1_COLOR; |
| 252 | case kS2A_GrBlendCoeff: |
| 253 | return D3D12_BLEND_SRC1_ALPHA; |
| 254 | case kIS2A_GrBlendCoeff: |
| 255 | return D3D12_BLEND_INV_SRC1_ALPHA; |
| 256 | case kIllegal_GrBlendCoeff: |
| 257 | return D3D12_BLEND_ZERO; |
| 258 | } |
| 259 | SkUNREACHABLE; |
| 260 | } |
| 261 | |
| 262 | static D3D12_BLEND blend_coeff_to_d3d_blend_for_alpha(GrBlendCoeff coeff) { |
| 263 | switch (coeff) { |
| 264 | // Force all srcColor used in alpha slot to alpha version. |
| 265 | case kSC_GrBlendCoeff: |
| 266 | return D3D12_BLEND_SRC_ALPHA; |
| 267 | case kISC_GrBlendCoeff: |
| 268 | return D3D12_BLEND_INV_SRC_ALPHA; |
| 269 | case kDC_GrBlendCoeff: |
| 270 | return D3D12_BLEND_DEST_ALPHA; |
| 271 | case kIDC_GrBlendCoeff: |
| 272 | return D3D12_BLEND_INV_DEST_ALPHA; |
| 273 | case kS2C_GrBlendCoeff: |
| 274 | return D3D12_BLEND_SRC1_ALPHA; |
| 275 | case kIS2C_GrBlendCoeff: |
| 276 | return D3D12_BLEND_INV_SRC1_ALPHA; |
| 277 | |
| 278 | default: |
| 279 | return blend_coeff_to_d3d_blend(coeff); |
| 280 | } |
| 281 | } |
| 282 | |
| 283 | |
| 284 | static D3D12_BLEND_OP blend_equation_to_d3d_op(GrBlendEquation equation) { |
| 285 | switch (equation) { |
| 286 | case kAdd_GrBlendEquation: |
| 287 | return D3D12_BLEND_OP_ADD; |
| 288 | case kSubtract_GrBlendEquation: |
| 289 | return D3D12_BLEND_OP_SUBTRACT; |
| 290 | case kReverseSubtract_GrBlendEquation: |
| 291 | return D3D12_BLEND_OP_REV_SUBTRACT; |
| 292 | default: |
| 293 | SkUNREACHABLE; |
| 294 | } |
| 295 | } |
| 296 | |
| 297 | static void fill_in_blend_state(const GrPipeline& pipeline, D3D12_BLEND_DESC* blendDesc) { |
| 298 | blendDesc->AlphaToCoverageEnable = false; |
| 299 | blendDesc->IndependentBlendEnable = false; |
| 300 | |
| 301 | const GrXferProcessor::BlendInfo& blendInfo = pipeline.getXferProcessor().getBlendInfo(); |
| 302 | |
| 303 | GrBlendEquation equation = blendInfo.fEquation; |
| 304 | GrBlendCoeff srcCoeff = blendInfo.fSrcBlend; |
| 305 | GrBlendCoeff dstCoeff = blendInfo.fDstBlend; |
| 306 | bool blendOff = GrBlendShouldDisable(equation, srcCoeff, dstCoeff); |
| 307 | |
| 308 | auto& rtBlend = blendDesc->RenderTarget[0]; |
| 309 | rtBlend.BlendEnable = !blendOff; |
| 310 | if (!blendOff) { |
| 311 | rtBlend.SrcBlend = blend_coeff_to_d3d_blend(srcCoeff); |
| 312 | rtBlend.DestBlend = blend_coeff_to_d3d_blend(dstCoeff); |
| 313 | rtBlend.BlendOp = blend_equation_to_d3d_op(equation); |
| 314 | rtBlend.SrcBlendAlpha = blend_coeff_to_d3d_blend_for_alpha(srcCoeff); |
| 315 | rtBlend.DestBlendAlpha = blend_coeff_to_d3d_blend_for_alpha(dstCoeff); |
| 316 | rtBlend.BlendOpAlpha = blend_equation_to_d3d_op(equation); |
| 317 | } |
| 318 | |
| 319 | if (!blendInfo.fWriteColor) { |
| 320 | rtBlend.RenderTargetWriteMask = 0; |
| 321 | } else { |
| 322 | rtBlend.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; |
| 323 | } |
| 324 | } |
| 325 | |
| 326 | static void fill_in_rasterizer_state(const GrPipeline& pipeline, const GrCaps* caps, |
| 327 | D3D12_RASTERIZER_DESC* rasterizer) { |
| 328 | rasterizer->FillMode = (caps->wireframeMode() || pipeline.isWireframe()) ? |
| 329 | D3D12_FILL_MODE_WIREFRAME : D3D12_FILL_MODE_SOLID; |
| 330 | rasterizer->CullMode = D3D12_CULL_MODE_NONE; |
| 331 | rasterizer->FrontCounterClockwise = true; |
| 332 | rasterizer->DepthBias = 0; |
| 333 | rasterizer->DepthBiasClamp = 0.0f; |
| 334 | rasterizer->SlopeScaledDepthBias = 0.0f; |
| 335 | rasterizer->DepthClipEnable = false; |
| 336 | rasterizer->MultisampleEnable = pipeline.isHWAntialiasState(); |
| 337 | rasterizer->AntialiasedLineEnable = false; |
| 338 | rasterizer->ForcedSampleCount = 0; |
| 339 | rasterizer->ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; |
| 340 | } |
| 341 | |
| 342 | static D3D12_STENCIL_OP stencil_op_to_d3d_op(GrStencilOp op) { |
| 343 | switch (op) { |
| 344 | case GrStencilOp::kKeep: |
| 345 | return D3D12_STENCIL_OP_KEEP; |
| 346 | case GrStencilOp::kZero: |
| 347 | return D3D12_STENCIL_OP_ZERO; |
| 348 | case GrStencilOp::kReplace: |
| 349 | return D3D12_STENCIL_OP_REPLACE; |
| 350 | case GrStencilOp::kInvert: |
| 351 | return D3D12_STENCIL_OP_INVERT; |
| 352 | case GrStencilOp::kIncWrap: |
| 353 | return D3D12_STENCIL_OP_INCR; |
| 354 | case GrStencilOp::kDecWrap: |
| 355 | return D3D12_STENCIL_OP_DECR; |
| 356 | case GrStencilOp::kIncClamp: |
| 357 | return D3D12_STENCIL_OP_INCR_SAT; |
| 358 | case GrStencilOp::kDecClamp: |
| 359 | return D3D12_STENCIL_OP_DECR_SAT; |
| 360 | } |
| 361 | SkUNREACHABLE; |
| 362 | } |
| 363 | |
| 364 | static D3D12_COMPARISON_FUNC stencil_test_to_d3d_func(GrStencilTest test) { |
| 365 | switch (test) { |
| 366 | case GrStencilTest::kAlways: |
| 367 | return D3D12_COMPARISON_FUNC_ALWAYS; |
| 368 | case GrStencilTest::kNever: |
| 369 | return D3D12_COMPARISON_FUNC_NEVER; |
| 370 | case GrStencilTest::kGreater: |
| 371 | return D3D12_COMPARISON_FUNC_GREATER; |
| 372 | case GrStencilTest::kGEqual: |
| 373 | return D3D12_COMPARISON_FUNC_GREATER_EQUAL; |
| 374 | case GrStencilTest::kLess: |
| 375 | return D3D12_COMPARISON_FUNC_LESS; |
| 376 | case GrStencilTest::kLEqual: |
| 377 | return D3D12_COMPARISON_FUNC_LESS_EQUAL; |
| 378 | case GrStencilTest::kEqual: |
| 379 | return D3D12_COMPARISON_FUNC_EQUAL; |
| 380 | case GrStencilTest::kNotEqual: |
| 381 | return D3D12_COMPARISON_FUNC_NOT_EQUAL; |
| 382 | } |
| 383 | SkUNREACHABLE; |
| 384 | } |
| 385 | |
| 386 | static void setup_stencilop_desc(D3D12_DEPTH_STENCILOP_DESC* desc, |
| 387 | const GrStencilSettings::Face& stencilFace) { |
| 388 | desc->StencilFailOp = stencil_op_to_d3d_op(stencilFace.fFailOp); |
| 389 | desc->StencilDepthFailOp = desc->StencilFailOp; |
| 390 | desc->StencilPassOp = stencil_op_to_d3d_op(stencilFace.fPassOp); |
| 391 | desc->StencilFunc = stencil_test_to_d3d_func(stencilFace.fTest); |
| 392 | } |
| 393 | |
| 394 | static void fill_in_depth_stencil_state(const GrProgramInfo& programInfo, |
| 395 | D3D12_DEPTH_STENCIL_DESC* dsDesc) { |
| 396 | GrStencilSettings stencilSettings = programInfo.nonGLStencilSettings(); |
| 397 | GrSurfaceOrigin origin = programInfo.origin(); |
| 398 | |
| 399 | dsDesc->DepthEnable = false; |
| 400 | dsDesc->DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO; |
| 401 | dsDesc->DepthFunc = D3D12_COMPARISON_FUNC_NEVER; |
| 402 | dsDesc->StencilEnable = !stencilSettings.isDisabled(); |
| 403 | if (!stencilSettings.isDisabled()) { |
| 404 | if (stencilSettings.isTwoSided()) { |
| 405 | const auto& frontFace = stencilSettings.postOriginCCWFace(origin); |
| 406 | const auto& backFace = stencilSettings.postOriginCCWFace(origin); |
| 407 | |
| 408 | SkASSERT(frontFace.fTestMask == backFace.fTestMask); |
| 409 | SkASSERT(frontFace.fWriteMask == backFace.fWriteMask); |
| 410 | dsDesc->StencilReadMask = frontFace.fTestMask; |
| 411 | dsDesc->StencilWriteMask = frontFace.fWriteMask; |
| 412 | |
| 413 | setup_stencilop_desc(&dsDesc->FrontFace, frontFace); |
| 414 | setup_stencilop_desc(&dsDesc->BackFace, backFace); |
| 415 | } else { |
| 416 | dsDesc->StencilReadMask = stencilSettings.singleSidedFace().fTestMask; |
| 417 | dsDesc->StencilWriteMask = stencilSettings.singleSidedFace().fTestMask; |
| 418 | setup_stencilop_desc(&dsDesc->FrontFace, stencilSettings.singleSidedFace()); |
| 419 | dsDesc->BackFace = dsDesc->FrontFace; |
| 420 | } |
| 421 | } |
| 422 | } |
| 423 | |
| 424 | static D3D12_PRIMITIVE_TOPOLOGY_TYPE gr_primitive_type_to_d3d(GrPrimitiveType primitiveType) { |
| 425 | switch (primitiveType) { |
| 426 | case GrPrimitiveType::kTriangles: |
| 427 | case GrPrimitiveType::kTriangleStrip: //fall through |
| 428 | return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; |
| 429 | case GrPrimitiveType::kPoints: |
| 430 | return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT; |
| 431 | case GrPrimitiveType::kLines: // fall through |
| 432 | case GrPrimitiveType::kLineStrip: |
| 433 | return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; |
| 434 | case GrPrimitiveType::kPatches: // fall through, unsupported |
| 435 | case GrPrimitiveType::kPath: // fall through, unsupported |
| 436 | default: |
| 437 | SkUNREACHABLE; |
| 438 | } |
| 439 | } |
| 440 | |
| 441 | gr_cp<ID3D12PipelineState> create_pipeline_state( |
| 442 | GrD3DGpu* gpu, const GrProgramInfo& programInfo, sk_sp<GrD3DRootSignature> rootSig, |
| 443 | gr_cp<ID3DBlob> vertexShader, gr_cp<ID3DBlob> geometryShader, gr_cp<ID3DBlob> pixelShader, |
| 444 | DXGI_FORMAT renderTargetFormat, DXGI_FORMAT depthStencilFormat, |
| 445 | unsigned int sampleQualityLevel) { |
| 446 | D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; |
| 447 | |
| 448 | psoDesc.pRootSignature = rootSig->rootSignature(); |
| 449 | |
| 450 | psoDesc.VS = { reinterpret_cast<UINT8*>(vertexShader->GetBufferPointer()), |
| 451 | vertexShader->GetBufferSize() }; |
| 452 | psoDesc.PS = { reinterpret_cast<UINT8*>(pixelShader->GetBufferPointer()), |
| 453 | pixelShader->GetBufferSize() }; |
| 454 | |
| 455 | if (geometryShader.get()) { |
| 456 | psoDesc.GS = { reinterpret_cast<UINT8*>(geometryShader->GetBufferPointer()), |
| 457 | geometryShader->GetBufferSize() }; |
| 458 | } |
| 459 | |
| 460 | psoDesc.StreamOutput = { nullptr, 0, nullptr, 0, 0 }; |
| 461 | |
| 462 | fill_in_blend_state(programInfo.pipeline(), &psoDesc.BlendState); |
| 463 | psoDesc.SampleMask = UINT_MAX; |
| 464 | |
| 465 | fill_in_rasterizer_state(programInfo.pipeline(), gpu->caps(), &psoDesc.RasterizerState); |
| 466 | |
| 467 | fill_in_depth_stencil_state(programInfo, &psoDesc.DepthStencilState); |
| 468 | |
| 469 | unsigned int totalAttributeCnt = programInfo.primProc().numVertexAttributes() + |
| 470 | programInfo.primProc().numInstanceAttributes(); |
| 471 | SkAutoSTArray<4, D3D12_INPUT_ELEMENT_DESC> inputElements(totalAttributeCnt); |
| 472 | setup_vertex_input_layout(programInfo.primProc(), inputElements.get()); |
| 473 | |
| 474 | psoDesc.InputLayout = { inputElements.get(), totalAttributeCnt }; |
| 475 | |
| 476 | psoDesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED; |
| 477 | |
| 478 | // This is for geometry or hull shader primitives |
| 479 | psoDesc.PrimitiveTopologyType = gr_primitive_type_to_d3d(programInfo.primitiveType()); |
| 480 | |
| 481 | psoDesc.NumRenderTargets = 1; |
| 482 | |
| 483 | psoDesc.RTVFormats[0] = renderTargetFormat; |
| 484 | |
| 485 | psoDesc.DSVFormat = depthStencilFormat; |
| 486 | |
| 487 | unsigned int numRasterSamples = programInfo.numRasterSamples(); |
| 488 | psoDesc.SampleDesc = { numRasterSamples, sampleQualityLevel }; |
| 489 | |
| 490 | // Only used for multi-adapter systems. |
| 491 | psoDesc.NodeMask = 0; |
| 492 | |
| 493 | psoDesc.CachedPSO = { nullptr, 0 }; |
| 494 | psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; |
| 495 | |
| 496 | gr_cp<ID3D12PipelineState> pipelineState; |
| 497 | SkDEBUGCODE(HRESULT hr = )gpu->device()->CreateGraphicsPipelineState( |
| 498 | &psoDesc, IID_PPV_ARGS(&pipelineState)); |
| 499 | SkASSERT(SUCCEEDED(hr)); |
| 500 | |
| 501 | return pipelineState; |
| 502 | } |
| 503 | |
Greg Daniel | fd77673 | 2020-04-23 12:51:13 -0400 | [diff] [blame] | 504 | sk_sp<GrD3DPipelineState> GrD3DPipelineStateBuilder::finalize() { |
Greg Daniel | 5fc5c81 | 2020-04-23 10:30:23 -0400 | [diff] [blame] | 505 | TRACE_EVENT0("skia.gpu", TRACE_FUNC); |
| 506 | |
| 507 | // We need to enable the following extensions so that the compiler can correctly make spir-v |
| 508 | // from our glsl shaders. |
| 509 | fVS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n"); |
| 510 | fFS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n"); |
| 511 | fVS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n"); |
| 512 | fFS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n"); |
| 513 | |
| 514 | this->finalizeShaders(); |
| 515 | |
| 516 | SkSL::Program::Settings settings; |
| 517 | settings.fCaps = this->caps()->shaderCaps(); |
| 518 | settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin; |
| 519 | settings.fSharpenTextures = |
| 520 | this->gpu()->getContext()->priv().options().fSharpenMipmappedTextures; |
| 521 | settings.fRTHeightOffset = fUniformHandler.getRTHeightOffset(); |
| 522 | settings.fRTHeightBinding = 0; |
| 523 | settings.fRTHeightSet = 0; |
| 524 | |
| 525 | gr_cp<ID3DBlob> vertexShader; |
| 526 | gr_cp<ID3DBlob> geometryShader; |
| 527 | gr_cp<ID3DBlob> pixelShader; |
| 528 | SkSL::Program::Inputs vertInputs, fragInputs, geomInputs; |
| 529 | |
| 530 | this->compileD3DProgram(SkSL::Program::kVertex_Kind, fVS.fCompilerString, settings, |
| 531 | &vertexShader, &vertInputs); |
| 532 | this->compileD3DProgram(SkSL::Program::kFragment_Kind, fFS.fCompilerString, settings, |
| 533 | &pixelShader, &fragInputs); |
| 534 | |
| 535 | if (!vertexShader.get() || !pixelShader.get()) { |
| 536 | return nullptr; |
| 537 | } |
| 538 | |
Jim Van Verth | 40b4de2 | 2020-05-20 09:35:42 -0400 | [diff] [blame^] | 539 | const GrPrimitiveProcessor& primProc = this->primitiveProcessor(); |
| 540 | if (primProc.willUseGeoShader()) { |
Greg Daniel | 5fc5c81 | 2020-04-23 10:30:23 -0400 | [diff] [blame] | 541 | this->compileD3DProgram(SkSL::Program::kGeometry_Kind, fGS.fCompilerString, settings, |
| 542 | &geometryShader, &geomInputs); |
| 543 | if (!geometryShader.get()) { |
| 544 | return nullptr; |
| 545 | } |
| 546 | } |
| 547 | |
Greg Daniel | c31edc0 | 2020-04-23 11:03:02 -0400 | [diff] [blame] | 548 | sk_sp<GrD3DRootSignature> rootSig = |
| 549 | fGpu->resourceProvider().findOrCreateRootSignature(fUniformHandler.fTextures.count()); |
| 550 | if (!rootSig) { |
| 551 | return nullptr; |
| 552 | } |
Greg Daniel | 5fc5c81 | 2020-04-23 10:30:23 -0400 | [diff] [blame] | 553 | |
| 554 | const GrD3DRenderTarget* rt = static_cast<const GrD3DRenderTarget*>(fRenderTarget); |
Jim Van Verth | be259dc | 2020-05-19 11:40:31 -0400 | [diff] [blame] | 555 | gr_cp<ID3D12PipelineState> pipelineState = create_pipeline_state( |
| 556 | fGpu, fProgramInfo, std::move(rootSig), std::move(vertexShader), |
| 557 | std::move(geometryShader), std::move(pixelShader), rt->dxgiFormat(), |
| 558 | rt->stencilDxgiFormat(), rt->sampleQualityLevel()); |
| 559 | |
| 560 | return sk_sp<GrD3DPipelineState>(new GrD3DPipelineState(std::move(pipelineState), |
| 561 | fUniformHandles, |
| 562 | fUniformHandler.fUniforms, |
| 563 | fUniformHandler.fCurrentUBOOffset, |
Jim Van Verth | 40b4de2 | 2020-05-20 09:35:42 -0400 | [diff] [blame^] | 564 | fUniformHandler.fSamplers.count(), |
Jim Van Verth | be259dc | 2020-05-19 11:40:31 -0400 | [diff] [blame] | 565 | std::move(fGeometryProcessor), |
| 566 | std::move(fXferProcessor), |
| 567 | std::move(fFragmentProcessors), |
Jim Van Verth | 40b4de2 | 2020-05-20 09:35:42 -0400 | [diff] [blame^] | 568 | fFragmentProcessorCnt, |
| 569 | primProc.vertexStride(), |
| 570 | primProc.instanceStride())); |
Greg Daniel | 5fc5c81 | 2020-04-23 10:30:23 -0400 | [diff] [blame] | 571 | } |