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/GrVkProgramBuilder.h"
9
10#include "vk/GrVkGpu.h"
11#include "vk/GrVkRenderPass.h"
12#include "vk/GrVkProgram.h"
13
14GrVkProgram* GrVkProgramBuilder::CreateProgram(GrVkGpu* gpu,
15                                               const DrawArgs& args,
16                                               GrPrimitiveType primitiveType,
17                                               const GrVkRenderPass& renderPass) {
18    // create a builder.  This will be handed off to effects so they can use it to add
19    // uniforms, varyings, textures, etc
20    GrVkProgramBuilder builder(gpu, args);
21
22    GrGLSLExpr4 inputColor;
23    GrGLSLExpr4 inputCoverage;
24
25    if (!builder.emitAndInstallProcs(&inputColor,
26                                     &inputCoverage,
27                                     gpu->vkCaps().maxSampledTextures())) {
28        builder.cleanupFragmentProcessors();
29        return nullptr;
30    }
31
32    return builder.finalize(args, primitiveType, renderPass);
33}
34
35GrVkProgramBuilder::GrVkProgramBuilder(GrVkGpu* gpu, const DrawArgs& args)
36    : INHERITED(args)
37    , fGpu(gpu)
38    , fVaryingHandler(this)
39    , fUniformHandler(this) {
40}
41
42const GrCaps* GrVkProgramBuilder::caps() const {
43    return fGpu->caps();
44}
45const GrGLSLCaps* GrVkProgramBuilder::glslCaps() const {
46    return fGpu->vkCaps().glslCaps();
47}
48
49void GrVkProgramBuilder::finalizeFragmentOutputColor(GrGLSLShaderVar& outputColor) {
50    outputColor.setLayoutQualifier("location = 0");
51}
52
53void GrVkProgramBuilder::emitSamplers(const GrProcessor& processor,
54                                      GrGLSLTextureSampler::TextureSamplerArray* outSamplers) {
55    int numTextures = processor.numTextures();
56    UniformHandle* localSamplerUniforms = fSamplerUniforms.push_back_n(numTextures);
57    SkString name;
58    for (int t = 0; t < numTextures; ++t) {
59        name.printf("%d", t);
60        localSamplerUniforms[t]  =
61            fUniformHandler.addUniform(kFragment_GrShaderFlag,
62                                       kSampler2D_GrSLType, kDefault_GrSLPrecision,
63                                       name.c_str());
64        outSamplers->emplace_back(localSamplerUniforms[t], processor.textureAccess(t));
65    }
66}
67
68VkShaderStageFlags visibility_to_vk_stage_flags(uint32_t visibility) {
69    VkShaderStageFlags flags = 0;
70
71    if (visibility & kVertex_GrShaderFlag) {
72        flags |= VK_SHADER_STAGE_VERTEX_BIT;
73    }
74    if (visibility & kGeometry_GrShaderFlag) {
75        flags |= VK_SHADER_STAGE_GEOMETRY_BIT;
76    }
77    if (visibility & kFragment_GrShaderFlag) {
78        flags |= VK_SHADER_STAGE_FRAGMENT_BIT;
79    }
80    return flags;
81}
82
83shaderc_shader_kind vk_shader_stage_to_shaderc_kind(VkShaderStageFlagBits stage) {
84    if (VK_SHADER_STAGE_VERTEX_BIT == stage) {
85        return shaderc_glsl_vertex_shader;
86    }
87    SkASSERT(VK_SHADER_STAGE_FRAGMENT_BIT == stage);
88    return shaderc_glsl_fragment_shader;
89}
90
91bool GrVkProgramBuilder::CreateVkShaderModule(const GrVkGpu* gpu,
92                                              VkShaderStageFlagBits stage,
93                                              const GrGLSLShaderBuilder& builder,
94                                              VkShaderModule* shaderModule,
95                                              VkPipelineShaderStageCreateInfo* stageInfo) {
96    SkString shaderString;
97    for (int i = 0; i < builder.fCompilerStrings.count(); ++i) {
98        if (builder.fCompilerStrings[i]) {
99            shaderString.append(builder.fCompilerStrings[i]);
100            shaderString.append("\n");
101        }
102    }
103
104    shaderc_compiler_t compiler = gpu->shadercCompiler();
105
106    shaderc_compile_options_t options = shaderc_compile_options_initialize();
107    shaderc_compile_options_set_forced_version_profile(options, 140, shaderc_profile_none);
108
109    shaderc_shader_kind shadercStage = vk_shader_stage_to_shaderc_kind(stage);
110    shaderc_compilation_result_t result = shaderc_compile_into_spv(compiler,
111                                                                   shaderString.c_str(),
112                                                                   strlen(shaderString.c_str()),
113                                                                   shadercStage,
114                                                                   "shader",
115                                                                   "main",
116                                                                   options);
117    shaderc_compile_options_release(options);
118#ifdef SK_DEBUG
119    if (shaderc_result_get_num_errors(result)) {
120        SkDebugf("%s\n", shaderString.c_str());
121        SkDebugf("%s\n", shaderc_result_get_error_message(result));
122        return false;
123    }
124#endif
125
126    VkShaderModuleCreateInfo moduleCreateInfo;
127    memset(&moduleCreateInfo, 0, sizeof(VkShaderModuleCreateInfo));
128    moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
129    moduleCreateInfo.pNext = nullptr;
130    moduleCreateInfo.flags = 0;
131    moduleCreateInfo.codeSize = shaderc_result_get_length(result);
132    moduleCreateInfo.pCode = (const uint32_t*)shaderc_result_get_bytes(result);
133
134    VkResult err = GR_VK_CALL(gpu->vkInterface(), CreateShaderModule(gpu->device(),
135                                                                     &moduleCreateInfo,
136                                                                     nullptr,
137                                                                     shaderModule));
138    shaderc_result_release(result);
139    if (err) {
140        return false;
141    }
142
143    memset(stageInfo, 0, sizeof(VkPipelineShaderStageCreateInfo));
144    stageInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
145    stageInfo->pNext = nullptr;
146    stageInfo->flags = 0;
147    stageInfo->stage = stage;
148    stageInfo->module = *shaderModule;
149    stageInfo->pName = "main";
150    stageInfo->pSpecializationInfo = nullptr;
151
152    return true;
153}
154
155GrVkProgram* GrVkProgramBuilder::finalize(const DrawArgs& args,
156                                          GrPrimitiveType primitiveType,
157                                          const GrVkRenderPass& renderPass) {
158    VkDescriptorSetLayout dsLayout[2];
159    VkPipelineLayout pipelineLayout;
160    VkShaderModule vertShaderModule;
161    VkShaderModule fragShaderModule;
162
163    uint32_t numSamplers = fSamplerUniforms.count();
164
165    SkAutoTDeleteArray<VkDescriptorSetLayoutBinding> dsSamplerBindings(
166                                                     new VkDescriptorSetLayoutBinding[numSamplers]);
167    for (uint32_t i = 0; i < numSamplers; ++i) {
168        UniformHandle uniHandle = fSamplerUniforms[i];
169        GrVkUniformHandler::UniformInfo uniformInfo = fUniformHandler.getUniformInfo(uniHandle);
170        SkASSERT(kSampler2D_GrSLType == uniformInfo.fVariable.getType());
171        SkASSERT(0 == uniformInfo.fSetNumber);
172        SkASSERT(uniformInfo.fBinding == i);
173        dsSamplerBindings[i].binding = uniformInfo.fBinding;
174        dsSamplerBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
175        dsSamplerBindings[i].descriptorCount = 1;
176        dsSamplerBindings[i].stageFlags = visibility_to_vk_stage_flags(uniformInfo.fVisibility);
177        dsSamplerBindings[i].pImmutableSamplers = nullptr;
178    }
179
180    VkDescriptorSetLayoutCreateInfo dsSamplerLayoutCreateInfo;
181    memset(&dsSamplerLayoutCreateInfo, 0, sizeof(VkDescriptorSetLayoutCreateInfo));
182    dsSamplerLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
183    dsSamplerLayoutCreateInfo.pNext = nullptr;
184    dsSamplerLayoutCreateInfo.flags = 0;
185    dsSamplerLayoutCreateInfo.bindingCount = fSamplerUniforms.count();
186    // Setting to nullptr fixes an error in the param checker validation layer. Even though
187    // bindingCount is 0 (which is valid), it still tries to validate pBindings unless it is null.
188    dsSamplerLayoutCreateInfo.pBindings = fSamplerUniforms.count() ? dsSamplerBindings.get() :
189                                                                     nullptr;
190
191    GR_VK_CALL_ERRCHECK(fGpu->vkInterface(),
192                        CreateDescriptorSetLayout(fGpu->device(),
193                                                  &dsSamplerLayoutCreateInfo,
194                                                  nullptr,
195                                                  &dsLayout[GrVkUniformHandler::kSamplerDescSet]));
196
197    // Create Uniform Buffer Descriptor
198    // We always attach uniform buffers to descriptor set 1. The vertex uniform buffer will have
199    // binding 0 and the fragment binding 1.
200    VkDescriptorSetLayoutBinding dsUniBindings[2];
201    memset(&dsUniBindings, 0, 2 * sizeof(VkDescriptorSetLayoutBinding));
202    dsUniBindings[0].binding = GrVkUniformHandler::kVertexBinding;
203    dsUniBindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
204    dsUniBindings[0].descriptorCount = fUniformHandler.hasVertexUniforms() ? 1 : 0;
205    dsUniBindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
206    dsUniBindings[0].pImmutableSamplers = nullptr;
207    dsUniBindings[1].binding = GrVkUniformHandler::kFragBinding;
208    dsUniBindings[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
209    dsUniBindings[1].descriptorCount = fUniformHandler.hasFragmentUniforms() ? 1 : 0;
210    dsUniBindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
211    dsUniBindings[1].pImmutableSamplers = nullptr;
212
213    VkDescriptorSetLayoutCreateInfo dsUniformLayoutCreateInfo;
214    memset(&dsUniformLayoutCreateInfo, 0, sizeof(VkDescriptorSetLayoutCreateInfo));
215    dsUniformLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
216    dsUniformLayoutCreateInfo.pNext = nullptr;
217    dsUniformLayoutCreateInfo.flags = 0;
218    dsUniformLayoutCreateInfo.bindingCount = 2;
219    dsUniformLayoutCreateInfo.pBindings = dsUniBindings;
220
221    GR_VK_CALL_ERRCHECK(fGpu->vkInterface(), CreateDescriptorSetLayout(
222                                             fGpu->device(),
223                                             &dsUniformLayoutCreateInfo,
224                                             nullptr,
225                                             &dsLayout[GrVkUniformHandler::kUniformBufferDescSet]));
226
227    // Create the VkPipelineLayout
228    VkPipelineLayoutCreateInfo layoutCreateInfo;
229    memset(&layoutCreateInfo, 0, sizeof(VkPipelineLayoutCreateFlags));
230    layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
231    layoutCreateInfo.pNext = 0;
232    layoutCreateInfo.flags = 0;
233    layoutCreateInfo.setLayoutCount = 2;
234    layoutCreateInfo.pSetLayouts = dsLayout;
235    layoutCreateInfo.pushConstantRangeCount = 0;
236    layoutCreateInfo.pPushConstantRanges = nullptr;
237
238    GR_VK_CALL_ERRCHECK(fGpu->vkInterface(), CreatePipelineLayout(fGpu->device(),
239                                                                  &layoutCreateInfo,
240                                                                  nullptr,
241                                                                  &pipelineLayout));
242
243    // We need to enable the following extensions so that the compiler can correctly make spir-v
244    // from our glsl shaders.
245    fVS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
246    fFS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
247    fVS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
248    fFS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
249
250    this->finalizeShaders();
251
252    VkPipelineShaderStageCreateInfo shaderStageInfo[2];
253    SkAssertResult(CreateVkShaderModule(fGpu,
254                                        VK_SHADER_STAGE_VERTEX_BIT,
255                                        fVS,
256                                        &vertShaderModule,
257                                        &shaderStageInfo[0]));
258
259    SkAssertResult(CreateVkShaderModule(fGpu,
260                                        VK_SHADER_STAGE_FRAGMENT_BIT,
261                                        fFS,
262                                        &fragShaderModule,
263                                        &shaderStageInfo[1]));
264
265    GrVkResourceProvider& resourceProvider = fGpu->resourceProvider();
266    GrVkPipeline* pipeline = resourceProvider.createPipeline(*args.fPipeline,
267                                                             *args.fPrimitiveProcessor,
268                                                             shaderStageInfo,
269                                                             2,
270                                                             primitiveType,
271                                                             renderPass,
272                                                             pipelineLayout);
273    GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), vertShaderModule,
274                                                        nullptr));
275    GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), fragShaderModule,
276                                                        nullptr));
277
278    if (!pipeline) {
279        GR_VK_CALL(fGpu->vkInterface(), DestroyPipelineLayout(fGpu->device(), pipelineLayout,
280                                                              nullptr));
281        GR_VK_CALL(fGpu->vkInterface(), DestroyDescriptorSetLayout(fGpu->device(), dsLayout[0],
282                                                                   nullptr));
283        GR_VK_CALL(fGpu->vkInterface(), DestroyDescriptorSetLayout(fGpu->device(), dsLayout[1],
284                                                                   nullptr));
285        return nullptr;
286    }
287
288
289    GrVkDescriptorPool::DescriptorTypeCounts typeCounts;
290    typeCounts.setTypeCount(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2);
291    SkASSERT(numSamplers < 256);
292    typeCounts.setTypeCount(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, (uint8_t)numSamplers);
293    GrVkDescriptorPool* descriptorPool =
294        fGpu->resourceProvider().findOrCreateCompatibleDescriptorPool(typeCounts);
295
296    VkDescriptorSetAllocateInfo dsAllocateInfo;
297    memset(&dsAllocateInfo, 0, sizeof(VkDescriptorSetAllocateInfo));
298    dsAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
299    dsAllocateInfo.pNext = nullptr;
300    dsAllocateInfo.descriptorPool = descriptorPool->descPool();
301    dsAllocateInfo.descriptorSetCount = 2;
302    dsAllocateInfo.pSetLayouts = dsLayout;
303
304    VkDescriptorSet descriptorSets[2];
305    GR_VK_CALL_ERRCHECK(fGpu->vkInterface(), AllocateDescriptorSets(fGpu->device(),
306                                                                    &dsAllocateInfo,
307                                                                    descriptorSets));
308
309    return new GrVkProgram(fGpu,
310                           pipeline,
311                           pipelineLayout,
312                           dsLayout,
313                           descriptorPool,
314                           descriptorSets,
315                           fUniformHandles,
316                           fUniformHandler.fUniforms,
317                           fUniformHandler.fCurrentVertexUBOOffset,
318                           fUniformHandler.fCurrentFragmentUBOOffset,
319                           numSamplers,
320                           fGeometryProcessor,
321                           fXferProcessor,
322                           fFragmentProcessors);
323}
324