1 //
2 // Copyright 2017 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // ProgramPipelineVk.cpp:
7 // Implements the class methods for ProgramPipelineVk.
8 //
9
10 #include "libANGLE/renderer/vulkan/ProgramPipelineVk.h"
11
12 namespace rx
13 {
14
ProgramPipelineVk(const gl::ProgramPipelineState & state)15 ProgramPipelineVk::ProgramPipelineVk(const gl::ProgramPipelineState &state)
16 : ProgramPipelineImpl(state)
17 {}
18
~ProgramPipelineVk()19 ProgramPipelineVk::~ProgramPipelineVk() {}
20
destroy(const gl::Context * context)21 void ProgramPipelineVk::destroy(const gl::Context *context)
22 {
23 ContextVk *contextVk = vk::GetImpl(context);
24 reset(contextVk);
25 }
26
reset(ContextVk * contextVk)27 void ProgramPipelineVk::reset(ContextVk *contextVk)
28 {
29 getExecutable()->reset(contextVk);
30 }
31
link(const gl::Context * glContext,const gl::ProgramMergedVaryings & mergedVaryings,const gl::ProgramVaryingPacking & varyingPacking)32 angle::Result ProgramPipelineVk::link(const gl::Context *glContext,
33 const gl::ProgramMergedVaryings &mergedVaryings,
34 const gl::ProgramVaryingPacking &varyingPacking)
35 {
36 ContextVk *contextVk = vk::GetImpl(glContext);
37 vk::Renderer *renderer = contextVk->getRenderer();
38 const gl::ProgramExecutable &glExecutable = mState.getExecutable();
39 ProgramExecutableVk *executableVk = vk::GetImpl(&glExecutable);
40 SpvSourceOptions options = SpvCreateSourceOptions(contextVk->getFeatures(),
41 renderer->getMaxColorInputAttachmentCount());
42 SpvProgramInterfaceInfo spvProgramInterfaceInfo = {};
43
44 reset(contextVk);
45 executableVk->clearVariableInfoMap();
46
47 // Now that the program pipeline has all of the programs attached, the various descriptor
48 // set/binding locations need to be re-assigned to their correct values.
49 const gl::ShaderType linkedTransformFeedbackStage =
50 glExecutable.getLinkedTransformFeedbackStage();
51
52 // This should be done before assigning varying locations. Otherwise, we can encounter shader
53 // interface mismatching problems when the transform feedback stage is not the vertex stage.
54 if (options.supportsTransformFeedbackExtension)
55 {
56 for (const gl::ShaderType shaderType : glExecutable.getLinkedShaderStages())
57 {
58 const gl::SharedProgramExecutable &glShaderExecutable =
59 mState.getShaderProgramExecutable(shaderType);
60 if (glShaderExecutable && gl::ShaderTypeSupportsTransformFeedback(shaderType))
61 {
62 const bool isTransformFeedbackStage =
63 shaderType == linkedTransformFeedbackStage &&
64 !glShaderExecutable->getLinkedTransformFeedbackVaryings().empty();
65
66 SpvAssignTransformFeedbackLocations(
67 shaderType, *glShaderExecutable.get(), isTransformFeedbackStage,
68 &spvProgramInterfaceInfo, &executableVk->mVariableInfoMap);
69 }
70 }
71 }
72
73 executableVk->mOriginalShaderInfo.clear();
74
75 SpvAssignLocations(options, glExecutable, varyingPacking, linkedTransformFeedbackStage,
76 &spvProgramInterfaceInfo, &executableVk->mVariableInfoMap);
77
78 for (const gl::ShaderType shaderType : glExecutable.getLinkedShaderStages())
79 {
80 const gl::SharedProgramExecutable &glShaderExecutable =
81 mState.getShaderProgramExecutable(shaderType);
82 ProgramExecutableVk *programExecutableVk = vk::GetImpl(glShaderExecutable.get());
83 executableVk->mDefaultUniformBlocks[shaderType] =
84 programExecutableVk->getSharedDefaultUniformBlock(shaderType);
85
86 executableVk->mOriginalShaderInfo.initShaderFromProgram(
87 shaderType, programExecutableVk->mOriginalShaderInfo);
88 }
89
90 executableVk->setAllDefaultUniformsDirty();
91
92 if (contextVk->getFeatures().varyingsRequireMatchingPrecisionInSpirv.enabled &&
93 contextVk->getFeatures().enablePrecisionQualifiers.enabled)
94 {
95 executableVk->resolvePrecisionMismatch(mergedVaryings);
96 }
97
98 executableVk->resetLayout(contextVk);
99 ANGLE_TRY(executableVk->createPipelineLayout(contextVk, &contextVk->getPipelineLayoutCache(),
100 &contextVk->getDescriptorSetLayoutCache(),
101 nullptr));
102 ANGLE_TRY(executableVk->initializeDescriptorPools(contextVk,
103 &contextVk->getDescriptorSetLayoutCache(),
104 &contextVk->getMetaDescriptorPools()));
105
106 angle::Result result = angle::Result::Continue;
107
108 if (contextVk->getFeatures().warmUpPipelineCacheAtLink.enabled)
109 {
110 ANGLE_TRY(executableVk->warmUpPipelineCache(renderer, contextVk->pipelineRobustness(),
111 contextVk->pipelineProtectedAccess()));
112 }
113
114 return result;
115 } // namespace rx
116
117 } // namespace rx
118