blob: f75100baac8bee93b2b4232a4523dc5a290dec44 [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"
22#include "src/sksl/SkSLCompiler.h"
23
24#include <d3dcompiler.h>
25
26typedef size_t shader_size;
27
28std::unique_ptr<GrD3DPipelineState> GrD3DPipelineStateBuilder::CreatePipelineState(
29 GrD3DGpu* gpu,
30 GrRenderTarget* renderTarget,
31 const GrProgramDesc& desc,
32 const GrProgramInfo& programInfo) {
33 // ensure that we use "." as a decimal separator when creating SkSL code
34 GrAutoLocaleSetter als("C");
35
36 // create a builder. This will be handed off to effects so they can use it to add
37 // uniforms, varyings, textures, etc
38 GrD3DPipelineStateBuilder builder(gpu, renderTarget, desc, programInfo);
39
40 if (!builder.emitAndInstallProcs()) {
41 return nullptr;
42 }
43
44 return builder.finalize();
45}
46
47GrD3DPipelineStateBuilder::GrD3DPipelineStateBuilder(GrD3DGpu* gpu,
48 GrRenderTarget* renderTarget,
49 const GrProgramDesc& desc,
50 const GrProgramInfo& programInfo)
51 : INHERITED(renderTarget, desc, programInfo)
52 , fGpu(gpu)
53 , fVaryingHandler(this)
54 , fUniformHandler(this) {}
55
56const GrCaps* GrD3DPipelineStateBuilder::caps() const {
57 return fGpu->caps();
58}
59
60void GrD3DPipelineStateBuilder::finalizeFragmentOutputColor(GrShaderVar& outputColor) {
61 outputColor.addLayoutQualifier("location = 0, index = 0");
62}
63
64void GrD3DPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outputColor) {
65 outputColor.addLayoutQualifier("location = 0, index = 1");
66}
67
68void GrD3DPipelineStateBuilder::compileD3DProgram(SkSL::Program::Kind kind,
69 const SkSL::String& sksl,
70 const SkSL::Program::Settings& settings,
71 ID3DBlob** shader,
72 SkSL::Program::Inputs* outInputs) {
73 auto errorHandler = fGpu->getContext()->priv().getShaderErrorHandler();
74 std::unique_ptr<SkSL::Program> program = fGpu->shaderCompiler()->convertProgram(
75 kind, sksl, settings);
76 if (!program) {
77 errorHandler->compileError(sksl.c_str(),
78 fGpu->shaderCompiler()->errorText().c_str());
79 return;
80 }
81 *outInputs = program->fInputs;
82 SkSL::String outHLSL;
83 if (!fGpu->shaderCompiler()->toHLSL(*program, &outHLSL)) {
84 errorHandler->compileError(sksl.c_str(),
85 fGpu->shaderCompiler()->errorText().c_str());
86 return;
87 }
88
89 const char* compileTarget = nullptr;
90 switch (kind) {
91 case SkSL::Program::kVertex_Kind:
92 compileTarget = "vs_5_1";
93 break;
94 case SkSL::Program::kGeometry_Kind:
95 compileTarget = "gs_5_1";
96 break;
97 case SkSL::Program::kFragment_Kind:
98 compileTarget = "ps_5_1";
99 break;
100 default:
101 SkUNREACHABLE;
102 }
103
104 uint32_t compileFlags = 0;
105#ifdef SK_DEBUG
106 // Enable better shader debugging with the graphics debugging tools.
107 compileFlags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
108#endif
109 // SPRIV-cross does matrix multiplication expecting row major matrices
110 compileFlags |= D3DCOMPILE_PACK_MATRIX_ROW_MAJOR;
111
112 // TODO: D3D Static Function
113 gr_cp<ID3DBlob> errors;
114 HRESULT hr = D3DCompile(outHLSL.c_str(), outHLSL.length(), nullptr, nullptr, nullptr, "main",
115 compileTarget, compileFlags, 0, shader, &errors);
116 if (!SUCCEEDED(hr)) {
117 errorHandler->compileError(outHLSL.c_str(),
118 reinterpret_cast<char*>(errors->GetBufferPointer()));
119 }
120}
121
122std::unique_ptr<GrD3DPipelineState> GrD3DPipelineStateBuilder::finalize() {
123 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
124
125 // We need to enable the following extensions so that the compiler can correctly make spir-v
126 // from our glsl shaders.
127 fVS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
128 fFS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
129 fVS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
130 fFS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
131
132 this->finalizeShaders();
133
134 SkSL::Program::Settings settings;
135 settings.fCaps = this->caps()->shaderCaps();
136 settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin;
137 settings.fSharpenTextures =
138 this->gpu()->getContext()->priv().options().fSharpenMipmappedTextures;
139 settings.fRTHeightOffset = fUniformHandler.getRTHeightOffset();
140 settings.fRTHeightBinding = 0;
141 settings.fRTHeightSet = 0;
142
143 gr_cp<ID3DBlob> vertexShader;
144 gr_cp<ID3DBlob> geometryShader;
145 gr_cp<ID3DBlob> pixelShader;
146 SkSL::Program::Inputs vertInputs, fragInputs, geomInputs;
147
148 this->compileD3DProgram(SkSL::Program::kVertex_Kind, fVS.fCompilerString, settings,
149 &vertexShader, &vertInputs);
150 this->compileD3DProgram(SkSL::Program::kFragment_Kind, fFS.fCompilerString, settings,
151 &pixelShader, &fragInputs);
152
153 if (!vertexShader.get() || !pixelShader.get()) {
154 return nullptr;
155 }
156
157 if (this->primitiveProcessor().willUseGeoShader()) {
158 this->compileD3DProgram(SkSL::Program::kGeometry_Kind, fGS.fCompilerString, settings,
159 &geometryShader, &geomInputs);
160 if (!geometryShader.get()) {
161 return nullptr;
162 }
163 }
164
165 gr_cp<ID3D12RootSignature> rootSignature;
166
167 const GrD3DRenderTarget* rt = static_cast<const GrD3DRenderTarget*>(fRenderTarget);
168 return GrD3DPipelineState::Make(fGpu, fProgramInfo, std::move(rootSignature),
169 std::move(vertexShader), std::move(geometryShader),
170 std::move(pixelShader), rt->dxgiFormat(),
171 rt->stencilDxgiFormat(), rt->sampleQualityLevel());
172}