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 if (!builder.emitAndInstallProcs()) {
29 builder.cleanupFragmentProcessors();
30 return nullptr;
31 }
32
33 return builder.finalize(stencil, primitiveType, renderPass, desc);
34 }
35
GrVkPipelineStateBuilder(GrVkGpu * gpu,const GrPipeline & pipeline,const GrPrimitiveProcessor & primProc,GrProgramDesc * desc)36 GrVkPipelineStateBuilder::GrVkPipelineStateBuilder(GrVkGpu* gpu,
37 const GrPipeline& pipeline,
38 const GrPrimitiveProcessor& primProc,
39 GrProgramDesc* desc)
40 : INHERITED(pipeline, primProc, desc)
41 , fGpu(gpu)
42 , fVaryingHandler(this)
43 , fUniformHandler(this) {
44 }
45
caps() const46 const GrCaps* GrVkPipelineStateBuilder::caps() const {
47 return fGpu->caps();
48 }
49
finalizeFragmentOutputColor(GrShaderVar & outputColor)50 void GrVkPipelineStateBuilder::finalizeFragmentOutputColor(GrShaderVar& outputColor) {
51 outputColor.addLayoutQualifier("location = 0, index = 0");
52 }
53
finalizeFragmentSecondaryColor(GrShaderVar & outputColor)54 void GrVkPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outputColor) {
55 outputColor.addLayoutQualifier("location = 0, index = 1");
56 }
57
createVkShaderModule(VkShaderStageFlagBits stage,const GrGLSLShaderBuilder & builder,VkShaderModule * shaderModule,VkPipelineShaderStageCreateInfo * stageInfo,const SkSL::Program::Settings & settings,GrVkPipelineState::Desc * desc)58 bool GrVkPipelineStateBuilder::createVkShaderModule(VkShaderStageFlagBits stage,
59 const GrGLSLShaderBuilder& builder,
60 VkShaderModule* shaderModule,
61 VkPipelineShaderStageCreateInfo* stageInfo,
62 const SkSL::Program::Settings& settings,
63 GrVkPipelineState::Desc* desc) {
64 SkString shaderString;
65 for (int i = 0; i < builder.fCompilerStrings.count(); ++i) {
66 if (builder.fCompilerStrings[i]) {
67 shaderString.append(builder.fCompilerStrings[i]);
68 shaderString.append("\n");
69 }
70 }
71
72 SkSL::Program::Inputs inputs;
73 bool result = GrCompileVkShaderModule(fGpu, shaderString.c_str(), stage, shaderModule,
74 stageInfo, settings, &inputs);
75 if (!result) {
76 return false;
77 }
78 if (inputs.fRTHeight) {
79 this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
80 }
81 if (inputs.fFlipY) {
82 desc->setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(
83 this->pipeline().getRenderTarget()->origin()));
84 desc->finalize();
85 }
86 return result;
87 }
88
finalize(const GrStencilSettings & stencil,GrPrimitiveType primitiveType,const GrVkRenderPass & renderPass,GrVkPipelineState::Desc * desc)89 GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& stencil,
90 GrPrimitiveType primitiveType,
91 const GrVkRenderPass& renderPass,
92 GrVkPipelineState::Desc* desc) {
93 VkDescriptorSetLayout dsLayout[3];
94 VkPipelineLayout pipelineLayout;
95 VkShaderModule vertShaderModule = VK_NULL_HANDLE;
96 VkShaderModule geomShaderModule = VK_NULL_HANDLE;
97 VkShaderModule fragShaderModule = VK_NULL_HANDLE;
98
99 GrVkResourceProvider& resourceProvider = fGpu->resourceProvider();
100 // These layouts are not owned by the PipelineStateBuilder and thus should not be destroyed
101 dsLayout[GrVkUniformHandler::kUniformBufferDescSet] = resourceProvider.getUniformDSLayout();
102
103 GrVkDescriptorSetManager::Handle samplerDSHandle;
104 resourceProvider.getSamplerDescriptorSetHandle(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
105 fUniformHandler, &samplerDSHandle);
106 dsLayout[GrVkUniformHandler::kSamplerDescSet] =
107 resourceProvider.getSamplerDSLayout(samplerDSHandle);
108
109 GrVkDescriptorSetManager::Handle texelBufferDSHandle;
110 resourceProvider.getSamplerDescriptorSetHandle(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
111 fUniformHandler, &texelBufferDSHandle);
112 dsLayout[GrVkUniformHandler::kTexelBufferDescSet] =
113 resourceProvider.getSamplerDSLayout(texelBufferDSHandle);
114
115 // Create the VkPipelineLayout
116 VkPipelineLayoutCreateInfo layoutCreateInfo;
117 memset(&layoutCreateInfo, 0, sizeof(VkPipelineLayoutCreateFlags));
118 layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
119 layoutCreateInfo.pNext = 0;
120 layoutCreateInfo.flags = 0;
121 layoutCreateInfo.setLayoutCount = 3;
122 layoutCreateInfo.pSetLayouts = dsLayout;
123 layoutCreateInfo.pushConstantRangeCount = 0;
124 layoutCreateInfo.pPushConstantRanges = nullptr;
125
126 GR_VK_CALL_ERRCHECK(fGpu->vkInterface(), CreatePipelineLayout(fGpu->device(),
127 &layoutCreateInfo,
128 nullptr,
129 &pipelineLayout));
130
131 // We need to enable the following extensions so that the compiler can correctly make spir-v
132 // from our glsl shaders.
133 fVS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
134 fFS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
135 fVS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
136 fFS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
137
138 this->finalizeShaders();
139
140 VkPipelineShaderStageCreateInfo shaderStageInfo[3];
141 SkSL::Program::Settings settings;
142 settings.fCaps = this->caps()->shaderCaps();
143 settings.fFlipY = this->pipeline().getRenderTarget()->origin() != kTopLeft_GrSurfaceOrigin;
144 SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
145 fVS,
146 &vertShaderModule,
147 &shaderStageInfo[0],
148 settings,
149 desc));
150
151 SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
152 fFS,
153 &fragShaderModule,
154 &shaderStageInfo[1],
155 settings,
156 desc));
157
158 int numShaderStages = 2; // We always have at least vertex and fragment stages.
159 if (this->primitiveProcessor().willUseGeoShader()) {
160 SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_GEOMETRY_BIT,
161 fGS,
162 &geomShaderModule,
163 &shaderStageInfo[2],
164 settings,
165 desc));
166 ++numShaderStages;
167 }
168
169 GrVkPipeline* pipeline = resourceProvider.createPipeline(fPipeline,
170 stencil,
171 fPrimProc,
172 shaderStageInfo,
173 numShaderStages,
174 primitiveType,
175 renderPass,
176 pipelineLayout);
177 GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), vertShaderModule,
178 nullptr));
179 GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), fragShaderModule,
180 nullptr));
181 // This if check should not be needed since calling destroy on a VK_NULL_HANDLE is allowed.
182 // However this is causing a crash in certain drivers (e.g. NVidia).
183 if (this->primitiveProcessor().willUseGeoShader()) {
184 GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), geomShaderModule,
185 nullptr));
186 }
187
188 if (!pipeline) {
189 GR_VK_CALL(fGpu->vkInterface(), DestroyPipelineLayout(fGpu->device(), pipelineLayout,
190 nullptr));
191 this->cleanupFragmentProcessors();
192 return nullptr;
193 }
194
195 return new GrVkPipelineState(fGpu,
196 *desc,
197 pipeline,
198 pipelineLayout,
199 samplerDSHandle,
200 texelBufferDSHandle,
201 fUniformHandles,
202 fUniformHandler.fUniforms,
203 fUniformHandler.fCurrentGeometryUBOOffset,
204 fUniformHandler.fCurrentFragmentUBOOffset,
205 (uint32_t)fUniformHandler.numSamplers(),
206 (uint32_t)fUniformHandler.numTexelBuffers(),
207 fGeometryProcessor,
208 fXferProcessor,
209 fFragmentProcessors);
210 }
211
212