xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/vulkan/ProgramPipelineVk.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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