blob: 29630683a8f6f1af857bec6665a4b4f762d49be0 [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"
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 Danielc31edc02020-04-23 11:03:02 -040022#include "src/gpu/d3d/GrD3DRootSignature.h"
Greg Daniel5fc5c812020-04-23 10:30:23 -040023#include "src/sksl/SkSLCompiler.h"
24
25#include <d3dcompiler.h>
26
27typedef size_t shader_size;
28
29std::unique_ptr<GrD3DPipelineState> GrD3DPipelineStateBuilder::CreatePipelineState(
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
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
69void 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
123std::unique_ptr<GrD3DPipelineState> GrD3DPipelineStateBuilder::finalize() {
124 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
125
126 // We need to enable the following extensions so that the compiler can correctly make spir-v
127 // from our glsl shaders.
128 fVS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
129 fFS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
130 fVS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
131 fFS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
132
133 this->finalizeShaders();
134
135 SkSL::Program::Settings settings;
136 settings.fCaps = this->caps()->shaderCaps();
137 settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin;
138 settings.fSharpenTextures =
139 this->gpu()->getContext()->priv().options().fSharpenMipmappedTextures;
140 settings.fRTHeightOffset = fUniformHandler.getRTHeightOffset();
141 settings.fRTHeightBinding = 0;
142 settings.fRTHeightSet = 0;
143
144 gr_cp<ID3DBlob> vertexShader;
145 gr_cp<ID3DBlob> geometryShader;
146 gr_cp<ID3DBlob> pixelShader;
147 SkSL::Program::Inputs vertInputs, fragInputs, geomInputs;
148
149 this->compileD3DProgram(SkSL::Program::kVertex_Kind, fVS.fCompilerString, settings,
150 &vertexShader, &vertInputs);
151 this->compileD3DProgram(SkSL::Program::kFragment_Kind, fFS.fCompilerString, settings,
152 &pixelShader, &fragInputs);
153
154 if (!vertexShader.get() || !pixelShader.get()) {
155 return nullptr;
156 }
157
158 if (this->primitiveProcessor().willUseGeoShader()) {
159 this->compileD3DProgram(SkSL::Program::kGeometry_Kind, fGS.fCompilerString, settings,
160 &geometryShader, &geomInputs);
161 if (!geometryShader.get()) {
162 return nullptr;
163 }
164 }
165
Greg Danielc31edc02020-04-23 11:03:02 -0400166 sk_sp<GrD3DRootSignature> rootSig =
167 fGpu->resourceProvider().findOrCreateRootSignature(fUniformHandler.fTextures.count());
168 if (!rootSig) {
169 return nullptr;
170 }
Greg Daniel5fc5c812020-04-23 10:30:23 -0400171
172 const GrD3DRenderTarget* rt = static_cast<const GrD3DRenderTarget*>(fRenderTarget);
Greg Danielc31edc02020-04-23 11:03:02 -0400173 return GrD3DPipelineState::Make(fGpu, fProgramInfo, std::move(rootSig),
Greg Daniel5fc5c812020-04-23 10:30:23 -0400174 std::move(vertexShader), std::move(geometryShader),
175 std::move(pixelShader), rt->dxgiFormat(),
176 rt->stencilDxgiFormat(), rt->sampleQualityLevel());
177}