1 /*
2 * Copyright 2016 Google Inc.
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 "vk/GrVkPipelineStateBuilder.h"
9
10 #include "GrShaderCaps.h"
11 #include "vk/GrVkDescriptorSetManager.h"
12 #include "vk/GrVkGpu.h"
13 #include "vk/GrVkRenderPass.h"
14
15
CreatePipelineState(GrVkGpu * gpu,const GrPipeline & pipeline,const GrStencilSettings & stencil,const GrPrimitiveProcessor & primProc,GrPrimitiveType primitiveType,GrVkPipelineState::Desc * desc,const GrVkRenderPass & renderPass)16 GrVkPipelineState* GrVkPipelineStateBuilder::CreatePipelineState(
17 GrVkGpu* gpu,
18 const GrPipeline& pipeline,
19 const GrStencilSettings& stencil,
20 const GrPrimitiveProcessor& primProc,
21 GrPrimitiveType primitiveType,
22 GrVkPipelineState::Desc* desc,
23 const GrVkRenderPass& renderPass) {
24 // create a builder. This will be handed off to effects so they can use it to add
25 // uniforms, varyings, textures, etc
26 GrVkPipelineStateBuilder builder(gpu, pipeline, primProc, desc);
27
28 GrGLSLExpr4 inputColor;
29 GrGLSLExpr4 inputCoverage;
30
31 if (!builder.emitAndInstallProcs(&inputColor, &inputCoverage)) {
32 builder.cleanupFragmentProcessors();
33 return nullptr;
34 }
35
36 return builder.finalize(stencil, primitiveType, renderPass, desc);
37 }
38
GrVkPipelineStateBuilder(GrVkGpu * gpu,const GrPipeline & pipeline,const GrPrimitiveProcessor & primProc,GrProgramDesc * desc)39 GrVkPipelineStateBuilder::GrVkPipelineStateBuilder(GrVkGpu* gpu,
40 const GrPipeline& pipeline,
41 const GrPrimitiveProcessor& primProc,
42 GrProgramDesc* desc)
43 : INHERITED(pipeline, primProc, desc)
44 , fGpu(gpu)
45 , fVaryingHandler(this)
46 , fUniformHandler(this) {
47 }
48
caps() const49 const GrCaps* GrVkPipelineStateBuilder::caps() const {
50 return fGpu->caps();
51 }
52
finalizeFragmentOutputColor(GrShaderVar & outputColor)53 void GrVkPipelineStateBuilder::finalizeFragmentOutputColor(GrShaderVar& outputColor) {
54 outputColor.addLayoutQualifier("location = 0, index = 0");
55 }
56
finalizeFragmentSecondaryColor(GrShaderVar & outputColor)57 void GrVkPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outputColor) {
58 outputColor.addLayoutQualifier("location = 0, index = 1");
59 }
60
createVkShaderModule(VkShaderStageFlagBits stage,const GrGLSLShaderBuilder & builder,VkShaderModule * shaderModule,VkPipelineShaderStageCreateInfo * stageInfo,const SkSL::Program::Settings & settings,GrVkPipelineState::Desc * desc)61 bool GrVkPipelineStateBuilder::createVkShaderModule(VkShaderStageFlagBits stage,
62 const GrGLSLShaderBuilder& builder,
63 VkShaderModule* shaderModule,
64 VkPipelineShaderStageCreateInfo* stageInfo,
65 const SkSL::Program::Settings& settings,
66 GrVkPipelineState::Desc* desc) {
67 SkString shaderString;
68 for (int i = 0; i < builder.fCompilerStrings.count(); ++i) {
69 if (builder.fCompilerStrings[i]) {
70 shaderString.append(builder.fCompilerStrings[i]);
71 shaderString.append("\n");
72 }
73 }
74
75 SkSL::Program::Inputs inputs;
76 bool result = GrCompileVkShaderModule(fGpu, shaderString.c_str(), stage, shaderModule,
77 stageInfo, settings, &inputs);
78 if (!result) {
79 return false;
80 }
81 if (inputs.fRTHeight) {
82 this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
83 }
84 if (inputs.fFlipY) {
85 desc->setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(
86 this->pipeline().getRenderTarget()->origin()));
87 desc->finalize();
88 }
89 return result;
90 }
91
finalize(const GrStencilSettings & stencil,GrPrimitiveType primitiveType,const GrVkRenderPass & renderPass,GrVkPipelineState::Desc * desc)92 GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& stencil,
93 GrPrimitiveType primitiveType,
94 const GrVkRenderPass& renderPass,
95 GrVkPipelineState::Desc* desc) {
96 VkDescriptorSetLayout dsLayout[2];
97 VkPipelineLayout pipelineLayout;
98 VkShaderModule vertShaderModule;
99 VkShaderModule fragShaderModule;
100
101 GrVkResourceProvider& resourceProvider = fGpu->resourceProvider();
102 // These layouts are not owned by the PipelineStateBuilder and thus should not be destroyed
103 dsLayout[GrVkUniformHandler::kUniformBufferDescSet] = resourceProvider.getUniformDSLayout();
104
105 GrVkDescriptorSetManager::Handle samplerDSHandle;
106 resourceProvider.getSamplerDescriptorSetHandle(fUniformHandler, &samplerDSHandle);
107 dsLayout[GrVkUniformHandler::kSamplerDescSet] =
108 resourceProvider.getSamplerDSLayout(samplerDSHandle);
109
110 // Create the VkPipelineLayout
111 VkPipelineLayoutCreateInfo layoutCreateInfo;
112 memset(&layoutCreateInfo, 0, sizeof(VkPipelineLayoutCreateFlags));
113 layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
114 layoutCreateInfo.pNext = 0;
115 layoutCreateInfo.flags = 0;
116 layoutCreateInfo.setLayoutCount = 2;
117 layoutCreateInfo.pSetLayouts = dsLayout;
118 layoutCreateInfo.pushConstantRangeCount = 0;
119 layoutCreateInfo.pPushConstantRanges = nullptr;
120
121 GR_VK_CALL_ERRCHECK(fGpu->vkInterface(), CreatePipelineLayout(fGpu->device(),
122 &layoutCreateInfo,
123 nullptr,
124 &pipelineLayout));
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 VkPipelineShaderStageCreateInfo shaderStageInfo[2];
136 SkSL::Program::Settings settings;
137 settings.fFlipY = this->pipeline().getRenderTarget()->origin() != kTopLeft_GrSurfaceOrigin;
138 SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
139 fVS,
140 &vertShaderModule,
141 &shaderStageInfo[0],
142 settings,
143 desc));
144
145 // TODO: geometry shader support.
146 SkASSERT(!this->primitiveProcessor().willUseGeoShader());
147
148 SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
149 fFS,
150 &fragShaderModule,
151 &shaderStageInfo[1],
152 settings,
153 desc));
154
155 GrVkPipeline* pipeline = resourceProvider.createPipeline(fPipeline,
156 stencil,
157 fPrimProc,
158 shaderStageInfo,
159 2,
160 primitiveType,
161 renderPass,
162 pipelineLayout);
163 GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), vertShaderModule,
164 nullptr));
165 GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), fragShaderModule,
166 nullptr));
167
168 if (!pipeline) {
169 GR_VK_CALL(fGpu->vkInterface(), DestroyPipelineLayout(fGpu->device(), pipelineLayout,
170 nullptr));
171 this->cleanupFragmentProcessors();
172 return nullptr;
173 }
174
175 return new GrVkPipelineState(fGpu,
176 *desc,
177 pipeline,
178 pipelineLayout,
179 samplerDSHandle,
180 fUniformHandles,
181 fUniformHandler.fUniforms,
182 fUniformHandler.fCurrentVertexUBOOffset,
183 fUniformHandler.fCurrentFragmentUBOOffset,
184 (uint32_t)fUniformHandler.numSamplers(),
185 fGeometryProcessor,
186 fXferProcessor,
187 fFragmentProcessors);
188 }
189
190