• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     mExecutable.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     const gl::ProgramExecutable &glExecutable = mState.getExecutable();
38     SpvSourceOptions options                  = SpvCreateSourceOptions(contextVk->getFeatures());
39     SpvProgramInterfaceInfo spvProgramInterfaceInfo;
40     spvProgramInterfaceInfo = {};
41 
42     reset(contextVk);
43     mExecutable.clearVariableInfoMap();
44 
45     // Now that the program pipeline has all of the programs attached, the various descriptor
46     // set/binding locations need to be re-assigned to their correct values.
47     const gl::ShaderType linkedTransformFeedbackStage =
48         glExecutable.getLinkedTransformFeedbackStage();
49 
50     // This should be done before assigning varying locations. Otherwise, we can encounter shader
51     // interface mismatching problems when the transform feedback stage is not the vertex stage.
52     if (options.supportsTransformFeedbackExtension)
53     {
54         for (const gl::ShaderType shaderType : glExecutable.getLinkedShaderStages())
55         {
56             const gl::Program *glProgram = mState.getShaderProgram(shaderType);
57             if (glProgram && gl::ShaderTypeSupportsTransformFeedback(shaderType))
58             {
59                 const bool isTransformFeedbackStage =
60                     shaderType == linkedTransformFeedbackStage &&
61                     !glProgram->getState().getLinkedTransformFeedbackVaryings().empty();
62 
63                 SpvAssignTransformFeedbackLocations(
64                     shaderType, glProgram->getExecutable(), isTransformFeedbackStage,
65                     &spvProgramInterfaceInfo, &mExecutable.mVariableInfoMap);
66             }
67         }
68     }
69 
70     mExecutable.mOriginalShaderInfo.clear();
71 
72     SpvAssignLocations(options, glExecutable, varyingPacking, linkedTransformFeedbackStage,
73                        &spvProgramInterfaceInfo, &mExecutable.mVariableInfoMap);
74 
75     for (const gl::ShaderType shaderType : glExecutable.getLinkedShaderStages())
76     {
77         const gl::Program *program               = mState.getShaderProgram(shaderType);
78         ProgramVk *programVk                     = vk::GetImpl(program);
79         ProgramExecutableVk &programExecutableVk = programVk->getExecutable();
80         mExecutable.mDefaultUniformBlocks[shaderType] =
81             programExecutableVk.getSharedDefaultUniformBlock(shaderType);
82 
83         mExecutable.mOriginalShaderInfo.initShaderFromProgram(
84             shaderType, programExecutableVk.mOriginalShaderInfo);
85     }
86 
87     mExecutable.setAllDefaultUniformsDirty(glExecutable);
88 
89     if (contextVk->getFeatures().varyingsRequireMatchingPrecisionInSpirv.enabled &&
90         contextVk->getFeatures().enablePrecisionQualifiers.enabled)
91     {
92         mExecutable.resolvePrecisionMismatch(mergedVaryings);
93     }
94 
95     ANGLE_TRY(mExecutable.createPipelineLayout(contextVk, mState.getExecutable(), nullptr));
96 
97     return mExecutable.warmUpPipelineCache(contextVk, mState.getExecutable());
98 }  // namespace rx
99 
syncState(const gl::Context * context,const gl::Program::DirtyBits & dirtyBits)100 angle::Result ProgramPipelineVk::syncState(const gl::Context *context,
101                                            const gl::Program::DirtyBits &dirtyBits)
102 {
103     ASSERT(dirtyBits.any());
104     // Push dirty bits to executable so that they can be used later.
105     mExecutable.mDirtyBits |= dirtyBits;
106     return angle::Result::Continue;
107 }
108 
onProgramUniformUpdate(gl::ShaderType shaderType)109 void ProgramPipelineVk::onProgramUniformUpdate(gl::ShaderType shaderType)
110 {
111     mExecutable.mDefaultUniformBlocksDirty.set(shaderType);
112 }
113 }  // namespace rx
114