• 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 #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