• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2016 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 // ProgramVk.h:
7 //    Defines the class interface for ProgramVk, implementing ProgramImpl.
8 //
9 
10 #ifndef LIBANGLE_RENDERER_VULKAN_PROGRAMVK_H_
11 #define LIBANGLE_RENDERER_VULKAN_PROGRAMVK_H_
12 
13 #include <array>
14 
15 #include "common/utilities.h"
16 #include "libANGLE/renderer/ProgramImpl.h"
17 #include "libANGLE/renderer/glslang_wrapper_utils.h"
18 #include "libANGLE/renderer/vulkan/ContextVk.h"
19 #include "libANGLE/renderer/vulkan/ProgramExecutableVk.h"
20 #include "libANGLE/renderer/vulkan/RendererVk.h"
21 #include "libANGLE/renderer/vulkan/TransformFeedbackVk.h"
22 #include "libANGLE/renderer/vulkan/vk_helpers.h"
23 
24 namespace rx
25 {
UseLineRaster(const ContextVk * contextVk,gl::PrimitiveMode mode)26 ANGLE_INLINE bool UseLineRaster(const ContextVk *contextVk, gl::PrimitiveMode mode)
27 {
28     return contextVk->getFeatures().basicGLLineRasterization.enabled && gl::IsLineMode(mode);
29 }
30 
31 class ProgramVk : public ProgramImpl
32 {
33   public:
34     ProgramVk(const gl::ProgramState &state);
35     ~ProgramVk() override;
36     void destroy(const gl::Context *context) override;
37 
38     std::unique_ptr<LinkEvent> load(const gl::Context *context,
39                                     gl::BinaryInputStream *stream,
40                                     gl::InfoLog &infoLog) override;
41     void save(const gl::Context *context, gl::BinaryOutputStream *stream) override;
42     void setBinaryRetrievableHint(bool retrievable) override;
43     void setSeparable(bool separable) override;
44 
45     void fillProgramStateMap(gl::ShaderMap<const gl::ProgramState *> *programStatesOut);
46 
47     std::unique_ptr<LinkEvent> link(const gl::Context *context,
48                                     const gl::ProgramLinkedResources &resources,
49                                     gl::InfoLog &infoLog,
50                                     const gl::ProgramMergedVaryings &mergedVaryings) override;
51     GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
52 
53     void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) override;
54     void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) override;
55     void setUniform3fv(GLint location, GLsizei count, const GLfloat *v) override;
56     void setUniform4fv(GLint location, GLsizei count, const GLfloat *v) override;
57     void setUniform1iv(GLint location, GLsizei count, const GLint *v) override;
58     void setUniform2iv(GLint location, GLsizei count, const GLint *v) override;
59     void setUniform3iv(GLint location, GLsizei count, const GLint *v) override;
60     void setUniform4iv(GLint location, GLsizei count, const GLint *v) override;
61     void setUniform1uiv(GLint location, GLsizei count, const GLuint *v) override;
62     void setUniform2uiv(GLint location, GLsizei count, const GLuint *v) override;
63     void setUniform3uiv(GLint location, GLsizei count, const GLuint *v) override;
64     void setUniform4uiv(GLint location, GLsizei count, const GLuint *v) override;
65     void setUniformMatrix2fv(GLint location,
66                              GLsizei count,
67                              GLboolean transpose,
68                              const GLfloat *value) override;
69     void setUniformMatrix3fv(GLint location,
70                              GLsizei count,
71                              GLboolean transpose,
72                              const GLfloat *value) override;
73     void setUniformMatrix4fv(GLint location,
74                              GLsizei count,
75                              GLboolean transpose,
76                              const GLfloat *value) override;
77     void setUniformMatrix2x3fv(GLint location,
78                                GLsizei count,
79                                GLboolean transpose,
80                                const GLfloat *value) override;
81     void setUniformMatrix3x2fv(GLint location,
82                                GLsizei count,
83                                GLboolean transpose,
84                                const GLfloat *value) override;
85     void setUniformMatrix2x4fv(GLint location,
86                                GLsizei count,
87                                GLboolean transpose,
88                                const GLfloat *value) override;
89     void setUniformMatrix4x2fv(GLint location,
90                                GLsizei count,
91                                GLboolean transpose,
92                                const GLfloat *value) override;
93     void setUniformMatrix3x4fv(GLint location,
94                                GLsizei count,
95                                GLboolean transpose,
96                                const GLfloat *value) override;
97     void setUniformMatrix4x3fv(GLint location,
98                                GLsizei count,
99                                GLboolean transpose,
100                                const GLfloat *value) override;
101 
102     void getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const override;
103     void getUniformiv(const gl::Context *context, GLint location, GLint *params) const override;
104     void getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const override;
105 
106     angle::Result updateUniforms(ContextVk *contextVk);
107 
108     void setAllDefaultUniformsDirty();
dirtyUniforms()109     bool dirtyUniforms() const { return mDefaultUniformBlocksDirty.any(); }
isShaderUniformDirty(gl::ShaderType shaderType)110     bool isShaderUniformDirty(gl::ShaderType shaderType) const
111     {
112         return mDefaultUniformBlocksDirty[shaderType];
113     }
setShaderUniformDirtyBit(gl::ShaderType shaderType)114     void setShaderUniformDirtyBit(gl::ShaderType shaderType)
115     {
116         if (!mDefaultUniformBlocks[shaderType].uniformData.empty())
117         {
118             mDefaultUniformBlocksDirty.set(shaderType);
119         }
120     }
clearShaderUniformDirtyBit(gl::ShaderType shaderType)121     void clearShaderUniformDirtyBit(gl::ShaderType shaderType)
122     {
123         mDefaultUniformBlocksDirty.reset(shaderType);
124     }
125     void onProgramBind();
126 
getExecutable()127     const ProgramExecutableVk &getExecutable() const { return mExecutable; }
getExecutable()128     ProgramExecutableVk &getExecutable() { return mExecutable; }
129 
getDefaultUniformBlocks()130     gl::ShaderMap<DefaultUniformBlock> &getDefaultUniformBlocks() { return mDefaultUniformBlocks; }
getDefaultUniformAlignedSize(ContextVk * contextVk,const gl::ShaderType shaderType)131     size_t getDefaultUniformAlignedSize(ContextVk *contextVk, const gl::ShaderType shaderType) const
132     {
133         RendererVk *renderer = contextVk->getRenderer();
134         size_t alignment     = static_cast<size_t>(
135             renderer->getPhysicalDeviceProperties().limits.minUniformBufferOffsetAlignment);
136         return roundUp(mDefaultUniformBlocks[shaderType].uniformData.size(), alignment);
137     }
138 
139     size_t calcUniformUpdateRequiredSpace(ContextVk *contextVk,
140                                           const gl::ProgramExecutable &glExecutable,
141                                           gl::ShaderMap<VkDeviceSize> &uniformOffsets) const;
142 
initGraphicsShaderProgram(ContextVk * contextVk,const gl::ShaderType shaderType,bool isLastPreFragmentStage,ProgramTransformOptions optionBits,ProgramInfo * programInfo,const ShaderInterfaceVariableInfoMap & variableInfoMap)143     ANGLE_INLINE angle::Result initGraphicsShaderProgram(
144         ContextVk *contextVk,
145         const gl::ShaderType shaderType,
146         bool isLastPreFragmentStage,
147         ProgramTransformOptions optionBits,
148         ProgramInfo *programInfo,
149         const ShaderInterfaceVariableInfoMap &variableInfoMap)
150     {
151         return initProgram(contextVk, shaderType, isLastPreFragmentStage, optionBits, programInfo,
152                            variableInfoMap);
153     }
154 
initComputeProgram(ContextVk * contextVk,ProgramInfo * programInfo,const ShaderInterfaceVariableInfoMap & variableInfoMap)155     ANGLE_INLINE angle::Result initComputeProgram(
156         ContextVk *contextVk,
157         ProgramInfo *programInfo,
158         const ShaderInterfaceVariableInfoMap &variableInfoMap)
159     {
160         ProgramTransformOptions optionBits = {};
161         return initProgram(contextVk, gl::ShaderType::Compute, false, optionBits, programInfo,
162                            variableInfoMap);
163     }
164 
getGlslangProgramInterfaceInfo()165     const GlslangProgramInterfaceInfo &getGlslangProgramInterfaceInfo()
166     {
167         return mGlslangProgramInterfaceInfo;
168     }
169 
170   private:
171     template <int cols, int rows>
172     void setUniformMatrixfv(GLint location,
173                             GLsizei count,
174                             GLboolean transpose,
175                             const GLfloat *value);
176 
177     void reset(ContextVk *contextVk);
178     angle::Result initDefaultUniformBlocks(const gl::Context *glContext);
179     void generateUniformLayoutMapping(gl::ShaderMap<sh::BlockLayoutMap> &layoutMap,
180                                       gl::ShaderMap<size_t> &requiredBufferSize);
181     void initDefaultUniformLayoutMapping(gl::ShaderMap<sh::BlockLayoutMap> &layoutMap);
182     angle::Result resizeUniformBlockMemory(ContextVk *contextVk,
183                                            gl::ShaderMap<size_t> &requiredBufferSize);
184 
185     template <class T>
186     void getUniformImpl(GLint location, T *v, GLenum entryPointType) const;
187 
188     template <typename T>
189     void setUniformImpl(GLint location, GLsizei count, const T *v, GLenum entryPointType);
190     void linkResources(const gl::ProgramLinkedResources &resources);
191 
initProgram(ContextVk * contextVk,const gl::ShaderType shaderType,bool isLastPreFragmentStage,ProgramTransformOptions optionBits,ProgramInfo * programInfo,const ShaderInterfaceVariableInfoMap & variableInfoMap)192     ANGLE_INLINE angle::Result initProgram(ContextVk *contextVk,
193                                            const gl::ShaderType shaderType,
194                                            bool isLastPreFragmentStage,
195                                            ProgramTransformOptions optionBits,
196                                            ProgramInfo *programInfo,
197                                            const ShaderInterfaceVariableInfoMap &variableInfoMap)
198     {
199         ASSERT(mOriginalShaderInfo.valid());
200 
201         // Create the program pipeline.  This is done lazily and once per combination of
202         // specialization constants.
203         if (!programInfo->valid(shaderType))
204         {
205             const bool isTransformFeedbackProgram =
206                 !mState.getLinkedTransformFeedbackVaryings().empty();
207             ANGLE_TRY(programInfo->initProgram(contextVk, shaderType, isLastPreFragmentStage,
208                                                isTransformFeedbackProgram, mOriginalShaderInfo,
209                                                optionBits, variableInfoMap));
210         }
211         ASSERT(programInfo->valid(shaderType));
212 
213         return angle::Result::Continue;
214     }
215 
216     gl::ShaderMap<DefaultUniformBlock> mDefaultUniformBlocks;
217     gl::ShaderBitSet mDefaultUniformBlocksDirty;
218 
219     // We keep the SPIR-V code to use for draw call pipeline creation.
220     ShaderInfo mOriginalShaderInfo;
221 
222     GlslangProgramInterfaceInfo mGlslangProgramInterfaceInfo;
223 
224     ProgramExecutableVk mExecutable;
225 };
226 
227 }  // namespace rx
228 
229 #endif  // LIBANGLE_RENDERER_VULKAN_PROGRAMVK_H_
230