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