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 | |
Adlai Holler | 3d0359a | 2020-07-09 15:35:55 -0400 | [diff] [blame] | 12 | #include "include/gpu/GrDirectContext.h" |
Greg Daniel | 5fc5c81 | 2020-04-23 10:30:23 -0400 | [diff] [blame] | 13 | #include "include/gpu/d3d/GrD3DTypes.h" |
| 14 | #include "src/core/SkTraceEvent.h" |
| 15 | #include "src/gpu/GrAutoLocaleSetter.h" |
Adlai Holler | a069304 | 2020-10-14 11:23:11 -0400 | [diff] [blame] | 16 | #include "src/gpu/GrDirectContextPriv.h" |
Brian Osman | b71b6ae | 2020-06-16 12:41:25 -0400 | [diff] [blame] | 17 | #include "src/gpu/GrPersistentCacheUtils.h" |
Greg Daniel | 5fc5c81 | 2020-04-23 10:30:23 -0400 | [diff] [blame] | 18 | #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 Daniel | c31edc0 | 2020-04-23 11:03:02 -0400 | [diff] [blame] | 23 | #include "src/gpu/d3d/GrD3DRootSignature.h" |
Jim Van Verth | 8bf0194 | 2020-07-01 13:46:57 -0400 | [diff] [blame] | 24 | #include "src/gpu/d3d/GrD3DUtil.h" |
Greg Daniel | 5fc5c81 | 2020-04-23 10:30:23 -0400 | [diff] [blame] | 25 | #include "src/sksl/SkSLCompiler.h" |
| 26 | |
| 27 | #include <d3dcompiler.h> |
| 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 | |
Ethan Nicholas | ee9cb6a | 2021-02-02 11:59:09 -0500 | [diff] [blame] | 61 | SkSL::Compiler* GrD3DPipelineStateBuilder::shaderCompiler() const { |
| 62 | return fGpu->shaderCompiler(); |
| 63 | } |
| 64 | |
Greg Daniel | 5fc5c81 | 2020-04-23 10:30:23 -0400 | [diff] [blame] | 65 | void GrD3DPipelineStateBuilder::finalizeFragmentOutputColor(GrShaderVar& outputColor) { |
| 66 | outputColor.addLayoutQualifier("location = 0, index = 0"); |
| 67 | } |
| 68 | |
| 69 | void GrD3DPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outputColor) { |
| 70 | outputColor.addLayoutQualifier("location = 0, index = 1"); |
| 71 | } |
| 72 | |
Jim Van Verth | 5fba9ae | 2020-09-21 17:18:04 -0400 | [diff] [blame] | 73 | static gr_cp<ID3DBlob> GrCompileHLSLShader(GrD3DGpu* gpu, |
Brian Osman | b71b6ae | 2020-06-16 12:41:25 -0400 | [diff] [blame] | 74 | const SkSL::String& hlsl, |
John Stiles | dbd4e6f | 2021-02-16 13:29:15 -0500 | [diff] [blame] | 75 | SkSL::ProgramKind kind) { |
Greg Daniel | 5fc5c81 | 2020-04-23 10:30:23 -0400 | [diff] [blame] | 76 | const char* compileTarget = nullptr; |
| 77 | switch (kind) { |
John Stiles | dbd4e6f | 2021-02-16 13:29:15 -0500 | [diff] [blame] | 78 | case SkSL::ProgramKind::kVertex: |
Greg Daniel | 5fc5c81 | 2020-04-23 10:30:23 -0400 | [diff] [blame] | 79 | compileTarget = "vs_5_1"; |
| 80 | break; |
John Stiles | dbd4e6f | 2021-02-16 13:29:15 -0500 | [diff] [blame] | 81 | case SkSL::ProgramKind::kGeometry: |
Greg Daniel | 5fc5c81 | 2020-04-23 10:30:23 -0400 | [diff] [blame] | 82 | compileTarget = "gs_5_1"; |
| 83 | break; |
John Stiles | dbd4e6f | 2021-02-16 13:29:15 -0500 | [diff] [blame] | 84 | case SkSL::ProgramKind::kFragment: |
Greg Daniel | 5fc5c81 | 2020-04-23 10:30:23 -0400 | [diff] [blame] | 85 | 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 Verth | 5fba9ae | 2020-09-21 17:18:04 -0400 | [diff] [blame] | 99 | gr_cp<ID3DBlob> shader; |
| 100 | gr_cp<ID3DBlob> errors; |
Brian Osman | b71b6ae | 2020-06-16 12:41:25 -0400 | [diff] [blame] | 101 | HRESULT hr = D3DCompile(hlsl.c_str(), hlsl.length(), nullptr, nullptr, nullptr, "main", |
| 102 | compileTarget, compileFlags, 0, &shader, &errors); |
Greg Daniel | 5fc5c81 | 2020-04-23 10:30:23 -0400 | [diff] [blame] | 103 | if (!SUCCEEDED(hr)) { |
Brian Osman | b71b6ae | 2020-06-16 12:41:25 -0400 | [diff] [blame] | 104 | gpu->getContext()->priv().getShaderErrorHandler()->compileError( |
| 105 | hlsl.c_str(), reinterpret_cast<char*>(errors->GetBufferPointer())); |
Greg Daniel | 5fc5c81 | 2020-04-23 10:30:23 -0400 | [diff] [blame] | 106 | } |
Brian Osman | b71b6ae | 2020-06-16 12:41:25 -0400 | [diff] [blame] | 107 | return shader; |
| 108 | } |
| 109 | |
Jim Van Verth | 5fba9ae | 2020-09-21 17:18:04 -0400 | [diff] [blame] | 110 | bool GrD3DPipelineStateBuilder::loadHLSLFromCache(SkReadBuffer* reader, gr_cp<ID3DBlob> shaders[]) { |
Brian Osman | b71b6ae | 2020-06-16 12:41:25 -0400 | [diff] [blame] | 111 | |
| 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 Stiles | dbd4e6f | 2021-02-16 13:29:15 -0500 | [diff] [blame] | 119 | auto compile = [&](SkSL::ProgramKind kind, GrShaderType shaderType) { |
Greg Daniel | ec3508a | 2020-06-16 14:23:35 -0400 | [diff] [blame] | 120 | if (inputs[shaderType].fRTHeight) { |
| 121 | this->addRTHeightUniform(SKSL_RTHEIGHT_NAME); |
| 122 | } |
Brian Osman | b71b6ae | 2020-06-16 12:41:25 -0400 | [diff] [blame] | 123 | shaders[shaderType] = GrCompileHLSLShader(fGpu, hlsl[shaderType], kind); |
Jim Van Verth | 5fba9ae | 2020-09-21 17:18:04 -0400 | [diff] [blame] | 124 | return shaders[shaderType].get(); |
Brian Osman | b71b6ae | 2020-06-16 12:41:25 -0400 | [diff] [blame] | 125 | }; |
| 126 | |
John Stiles | dbd4e6f | 2021-02-16 13:29:15 -0500 | [diff] [blame] | 127 | return compile(SkSL::ProgramKind::kVertex, kVertex_GrShaderType) && |
| 128 | compile(SkSL::ProgramKind::kFragment, kFragment_GrShaderType) && |
Brian Osman | b71b6ae | 2020-06-16 12:41:25 -0400 | [diff] [blame] | 129 | (hlsl[kGeometry_GrShaderType].empty() || |
John Stiles | dbd4e6f | 2021-02-16 13:29:15 -0500 | [diff] [blame] | 130 | compile(SkSL::ProgramKind::kGeometry, kGeometry_GrShaderType)); |
Brian Osman | b71b6ae | 2020-06-16 12:41:25 -0400 | [diff] [blame] | 131 | } |
| 132 | |
Jim Van Verth | 5fba9ae | 2020-09-21 17:18:04 -0400 | [diff] [blame] | 133 | gr_cp<ID3DBlob> GrD3DPipelineStateBuilder::compileD3DProgram( |
John Stiles | dbd4e6f | 2021-02-16 13:29:15 -0500 | [diff] [blame] | 134 | SkSL::ProgramKind kind, |
Brian Osman | b71b6ae | 2020-06-16 12:41:25 -0400 | [diff] [blame] | 135 | 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 Verth | 5fba9ae | 2020-09-21 17:18:04 -0400 | [diff] [blame] | 145 | return gr_cp<ID3DBlob>(); |
Brian Osman | b71b6ae | 2020-06-16 12:41:25 -0400 | [diff] [blame] | 146 | } |
| 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 Verth | 5fba9ae | 2020-09-21 17:18:04 -0400 | [diff] [blame] | 151 | return gr_cp<ID3DBlob>(); |
Brian Osman | b71b6ae | 2020-06-16 12:41:25 -0400 | [diff] [blame] | 152 | } |
| 153 | |
Greg Daniel | ec3508a | 2020-06-16 14:23:35 -0400 | [diff] [blame] | 154 | if (program->fInputs.fRTHeight) { |
| 155 | this->addRTHeightUniform(SKSL_RTHEIGHT_NAME); |
| 156 | } |
| 157 | |
Brian Osman | b71b6ae | 2020-06-16 12:41:25 -0400 | [diff] [blame] | 158 | return GrCompileHLSLShader(fGpu, *outHLSL, kind); |
Greg Daniel | 5fc5c81 | 2020-04-23 10:30:23 -0400 | [diff] [blame] | 159 | } |
| 160 | |
Jim Van Verth | be259dc | 2020-05-19 11:40:31 -0400 | [diff] [blame] | 161 | static 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 | |
| 219 | static 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 Daniel | 8346834 | 2020-06-17 11:49:06 -0400 | [diff] [blame] | 253 | D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, 1 }; |
Jim Van Verth | be259dc | 2020-05-19 11:40:31 -0400 | [diff] [blame] | 254 | instanceAttributeOffset += attrib.sizeAlign4(); |
| 255 | currentAttrib++; |
| 256 | } |
| 257 | SkASSERT(instanceAttributeOffset == primProc.instanceStride()); |
| 258 | } |
| 259 | |
| 260 | static 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 | |
| 300 | static 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 | |
| 322 | static 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 | |
| 335 | static 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 | |
| 364 | static 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 | |
| 380 | static 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 | |
| 402 | static 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 | |
| 424 | static 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 | |
| 432 | static 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 Daniel | 90cf5d4 | 2020-06-16 09:39:35 -0400 | [diff] [blame] | 444 | const auto& backFace = stencilSettings.postOriginCWFace(origin); |
Jim Van Verth | be259dc | 2020-05-19 11:40:31 -0400 | [diff] [blame] | 445 | |
| 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 Daniel | 90cf5d4 | 2020-06-16 09:39:35 -0400 | [diff] [blame] | 455 | dsDesc->StencilWriteMask = stencilSettings.singleSidedFace().fWriteMask; |
Jim Van Verth | be259dc | 2020-05-19 11:40:31 -0400 | [diff] [blame] | 456 | setup_stencilop_desc(&dsDesc->FrontFace, stencilSettings.singleSidedFace()); |
| 457 | dsDesc->BackFace = dsDesc->FrontFace; |
| 458 | } |
| 459 | } |
| 460 | } |
| 461 | |
| 462 | static D3D12_PRIMITIVE_TOPOLOGY_TYPE gr_primitive_type_to_d3d(GrPrimitiveType primitiveType) { |
| 463 | switch (primitiveType) { |
Jim Van Verth | 83ed957 | 2020-05-21 11:53:55 -0400 | [diff] [blame] | 464 | 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 Verth | be259dc | 2020-05-19 11:40:31 -0400 | [diff] [blame] | 476 | } |
| 477 | } |
| 478 | |
Jim Van Verth | 5fba9ae | 2020-09-21 17:18:04 -0400 | [diff] [blame] | 479 | gr_cp<ID3D12PipelineState> create_pipeline_state( |
Jim Van Verth | 765c592 | 2020-08-10 17:23:50 -0400 | [diff] [blame] | 480 | GrD3DGpu* gpu, const GrProgramInfo& programInfo, const sk_sp<GrD3DRootSignature>& rootSig, |
Jim Van Verth | 5fba9ae | 2020-09-21 17:18:04 -0400 | [diff] [blame] | 481 | 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 Verth | be259dc | 2020-05-19 11:40:31 -0400 | [diff] [blame] | 484 | 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 Verth | 5fba9ae | 2020-09-21 17:18:04 -0400 | [diff] [blame] | 493 | if (geometryShader.get()) { |
Jim Van Verth | be259dc | 2020-05-19 11:40:31 -0400 | [diff] [blame] | 494 | 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 Verth | 765c592 | 2020-08-10 17:23:50 -0400 | [diff] [blame] | 526 | psoDesc.SampleDesc = { numRasterSamples, sampleQualityPattern }; |
Jim Van Verth | be259dc | 2020-05-19 11:40:31 -0400 | [diff] [blame] | 527 | |
| 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 Verth | 5fba9ae | 2020-09-21 17:18:04 -0400 | [diff] [blame] | 534 | gr_cp<ID3D12PipelineState> pipelineState; |
Jim Van Verth | 8bf0194 | 2020-07-01 13:46:57 -0400 | [diff] [blame] | 535 | GR_D3D_CALL_ERRCHECK(gpu->device()->CreateGraphicsPipelineState( |
| 536 | &psoDesc, IID_PPV_ARGS(&pipelineState))); |
Jim Van Verth | be259dc | 2020-05-19 11:40:31 -0400 | [diff] [blame] | 537 | |
| 538 | return pipelineState; |
| 539 | } |
| 540 | |
Brian Osman | b71b6ae | 2020-06-16 12:41:25 -0400 | [diff] [blame] | 541 | static constexpr SkFourByteTag kHLSL_Tag = SkSetFourByteTag('H', 'L', 'S', 'L'); |
| 542 | static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L'); |
| 543 | |
Greg Daniel | fd77673 | 2020-04-23 12:51:13 -0400 | [diff] [blame] | 544 | sk_sp<GrD3DPipelineState> GrD3DPipelineStateBuilder::finalize() { |
Greg Daniel | 5fc5c81 | 2020-04-23 10:30:23 -0400 | [diff] [blame] | 545 | 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 Daniel | 5fc5c81 | 2020-04-23 10:30:23 -0400 | [diff] [blame] | 557 | 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 Osman | b71b6ae | 2020-06-16 12:41:25 -0400 | [diff] [blame] | 564 | 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 Daniel | 5fc5c81 | 2020-04-23 10:30:23 -0400 | [diff] [blame] | 578 | } |
| 579 | |
Jim Van Verth | 40b4de2 | 2020-05-20 09:35:42 -0400 | [diff] [blame] | 580 | const GrPrimitiveProcessor& primProc = this->primitiveProcessor(); |
Jim Van Verth | 5fba9ae | 2020-09-21 17:18:04 -0400 | [diff] [blame] | 581 | gr_cp<ID3DBlob> shaders[kGrShaderTypeCount]; |
Brian Osman | b71b6ae | 2020-06-16 12:41:25 -0400 | [diff] [blame] | 582 | |
| 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 Stiles | dbd4e6f | 2021-02-16 13:29:15 -0500 | [diff] [blame] | 604 | auto compile = [&](SkSL::ProgramKind kind, GrShaderType shaderType) { |
Brian Osman | b71b6ae | 2020-06-16 12:41:25 -0400 | [diff] [blame] | 605 | shaders[shaderType] = this->compileD3DProgram(kind, *sksl[shaderType], settings, |
| 606 | &inputs[shaderType], &hlsl[shaderType]); |
Jim Van Verth | 5fba9ae | 2020-09-21 17:18:04 -0400 | [diff] [blame] | 607 | return shaders[shaderType].get(); |
Brian Osman | b71b6ae | 2020-06-16 12:41:25 -0400 | [diff] [blame] | 608 | }; |
| 609 | |
John Stiles | dbd4e6f | 2021-02-16 13:29:15 -0500 | [diff] [blame] | 610 | if (!compile(SkSL::ProgramKind::kVertex, kVertex_GrShaderType) || |
| 611 | !compile(SkSL::ProgramKind::kFragment, kFragment_GrShaderType)) { |
Greg Daniel | 5fc5c81 | 2020-04-23 10:30:23 -0400 | [diff] [blame] | 612 | return nullptr; |
| 613 | } |
Brian Osman | b71b6ae | 2020-06-16 12:41:25 -0400 | [diff] [blame] | 614 | |
| 615 | if (primProc.willUseGeoShader()) { |
John Stiles | dbd4e6f | 2021-02-16 13:29:15 -0500 | [diff] [blame] | 616 | if (!compile(SkSL::ProgramKind::kGeometry, kGeometry_GrShaderType)) { |
Brian Osman | b71b6ae | 2020-06-16 12:41:25 -0400 | [diff] [blame] | 617 | 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 Osman | 5ca9d1a | 2020-06-16 15:25:33 -0400 | [diff] [blame] | 634 | cacheSkSL ? kSKSL_Tag : kHLSL_Tag, hlsl, inputs, kGrShaderTypeCount); |
Brian Osman | acf2650 | 2021-03-03 13:35:04 +0000 | [diff] [blame] | 635 | persistentCache->store(*key, *data); |
Brian Osman | b71b6ae | 2020-06-16 12:41:25 -0400 | [diff] [blame] | 636 | } |
Greg Daniel | 5fc5c81 | 2020-04-23 10:30:23 -0400 | [diff] [blame] | 637 | } |
| 638 | |
Greg Daniel | c31edc0 | 2020-04-23 11:03:02 -0400 | [diff] [blame] | 639 | sk_sp<GrD3DRootSignature> rootSig = |
| 640 | fGpu->resourceProvider().findOrCreateRootSignature(fUniformHandler.fTextures.count()); |
| 641 | if (!rootSig) { |
| 642 | return nullptr; |
| 643 | } |
Greg Daniel | 5fc5c81 | 2020-04-23 10:30:23 -0400 | [diff] [blame] | 644 | |
| 645 | const GrD3DRenderTarget* rt = static_cast<const GrD3DRenderTarget*>(fRenderTarget); |
Jim Van Verth | 5fba9ae | 2020-09-21 17:18:04 -0400 | [diff] [blame] | 646 | gr_cp<ID3D12PipelineState> pipelineState = create_pipeline_state( |
Brian Osman | b71b6ae | 2020-06-16 12:41:25 -0400 | [diff] [blame] | 647 | fGpu, fProgramInfo, rootSig, std::move(shaders[kVertex_GrShaderType]), |
| 648 | std::move(shaders[kGeometry_GrShaderType]), std::move(shaders[kFragment_GrShaderType]), |
Jim Van Verth | 765c592 | 2020-08-10 17:23:50 -0400 | [diff] [blame] | 649 | rt->dxgiFormat(), rt->stencilDxgiFormat(), rt->sampleQualityPattern()); |
Jim Van Verth | be259dc | 2020-05-19 11:40:31 -0400 | [diff] [blame] | 650 | |
| 651 | return sk_sp<GrD3DPipelineState>(new GrD3DPipelineState(std::move(pipelineState), |
Jim Van Verth | 83ed957 | 2020-05-21 11:53:55 -0400 | [diff] [blame] | 652 | std::move(rootSig), |
Jim Van Verth | be259dc | 2020-05-19 11:40:31 -0400 | [diff] [blame] | 653 | fUniformHandles, |
| 654 | fUniformHandler.fUniforms, |
| 655 | fUniformHandler.fCurrentUBOOffset, |
Jim Van Verth | 40b4de2 | 2020-05-20 09:35:42 -0400 | [diff] [blame] | 656 | fUniformHandler.fSamplers.count(), |
Jim Van Verth | be259dc | 2020-05-19 11:40:31 -0400 | [diff] [blame] | 657 | std::move(fGeometryProcessor), |
| 658 | std::move(fXferProcessor), |
Brian Salomon | 17f95b1 | 2021-02-23 09:35:08 -0500 | [diff] [blame] | 659 | std::move(fFPImpls), |
Jim Van Verth | 40b4de2 | 2020-05-20 09:35:42 -0400 | [diff] [blame] | 660 | primProc.vertexStride(), |
| 661 | primProc.instanceStride())); |
Greg Daniel | 5fc5c81 | 2020-04-23 10:30:23 -0400 | [diff] [blame] | 662 | } |