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