blob: 323ea669463c35b1b897194d54f4ecdbe1a5f3ac [file] [log] [blame]
jvanverth992ad362016-02-26 09:21:02 -08001/*
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
egdaniel22281c12016-03-23 13:49:40 -07008#include "vk/GrVkPipelineStateBuilder.h"
jvanverth992ad362016-02-26 09:21:02 -08009
10#include "vk/GrVkGpu.h"
11#include "vk/GrVkRenderPass.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070012#if USE_SKSL
13#include "SkSLCompiler.h"
14#endif
jvanverth992ad362016-02-26 09:21:02 -080015
egdaniel22281c12016-03-23 13:49:40 -070016GrVkPipelineState* GrVkPipelineStateBuilder::CreatePipelineState(
17 GrVkGpu* gpu,
18 const GrPipeline& pipeline,
19 const GrPrimitiveProcessor& primProc,
20 GrPrimitiveType primitiveType,
21 const GrVkPipelineState::Desc& desc,
22 const GrVkRenderPass& renderPass) {
jvanverth992ad362016-02-26 09:21:02 -080023 // create a builder. This will be handed off to effects so they can use it to add
24 // uniforms, varyings, textures, etc
egdaniel22281c12016-03-23 13:49:40 -070025 GrVkPipelineStateBuilder builder(gpu, pipeline, primProc, desc.fProgramDesc);
jvanverth992ad362016-02-26 09:21:02 -080026
27 GrGLSLExpr4 inputColor;
28 GrGLSLExpr4 inputCoverage;
29
cdalton9c3f1432016-03-11 10:07:37 -080030 if (!builder.emitAndInstallProcs(&inputColor, &inputCoverage)) {
jvanverth992ad362016-02-26 09:21:02 -080031 builder.cleanupFragmentProcessors();
32 return nullptr;
33 }
34
egdaniel22281c12016-03-23 13:49:40 -070035 return builder.finalize(primitiveType, renderPass, desc);
jvanverth992ad362016-02-26 09:21:02 -080036}
37
egdaniel22281c12016-03-23 13:49:40 -070038GrVkPipelineStateBuilder::GrVkPipelineStateBuilder(GrVkGpu* gpu,
39 const GrPipeline& pipeline,
40 const GrPrimitiveProcessor& primProc,
41 const GrVkProgramDesc& desc)
halcanary9d524f22016-03-29 09:03:52 -070042 : INHERITED(pipeline, primProc, desc)
jvanverth992ad362016-02-26 09:21:02 -080043 , fGpu(gpu)
halcanary9d524f22016-03-29 09:03:52 -070044 , fVaryingHandler(this)
jvanverth992ad362016-02-26 09:21:02 -080045 , fUniformHandler(this) {
46}
47
egdaniel22281c12016-03-23 13:49:40 -070048const GrCaps* GrVkPipelineStateBuilder::caps() const {
jvanverth992ad362016-02-26 09:21:02 -080049 return fGpu->caps();
50}
egdaniel22281c12016-03-23 13:49:40 -070051const GrGLSLCaps* GrVkPipelineStateBuilder::glslCaps() const {
jvanverth992ad362016-02-26 09:21:02 -080052 return fGpu->vkCaps().glslCaps();
53}
54
egdaniel22281c12016-03-23 13:49:40 -070055void GrVkPipelineStateBuilder::finalizeFragmentOutputColor(GrGLSLShaderVar& outputColor) {
egdaniel3a15fd42016-04-05 11:00:29 -070056 outputColor.setLayoutQualifier("location = 0, index = 0");
jvanverth992ad362016-02-26 09:21:02 -080057}
58
egdanield632bb42016-03-30 12:06:48 -070059void GrVkPipelineStateBuilder::finalizeFragmentSecondaryColor(GrGLSLShaderVar& outputColor) {
egdaniel3a15fd42016-04-05 11:00:29 -070060 outputColor.setLayoutQualifier("location = 0, index = 1");
egdanield632bb42016-03-30 12:06:48 -070061}
62
jvanverth992ad362016-02-26 09:21:02 -080063VkShaderStageFlags visibility_to_vk_stage_flags(uint32_t visibility) {
64 VkShaderStageFlags flags = 0;
65
66 if (visibility & kVertex_GrShaderFlag) {
67 flags |= VK_SHADER_STAGE_VERTEX_BIT;
68 }
69 if (visibility & kGeometry_GrShaderFlag) {
70 flags |= VK_SHADER_STAGE_GEOMETRY_BIT;
71 }
72 if (visibility & kFragment_GrShaderFlag) {
73 flags |= VK_SHADER_STAGE_FRAGMENT_BIT;
74 }
75 return flags;
76}
77
ethannicholasb3058bd2016-07-01 08:22:01 -070078#if USE_SKSL
79SkSL::Program::Kind vk_shader_stage_to_skiasl_kind(VkShaderStageFlagBits stage) {
80 if (VK_SHADER_STAGE_VERTEX_BIT == stage) {
81 return SkSL::Program::kVertex_Kind;
82 }
83 SkASSERT(VK_SHADER_STAGE_FRAGMENT_BIT == stage);
84 return SkSL::Program::kFragment_Kind;
85}
86#else
jvanverth992ad362016-02-26 09:21:02 -080087shaderc_shader_kind vk_shader_stage_to_shaderc_kind(VkShaderStageFlagBits stage) {
88 if (VK_SHADER_STAGE_VERTEX_BIT == stage) {
89 return shaderc_glsl_vertex_shader;
90 }
91 SkASSERT(VK_SHADER_STAGE_FRAGMENT_BIT == stage);
92 return shaderc_glsl_fragment_shader;
93}
ethannicholasb3058bd2016-07-01 08:22:01 -070094#endif
jvanverth992ad362016-02-26 09:21:02 -080095
ethannicholasb3058bd2016-07-01 08:22:01 -070096#include <fstream>
97#include <sstream>
egdaniel22281c12016-03-23 13:49:40 -070098bool GrVkPipelineStateBuilder::CreateVkShaderModule(const GrVkGpu* gpu,
99 VkShaderStageFlagBits stage,
100 const GrGLSLShaderBuilder& builder,
101 VkShaderModule* shaderModule,
102 VkPipelineShaderStageCreateInfo* stageInfo) {
jvanverth992ad362016-02-26 09:21:02 -0800103 SkString shaderString;
104 for (int i = 0; i < builder.fCompilerStrings.count(); ++i) {
105 if (builder.fCompilerStrings[i]) {
106 shaderString.append(builder.fCompilerStrings[i]);
107 shaderString.append("\n");
108 }
109 }
110
jvanverth992ad362016-02-26 09:21:02 -0800111 VkShaderModuleCreateInfo moduleCreateInfo;
112 memset(&moduleCreateInfo, 0, sizeof(VkShaderModuleCreateInfo));
113 moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
114 moduleCreateInfo.pNext = nullptr;
115 moduleCreateInfo.flags = 0;
egdanielc5ec1402016-03-28 12:14:42 -0700116
ethannicholasb3058bd2016-07-01 08:22:01 -0700117#if USE_SKSL
118 std::string code;
119#else
egdanielb60c3372016-04-01 08:47:35 -0700120 shaderc_compilation_result_t result = nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -0700121#endif
egdanielc5ec1402016-03-28 12:14:42 -0700122
123 if (gpu->vkCaps().canUseGLSLForShaderModule()) {
124 moduleCreateInfo.codeSize = strlen(shaderString.c_str());
125 moduleCreateInfo.pCode = (const uint32_t*)shaderString.c_str();
126 } else {
127
ethannicholasb3058bd2016-07-01 08:22:01 -0700128#if USE_SKSL
129 bool result = gpu->shaderCompiler()->toSPIRV(vk_shader_stage_to_skiasl_kind(stage),
130 std::string(shaderString.c_str()),
131 &code);
132 if (!result) {
133 SkDebugf("%s\n", gpu->shaderCompiler()->errorText().c_str());
134 return false;
135 }
136 moduleCreateInfo.codeSize = code.size();
137 moduleCreateInfo.pCode = (const uint32_t*) code.c_str();
138#else
egdanielc5ec1402016-03-28 12:14:42 -0700139 shaderc_compiler_t compiler = gpu->shadercCompiler();
140
141 shaderc_compile_options_t options = shaderc_compile_options_initialize();
egdanielc5ec1402016-03-28 12:14:42 -0700142
143 shaderc_shader_kind shadercStage = vk_shader_stage_to_shaderc_kind(stage);
144 result = shaderc_compile_into_spv(compiler,
145 shaderString.c_str(),
146 strlen(shaderString.c_str()),
147 shadercStage,
148 "shader",
149 "main",
150 options);
151 shaderc_compile_options_release(options);
152#ifdef SK_DEBUG
153 if (shaderc_result_get_num_errors(result)) {
154 SkDebugf("%s\n", shaderString.c_str());
155 SkDebugf("%s\n", shaderc_result_get_error_message(result));
156 return false;
157 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700158#endif // SK_DEBUG
egdanielc5ec1402016-03-28 12:14:42 -0700159
160 moduleCreateInfo.codeSize = shaderc_result_get_length(result);
161 moduleCreateInfo.pCode = (const uint32_t*)shaderc_result_get_bytes(result);
ethannicholasb3058bd2016-07-01 08:22:01 -0700162#endif // USE_SKSL
egdanielc5ec1402016-03-28 12:14:42 -0700163 }
jvanverth992ad362016-02-26 09:21:02 -0800164
165 VkResult err = GR_VK_CALL(gpu->vkInterface(), CreateShaderModule(gpu->device(),
166 &moduleCreateInfo,
167 nullptr,
168 shaderModule));
ethannicholasb3058bd2016-07-01 08:22:01 -0700169
egdanielc5ec1402016-03-28 12:14:42 -0700170 if (!gpu->vkCaps().canUseGLSLForShaderModule()) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700171#if !USE_SKSL
egdanielc5ec1402016-03-28 12:14:42 -0700172 shaderc_result_release(result);
ethannicholasb3058bd2016-07-01 08:22:01 -0700173#endif
egdanielc5ec1402016-03-28 12:14:42 -0700174 }
jvanverth992ad362016-02-26 09:21:02 -0800175 if (err) {
176 return false;
177 }
178
179 memset(stageInfo, 0, sizeof(VkPipelineShaderStageCreateInfo));
180 stageInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
181 stageInfo->pNext = nullptr;
182 stageInfo->flags = 0;
183 stageInfo->stage = stage;
184 stageInfo->module = *shaderModule;
185 stageInfo->pName = "main";
186 stageInfo->pSpecializationInfo = nullptr;
187
188 return true;
189}
190
egdaniel22281c12016-03-23 13:49:40 -0700191GrVkPipelineState* GrVkPipelineStateBuilder::finalize(GrPrimitiveType primitiveType,
192 const GrVkRenderPass& renderPass,
193 const GrVkPipelineState::Desc& desc) {
jvanverth992ad362016-02-26 09:21:02 -0800194 VkDescriptorSetLayout dsLayout[2];
195 VkPipelineLayout pipelineLayout;
196 VkShaderModule vertShaderModule;
197 VkShaderModule fragShaderModule;
198
egdaniel09aa1fc2016-04-20 07:09:46 -0700199 uint32_t numSamplers = (uint32_t)fUniformHandler.numSamplers();
jvanverth992ad362016-02-26 09:21:02 -0800200
201 SkAutoTDeleteArray<VkDescriptorSetLayoutBinding> dsSamplerBindings(
202 new VkDescriptorSetLayoutBinding[numSamplers]);
203 for (uint32_t i = 0; i < numSamplers; ++i) {
egdaniel09aa1fc2016-04-20 07:09:46 -0700204 const GrVkGLSLSampler& sampler =
205 static_cast<const GrVkGLSLSampler&>(fUniformHandler.getSampler(i));
206 SkASSERT(sampler.binding() == i);
207 dsSamplerBindings[i].binding = sampler.binding();
jvanverth992ad362016-02-26 09:21:02 -0800208 dsSamplerBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
209 dsSamplerBindings[i].descriptorCount = 1;
egdaniel09aa1fc2016-04-20 07:09:46 -0700210 dsSamplerBindings[i].stageFlags = visibility_to_vk_stage_flags(sampler.visibility());
jvanverth992ad362016-02-26 09:21:02 -0800211 dsSamplerBindings[i].pImmutableSamplers = nullptr;
212 }
213
214 VkDescriptorSetLayoutCreateInfo dsSamplerLayoutCreateInfo;
215 memset(&dsSamplerLayoutCreateInfo, 0, sizeof(VkDescriptorSetLayoutCreateInfo));
216 dsSamplerLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
217 dsSamplerLayoutCreateInfo.pNext = nullptr;
218 dsSamplerLayoutCreateInfo.flags = 0;
egdaniel09aa1fc2016-04-20 07:09:46 -0700219 dsSamplerLayoutCreateInfo.bindingCount = numSamplers;
jvanverth992ad362016-02-26 09:21:02 -0800220 // Setting to nullptr fixes an error in the param checker validation layer. Even though
221 // bindingCount is 0 (which is valid), it still tries to validate pBindings unless it is null.
egdaniel09aa1fc2016-04-20 07:09:46 -0700222 dsSamplerLayoutCreateInfo.pBindings = numSamplers ? dsSamplerBindings.get() : nullptr;
jvanverth992ad362016-02-26 09:21:02 -0800223
224 GR_VK_CALL_ERRCHECK(fGpu->vkInterface(),
225 CreateDescriptorSetLayout(fGpu->device(),
226 &dsSamplerLayoutCreateInfo,
227 nullptr,
228 &dsLayout[GrVkUniformHandler::kSamplerDescSet]));
229
egdaniel778555c2016-05-02 06:50:36 -0700230 // This layout is not owned by the PipelineStateBuilder and thus should no be destroyed
231 dsLayout[GrVkUniformHandler::kUniformBufferDescSet] = fGpu->resourceProvider().getUniDSLayout();
jvanverth992ad362016-02-26 09:21:02 -0800232
233 // Create the VkPipelineLayout
234 VkPipelineLayoutCreateInfo layoutCreateInfo;
235 memset(&layoutCreateInfo, 0, sizeof(VkPipelineLayoutCreateFlags));
236 layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
237 layoutCreateInfo.pNext = 0;
238 layoutCreateInfo.flags = 0;
239 layoutCreateInfo.setLayoutCount = 2;
240 layoutCreateInfo.pSetLayouts = dsLayout;
241 layoutCreateInfo.pushConstantRangeCount = 0;
242 layoutCreateInfo.pPushConstantRanges = nullptr;
243
244 GR_VK_CALL_ERRCHECK(fGpu->vkInterface(), CreatePipelineLayout(fGpu->device(),
245 &layoutCreateInfo,
246 nullptr,
247 &pipelineLayout));
248
249 // We need to enable the following extensions so that the compiler can correctly make spir-v
250 // from our glsl shaders.
251 fVS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
252 fFS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
253 fVS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
254 fFS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
255
256 this->finalizeShaders();
257
258 VkPipelineShaderStageCreateInfo shaderStageInfo[2];
259 SkAssertResult(CreateVkShaderModule(fGpu,
260 VK_SHADER_STAGE_VERTEX_BIT,
261 fVS,
262 &vertShaderModule,
263 &shaderStageInfo[0]));
264
265 SkAssertResult(CreateVkShaderModule(fGpu,
266 VK_SHADER_STAGE_FRAGMENT_BIT,
267 fFS,
268 &fragShaderModule,
269 &shaderStageInfo[1]));
270
271 GrVkResourceProvider& resourceProvider = fGpu->resourceProvider();
egdaniel0e1853c2016-03-17 11:35:45 -0700272 GrVkPipeline* pipeline = resourceProvider.createPipeline(fPipeline,
273 fPrimProc,
jvanverth992ad362016-02-26 09:21:02 -0800274 shaderStageInfo,
275 2,
276 primitiveType,
277 renderPass,
278 pipelineLayout);
279 GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), vertShaderModule,
280 nullptr));
281 GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), fragShaderModule,
282 nullptr));
283
284 if (!pipeline) {
285 GR_VK_CALL(fGpu->vkInterface(), DestroyPipelineLayout(fGpu->device(), pipelineLayout,
286 nullptr));
egdaniel778555c2016-05-02 06:50:36 -0700287 GR_VK_CALL(fGpu->vkInterface(),
288 DestroyDescriptorSetLayout(fGpu->device(),
289 dsLayout[GrVkUniformHandler::kSamplerDescSet],
290 nullptr));
291
egdaniel8af936d2016-04-07 10:17:47 -0700292 this->cleanupFragmentProcessors();
jvanverth992ad362016-02-26 09:21:02 -0800293 return nullptr;
294 }
295
egdaniel22281c12016-03-23 13:49:40 -0700296 return new GrVkPipelineState(fGpu,
297 desc,
298 pipeline,
299 pipelineLayout,
egdaniel778555c2016-05-02 06:50:36 -0700300 dsLayout[GrVkUniformHandler::kSamplerDescSet],
egdaniel22281c12016-03-23 13:49:40 -0700301 fUniformHandles,
302 fUniformHandler.fUniforms,
303 fUniformHandler.fCurrentVertexUBOOffset,
304 fUniformHandler.fCurrentFragmentUBOOffset,
305 numSamplers,
306 fGeometryProcessor,
307 fXferProcessor,
308 fFragmentProcessors);
jvanverth992ad362016-02-26 09:21:02 -0800309}