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
16GrVkPipelineState* 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
36GrVkPipelineStateBuilder::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
46const GrCaps* GrVkPipelineStateBuilder::caps() const {
47    return fGpu->caps();
48}
49
50void GrVkPipelineStateBuilder::finalizeFragmentOutputColor(GrShaderVar& outputColor) {
51    outputColor.addLayoutQualifier("location = 0, index = 0");
52}
53
54void GrVkPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outputColor) {
55    outputColor.addLayoutQualifier("location = 0, index = 1");
56}
57
58bool 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().proxy()->origin()));
84        desc->finalize();
85    }
86    return result;
87}
88
89GrVkPipelineState* 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().proxy()->origin() != kTopLeft_GrSurfaceOrigin;
144    SkASSERT(!this->fragColorIsInOut());
145    SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
146                                              fVS,
147                                              &vertShaderModule,
148                                              &shaderStageInfo[0],
149                                              settings,
150                                              desc));
151
152    SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
153                                              fFS,
154                                              &fragShaderModule,
155                                              &shaderStageInfo[1],
156                                              settings,
157                                              desc));
158
159    int numShaderStages = 2; // We always have at least vertex and fragment stages.
160    if (this->primitiveProcessor().willUseGeoShader()) {
161        SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_GEOMETRY_BIT,
162                                                  fGS,
163                                                  &geomShaderModule,
164                                                  &shaderStageInfo[2],
165                                                  settings,
166                                                  desc));
167        ++numShaderStages;
168    }
169
170    GrVkPipeline* pipeline = resourceProvider.createPipeline(fPipeline,
171                                                             stencil,
172                                                             fPrimProc,
173                                                             shaderStageInfo,
174                                                             numShaderStages,
175                                                             primitiveType,
176                                                             renderPass,
177                                                             pipelineLayout);
178    GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), vertShaderModule,
179                                                        nullptr));
180    GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), fragShaderModule,
181                                                        nullptr));
182    // This if check should not be needed since calling destroy on a VK_NULL_HANDLE is allowed.
183    // However this is causing a crash in certain drivers (e.g. NVidia).
184    if (this->primitiveProcessor().willUseGeoShader()) {
185        GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), geomShaderModule,
186                                                            nullptr));
187    }
188
189    if (!pipeline) {
190        GR_VK_CALL(fGpu->vkInterface(), DestroyPipelineLayout(fGpu->device(), pipelineLayout,
191                                                              nullptr));
192        this->cleanupFragmentProcessors();
193        return nullptr;
194    }
195
196    return new GrVkPipelineState(fGpu,
197                                 *desc,
198                                 pipeline,
199                                 pipelineLayout,
200                                 samplerDSHandle,
201                                 texelBufferDSHandle,
202                                 fUniformHandles,
203                                 fUniformHandler.fUniforms,
204                                 fUniformHandler.fCurrentGeometryUBOOffset,
205                                 fUniformHandler.fCurrentFragmentUBOOffset,
206                                 (uint32_t)fUniformHandler.numSamplers(),
207                                 (uint32_t)fUniformHandler.numTexelBuffers(),
208                                 std::move(fGeometryProcessor),
209                                 std::move(fXferProcessor),
210                                 fFragmentProcessors);
211}
212
213