| /* |
| * Copyright 2016 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "vk/GrVkPipelineStateBuilder.h" |
| |
| #include "GrShaderCaps.h" |
| #include "vk/GrVkDescriptorSetManager.h" |
| #include "vk/GrVkGpu.h" |
| #include "vk/GrVkRenderPass.h" |
| |
| |
| GrVkPipelineState* GrVkPipelineStateBuilder::CreatePipelineState( |
| GrVkGpu* gpu, |
| const GrPipeline& pipeline, |
| const GrStencilSettings& stencil, |
| const GrPrimitiveProcessor& primProc, |
| GrPrimitiveType primitiveType, |
| const GrVkPipelineState::Desc& desc, |
| const GrVkRenderPass& renderPass) { |
| // create a builder. This will be handed off to effects so they can use it to add |
| // uniforms, varyings, textures, etc |
| GrVkPipelineStateBuilder builder(gpu, pipeline, primProc, desc); |
| |
| GrGLSLExpr4 inputColor; |
| GrGLSLExpr4 inputCoverage; |
| |
| if (!builder.emitAndInstallProcs(&inputColor, &inputCoverage)) { |
| builder.cleanupFragmentProcessors(); |
| return nullptr; |
| } |
| |
| return builder.finalize(stencil, primitiveType, renderPass, desc); |
| } |
| |
| GrVkPipelineStateBuilder::GrVkPipelineStateBuilder(GrVkGpu* gpu, |
| const GrPipeline& pipeline, |
| const GrPrimitiveProcessor& primProc, |
| const GrProgramDesc& desc) |
| : INHERITED(pipeline, primProc, desc) |
| , fGpu(gpu) |
| , fVaryingHandler(this) |
| , fUniformHandler(this) { |
| } |
| |
| const GrCaps* GrVkPipelineStateBuilder::caps() const { |
| return fGpu->caps(); |
| } |
| |
| void GrVkPipelineStateBuilder::finalizeFragmentOutputColor(GrShaderVar& outputColor) { |
| outputColor.addLayoutQualifier("location = 0, index = 0"); |
| } |
| |
| void GrVkPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outputColor) { |
| outputColor.addLayoutQualifier("location = 0, index = 1"); |
| } |
| |
| bool GrVkPipelineStateBuilder::createVkShaderModule(VkShaderStageFlagBits stage, |
| const GrGLSLShaderBuilder& builder, |
| VkShaderModule* shaderModule, |
| VkPipelineShaderStageCreateInfo* stageInfo, |
| const SkSL::Program::Settings& settings) { |
| SkString shaderString; |
| for (int i = 0; i < builder.fCompilerStrings.count(); ++i) { |
| if (builder.fCompilerStrings[i]) { |
| shaderString.append(builder.fCompilerStrings[i]); |
| shaderString.append("\n"); |
| } |
| } |
| |
| SkSL::Program::Inputs inputs; |
| bool result = GrCompileVkShaderModule(fGpu, shaderString.c_str(), stage, shaderModule, |
| stageInfo, settings, &inputs); |
| if (!result) { |
| return false; |
| } |
| if (inputs.fRTHeight) { |
| this->addRTHeightUniform(SKSL_RTHEIGHT_NAME); |
| } |
| return result; |
| } |
| |
| GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& stencil, |
| GrPrimitiveType primitiveType, |
| const GrVkRenderPass& renderPass, |
| const GrVkPipelineState::Desc& desc) { |
| VkDescriptorSetLayout dsLayout[2]; |
| VkPipelineLayout pipelineLayout; |
| VkShaderModule vertShaderModule; |
| VkShaderModule fragShaderModule; |
| |
| GrVkResourceProvider& resourceProvider = fGpu->resourceProvider(); |
| // These layouts are not owned by the PipelineStateBuilder and thus should not be destroyed |
| dsLayout[GrVkUniformHandler::kUniformBufferDescSet] = resourceProvider.getUniformDSLayout(); |
| |
| GrVkDescriptorSetManager::Handle samplerDSHandle; |
| resourceProvider.getSamplerDescriptorSetHandle(fUniformHandler, &samplerDSHandle); |
| dsLayout[GrVkUniformHandler::kSamplerDescSet] = |
| resourceProvider.getSamplerDSLayout(samplerDSHandle); |
| |
| // Create the VkPipelineLayout |
| VkPipelineLayoutCreateInfo layoutCreateInfo; |
| memset(&layoutCreateInfo, 0, sizeof(VkPipelineLayoutCreateFlags)); |
| layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; |
| layoutCreateInfo.pNext = 0; |
| layoutCreateInfo.flags = 0; |
| layoutCreateInfo.setLayoutCount = 2; |
| layoutCreateInfo.pSetLayouts = dsLayout; |
| layoutCreateInfo.pushConstantRangeCount = 0; |
| layoutCreateInfo.pPushConstantRanges = nullptr; |
| |
| GR_VK_CALL_ERRCHECK(fGpu->vkInterface(), CreatePipelineLayout(fGpu->device(), |
| &layoutCreateInfo, |
| nullptr, |
| &pipelineLayout)); |
| |
| // We need to enable the following extensions so that the compiler can correctly make spir-v |
| // from our glsl shaders. |
| fVS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n"); |
| fFS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n"); |
| fVS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n"); |
| fFS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n"); |
| |
| this->finalizeShaders(); |
| |
| VkPipelineShaderStageCreateInfo shaderStageInfo[2]; |
| SkSL::Program::Settings settings; |
| settings.fFlipY = this->pipeline().getRenderTarget()->origin() != kTopLeft_GrSurfaceOrigin; |
| SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT, |
| fVS, |
| &vertShaderModule, |
| &shaderStageInfo[0], |
| settings)); |
| |
| // TODO: geometry shader support. |
| SkASSERT(!this->primitiveProcessor().willUseGeoShader()); |
| |
| SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT, |
| fFS, |
| &fragShaderModule, |
| &shaderStageInfo[1], |
| settings)); |
| |
| GrVkPipeline* pipeline = resourceProvider.createPipeline(fPipeline, |
| stencil, |
| fPrimProc, |
| shaderStageInfo, |
| 2, |
| primitiveType, |
| renderPass, |
| pipelineLayout); |
| GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), vertShaderModule, |
| nullptr)); |
| GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), fragShaderModule, |
| nullptr)); |
| |
| if (!pipeline) { |
| GR_VK_CALL(fGpu->vkInterface(), DestroyPipelineLayout(fGpu->device(), pipelineLayout, |
| nullptr)); |
| this->cleanupFragmentProcessors(); |
| return nullptr; |
| } |
| |
| return new GrVkPipelineState(fGpu, |
| desc, |
| pipeline, |
| pipelineLayout, |
| samplerDSHandle, |
| fUniformHandles, |
| fUniformHandler.fUniforms, |
| fUniformHandler.fCurrentVertexUBOOffset, |
| fUniformHandler.fCurrentFragmentUBOOffset, |
| (uint32_t)fUniformHandler.numSamplers(), |
| fGeometryProcessor, |
| fXferProcessor, |
| fFragmentProcessors); |
| } |
| |