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 #include "libANGLE/renderer/glslang_wrapper_utils.h"
13 #include "libANGLE/renderer/vulkan/GlslangWrapperVk.h"
14
15 namespace rx
16 {
17
ProgramPipelineVk(const gl::ProgramPipelineState & state)18 ProgramPipelineVk::ProgramPipelineVk(const gl::ProgramPipelineState &state)
19 : ProgramPipelineImpl(state)
20 {
21 mExecutable.setProgramPipeline(this);
22 }
23
~ProgramPipelineVk()24 ProgramPipelineVk::~ProgramPipelineVk() {}
25
destroy(const gl::Context * context)26 void ProgramPipelineVk::destroy(const gl::Context *context)
27 {
28 ContextVk *contextVk = vk::GetImpl(context);
29 reset(contextVk);
30 }
31
reset(ContextVk * contextVk)32 void ProgramPipelineVk::reset(ContextVk *contextVk)
33 {
34 mExecutable.reset(contextVk);
35 }
36
37 // TODO: http://anglebug.com/3570: Move/Copy all of the necessary information into
38 // the ProgramExecutable, so this function can be removed.
fillProgramStateMap(const ContextVk * contextVk,gl::ShaderMap<const gl::ProgramState * > * programStatesOut)39 void ProgramPipelineVk::fillProgramStateMap(
40 const ContextVk *contextVk,
41 gl::ShaderMap<const gl::ProgramState *> *programStatesOut)
42 {
43 for (gl::ShaderType shaderType : gl::AllShaderTypes())
44 {
45 (*programStatesOut)[shaderType] = nullptr;
46
47 ProgramVk *programVk = getShaderProgram(contextVk->getState(), shaderType);
48 if (programVk)
49 {
50 (*programStatesOut)[shaderType] = &programVk->getState();
51 }
52 }
53 }
54
link(const gl::Context * glContext)55 angle::Result ProgramPipelineVk::link(const gl::Context *glContext)
56 {
57 ContextVk *contextVk = vk::GetImpl(glContext);
58 const gl::State &glState = glContext->getState();
59 const gl::ProgramPipeline *glPipeline = glState.getProgramPipeline();
60 GlslangSourceOptions options =
61 GlslangWrapperVk::CreateSourceOptions(contextVk->getRenderer()->getFeatures());
62 GlslangProgramInterfaceInfo glslangProgramInterfaceInfo;
63 GlslangWrapperVk::ResetGlslangProgramInterfaceInfo(&glslangProgramInterfaceInfo);
64
65 mExecutable.clearVariableInfoMap();
66
67 // Now that the program pipeline has all of the programs attached, the various descriptor
68 // set/binding locations need to be re-assigned to their correct values.
69 for (const gl::ShaderType shaderType : glPipeline->getExecutable().getLinkedShaderStages())
70 {
71 gl::Program *glProgram =
72 const_cast<gl::Program *>(glPipeline->getShaderProgram(shaderType));
73 if (glProgram)
74 {
75 // The program interface info must survive across shaders, except
76 // for some program-specific values.
77 ProgramVk *programVk = vk::GetImpl(glProgram);
78 GlslangProgramInterfaceInfo &programProgramInterfaceInfo =
79 programVk->getGlslangProgramInterfaceInfo();
80 glslangProgramInterfaceInfo.locationsUsedForXfbExtension =
81 programProgramInterfaceInfo.locationsUsedForXfbExtension;
82
83 GlslangAssignLocations(options, glProgram->getState(), glProgram->getResources(),
84 shaderType, &glslangProgramInterfaceInfo,
85 &mExecutable.getShaderInterfaceVariableInfoMap());
86 }
87 }
88
89 ANGLE_TRY(transformShaderSpirV(glContext));
90
91 return mExecutable.createPipelineLayout(glContext);
92 }
93
transformShaderSpirV(const gl::Context * glContext)94 angle::Result ProgramPipelineVk::transformShaderSpirV(const gl::Context *glContext)
95 {
96 ContextVk *contextVk = vk::GetImpl(glContext);
97 const gl::ProgramExecutable *executable = contextVk->getState().getProgramExecutable();
98 ASSERT(executable);
99
100 for (const gl::ShaderType shaderType : executable->getLinkedShaderStages())
101 {
102 ProgramVk *programVk = getShaderProgram(contextVk->getState(), shaderType);
103 if (programVk)
104 {
105 ShaderInterfaceVariableInfoMap &variableInfoMap =
106 mExecutable.mVariableInfoMap[shaderType];
107 std::vector<uint32_t> transformedSpirvBlob;
108
109 // We skip early fragment tests optimization modification here since we need to keep
110 // original spriv blob here.
111 ANGLE_TRY(GlslangWrapperVk::TransformSpirV(
112 contextVk, shaderType, false, variableInfoMap,
113 programVk->getShaderInfo().getSpirvBlobs()[shaderType], &transformedSpirvBlob));
114
115 // Save the newly transformed SPIR-V
116 // TODO: http://anglebug.com/4513: Keep the original SPIR-V and
117 // translated SPIR-V in separate buffers in ShaderInfo to avoid the
118 // extra copy here.
119 programVk->getShaderInfo().getSpirvBlobs()[shaderType] = transformedSpirvBlob;
120 }
121 }
122 return angle::Result::Continue;
123 }
124
updateUniforms(ContextVk * contextVk)125 angle::Result ProgramPipelineVk::updateUniforms(ContextVk *contextVk)
126 {
127 uint32_t offsetIndex = 0;
128 bool anyNewBufferAllocated = false;
129 const gl::ProgramExecutable *glExecutable = contextVk->getState().getProgramExecutable();
130
131 for (const gl::ShaderType shaderType : glExecutable->getLinkedShaderStages())
132 {
133 ProgramVk *programVk = getShaderProgram(contextVk->getState(), shaderType);
134 if (programVk && programVk->dirtyUniforms())
135 {
136 ANGLE_TRY(programVk->updateShaderUniforms(
137 contextVk, shaderType, &mExecutable.mDynamicBufferOffsets[offsetIndex],
138 &anyNewBufferAllocated));
139 }
140 ++offsetIndex;
141 }
142
143 if (anyNewBufferAllocated)
144 {
145 // We need to reinitialize the descriptor sets if we newly allocated buffers since we can't
146 // modify the descriptor sets once initialized.
147 ANGLE_TRY(mExecutable.allocateDescriptorSet(contextVk, kUniformsAndXfbDescriptorSetIndex));
148
149 mExecutable.mDescriptorBuffersCache.clear();
150 for (const gl::ShaderType shaderType : glExecutable->getLinkedShaderStages())
151 {
152 ProgramVk *programVk = getShaderProgram(contextVk->getState(), shaderType);
153 if (programVk)
154 {
155 mExecutable.updateDefaultUniformsDescriptorSet(
156 shaderType, programVk->getDefaultUniformBlocks(), contextVk);
157 mExecutable.updateTransformFeedbackDescriptorSetImpl(programVk->getState(),
158 contextVk);
159 }
160 }
161 }
162
163 return angle::Result::Continue;
164 }
165
dirtyUniforms(const gl::State & glState)166 bool ProgramPipelineVk::dirtyUniforms(const gl::State &glState)
167 {
168 for (const gl::ShaderType shaderType : gl::AllShaderTypes())
169 {
170 const ProgramVk *program = getShaderProgram(glState, shaderType);
171 if (program && program->dirtyUniforms())
172 {
173 return true;
174 }
175 }
176
177 return false;
178 }
179
180 } // namespace rx
181