• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2020 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 // ProgramExecutable.h: Collects the information and interfaces common to both Programs and
7 // ProgramPipelines in order to execute/draw with either.
8 
9 #ifndef LIBANGLE_PROGRAMEXECUTABLE_H_
10 #define LIBANGLE_PROGRAMEXECUTABLE_H_
11 
12 #include "BinaryStream.h"
13 #include "libANGLE/Caps.h"
14 #include "libANGLE/InfoLog.h"
15 #include "libANGLE/ProgramLinkedResources.h"
16 #include "libANGLE/Shader.h"
17 #include "libANGLE/Uniform.h"
18 #include "libANGLE/VaryingPacking.h"
19 #include "libANGLE/angletypes.h"
20 
21 namespace gl
22 {
23 
24 // This small structure encapsulates binding sampler uniforms to active GL textures.
25 struct SamplerBinding
26 {
27     SamplerBinding(TextureType textureTypeIn,
28                    SamplerFormat formatIn,
29                    size_t elementCount,
30                    bool unreferenced);
31     SamplerBinding(const SamplerBinding &other);
32     ~SamplerBinding();
33 
34     // Necessary for retrieving active textures from the GL state.
35     TextureType textureType;
36 
37     SamplerFormat format;
38 
39     // List of all textures bound to this sampler, of type textureType.
40     std::vector<GLuint> boundTextureUnits;
41 
42     // A note if this sampler is an unreferenced uniform.
43     bool unreferenced;
44 };
45 
46 struct ImageBinding
47 {
48     ImageBinding(size_t count);
49     ImageBinding(GLuint imageUnit, size_t count, bool unreferenced);
50     ImageBinding(const ImageBinding &other);
51     ~ImageBinding();
52 
53     std::vector<GLuint> boundImageUnits;
54 
55     // A note if this image unit is an unreferenced uniform.
56     bool unreferenced;
57 };
58 
59 // A varying with transform feedback enabled. If it's an array, either the whole array or one of its
60 // elements specified by 'arrayIndex' can set to be enabled.
61 struct TransformFeedbackVarying : public sh::ShaderVariable
62 {
TransformFeedbackVaryingTransformFeedbackVarying63     TransformFeedbackVarying(const sh::ShaderVariable &varyingIn, GLuint arrayIndexIn)
64         : sh::ShaderVariable(varyingIn), arrayIndex(arrayIndexIn)
65     {
66         ASSERT(!isArrayOfArrays());
67     }
68 
TransformFeedbackVaryingTransformFeedbackVarying69     TransformFeedbackVarying(const sh::ShaderVariable &field, const sh::ShaderVariable &parent)
70         : arrayIndex(GL_INVALID_INDEX)
71     {
72         sh::ShaderVariable *thisVar = this;
73         *thisVar                    = field;
74         interpolation               = parent.interpolation;
75         isInvariant                 = parent.isInvariant;
76         name                        = parent.name + "." + name;
77         mappedName                  = parent.mappedName + "." + mappedName;
78     }
79 
nameWithArrayIndexTransformFeedbackVarying80     std::string nameWithArrayIndex() const
81     {
82         std::stringstream fullNameStr;
83         fullNameStr << name;
84         if (arrayIndex != GL_INVALID_INDEX)
85         {
86             fullNameStr << "[" << arrayIndex << "]";
87         }
88         return fullNameStr.str();
89     }
sizeTransformFeedbackVarying90     GLsizei size() const
91     {
92         return (isArray() && arrayIndex == GL_INVALID_INDEX ? getOutermostArraySize() : 1);
93     }
94 
95     GLuint arrayIndex;
96 };
97 
98 class ProgramState;
99 class ProgramPipelineState;
100 
101 class ProgramExecutable
102 {
103   public:
104     ProgramExecutable();
105     ProgramExecutable(const ProgramExecutable &other);
106     virtual ~ProgramExecutable();
107 
108     void reset();
109 
110     void save(gl::BinaryOutputStream *stream) const;
111     void load(gl::BinaryInputStream *stream);
112 
113     const ProgramState *getProgramState(ShaderType shaderType) const;
114 
115     int getInfoLogLength() const;
getInfoLog()116     InfoLog &getInfoLog() { return mInfoLog; }
117     void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
118     std::string getInfoLogString() const;
resetInfoLog()119     void resetInfoLog() { mInfoLog.reset(); }
120 
resetLinkedShaderStages()121     void resetLinkedShaderStages()
122     {
123         mLinkedComputeShaderStages.reset();
124         mLinkedGraphicsShaderStages.reset();
125     }
getLinkedShaderStages()126     const ShaderBitSet &getLinkedShaderStages() const
127     {
128         return isCompute() ? mLinkedComputeShaderStages : mLinkedGraphicsShaderStages;
129     }
setLinkedShaderStages(ShaderType shaderType)130     void setLinkedShaderStages(ShaderType shaderType)
131     {
132         if (shaderType == ShaderType::Compute)
133         {
134             mLinkedComputeShaderStages.set(ShaderType::Compute);
135         }
136         else
137         {
138             mLinkedGraphicsShaderStages.set(shaderType);
139         }
140 
141         updateCanDrawWith();
142     }
hasLinkedShaderStage(ShaderType shaderType)143     bool hasLinkedShaderStage(ShaderType shaderType) const
144     {
145         ASSERT(shaderType != ShaderType::InvalidEnum);
146         return (shaderType == ShaderType::Compute) ? mLinkedComputeShaderStages[shaderType]
147                                                    : mLinkedGraphicsShaderStages[shaderType];
148     }
getLinkedShaderStageCount()149     size_t getLinkedShaderStageCount() const
150     {
151         return isCompute() ? mLinkedComputeShaderStages.count()
152                            : mLinkedGraphicsShaderStages.count();
153     }
154     bool isCompute() const;
155 
getActiveAttribLocationsMask()156     const AttributesMask &getActiveAttribLocationsMask() const
157     {
158         return mActiveAttribLocationsMask;
159     }
160     bool isAttribLocationActive(size_t attribLocation) const;
getNonBuiltinAttribLocationsMask()161     const AttributesMask &getNonBuiltinAttribLocationsMask() const { return mAttributesMask; }
getMaxActiveAttribLocation()162     unsigned int getMaxActiveAttribLocation() const { return mMaxActiveAttribLocation; }
getAttributesTypeMask()163     const ComponentTypeMask &getAttributesTypeMask() const { return mAttributesTypeMask; }
164     AttributesMask getAttributesMask() const;
165 
getActiveSamplersMask()166     const ActiveTextureMask &getActiveSamplersMask() const { return mActiveSamplersMask; }
getSamplerFormatForTextureUnitIndex(size_t textureUnitIndex)167     SamplerFormat getSamplerFormatForTextureUnitIndex(size_t textureUnitIndex) const
168     {
169         return mActiveSamplerFormats[textureUnitIndex];
170     }
getSamplerShaderBitsForTextureUnitIndex(size_t textureUnitIndex)171     const ShaderBitSet getSamplerShaderBitsForTextureUnitIndex(size_t textureUnitIndex) const
172     {
173         return mActiveSamplerShaderBits[textureUnitIndex];
174     }
getActiveImagesMask()175     const ActiveTextureMask &getActiveImagesMask() const { return mActiveImagesMask; }
getActiveImageShaderBits()176     const ActiveTextureArray<ShaderBitSet> &getActiveImageShaderBits() const
177     {
178         return mActiveImageShaderBits;
179     }
180 
getActiveSamplerTypes()181     const ActiveTextureArray<TextureType> &getActiveSamplerTypes() const
182     {
183         return mActiveSamplerTypes;
184     }
185 
186     bool hasDefaultUniforms() const;
187     bool hasTextures() const;
188     bool hasUniformBuffers() const;
189     bool hasStorageBuffers() const;
190     bool hasAtomicCounterBuffers() const;
191     bool hasImages() const;
hasTransformFeedbackOutput()192     bool hasTransformFeedbackOutput() const
193     {
194         return !getLinkedTransformFeedbackVaryings().empty();
195     }
196 
197     // Count the number of uniform and storage buffer declarations, counting arrays as one.
getTransformFeedbackBufferCount()198     size_t getTransformFeedbackBufferCount() const { return mTransformFeedbackStrides.size(); }
199 
200     bool linkValidateGlobalNames(InfoLog &infoLog) const;
201 
202     // TODO: http://anglebug.com/4520: Remove mProgramState/mProgramPipelineState
setProgramState(ProgramState * state)203     void setProgramState(ProgramState *state)
204     {
205         ASSERT(!mProgramState && !mProgramPipelineState);
206         mProgramState = state;
207     }
setProgramPipelineState(ProgramPipelineState * state)208     void setProgramPipelineState(ProgramPipelineState *state)
209     {
210         ASSERT(!mProgramState && !mProgramPipelineState);
211         mProgramPipelineState = state;
212     }
213 
214     void setIsCompute(bool isComputeIn);
215 
216     void updateCanDrawWith();
hasVertexAndFragmentShader()217     bool hasVertexAndFragmentShader() const { return mCanDrawWith; }
218 
getProgramInputs()219     const std::vector<sh::ShaderVariable> &getProgramInputs() const { return mProgramInputs; }
getOutputVariables()220     const std::vector<sh::ShaderVariable> &getOutputVariables() const { return mOutputVariables; }
getOutputLocations()221     const std::vector<VariableLocation> &getOutputLocations() const { return mOutputLocations; }
getUniforms()222     const std::vector<LinkedUniform> &getUniforms() const { return mUniforms; }
getUniformBlocks()223     const std::vector<InterfaceBlock> &getUniformBlocks() const { return mUniformBlocks; }
getSamplerUniformRange()224     const RangeUI &getSamplerUniformRange() const { return mSamplerUniformRange; }
getImageUniformRange()225     const RangeUI &getImageUniformRange() const { return mImageUniformRange; }
getLinkedTransformFeedbackVaryings()226     const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const
227     {
228         return mLinkedTransformFeedbackVaryings;
229     }
getTransformFeedbackBufferMode()230     GLint getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; }
getUniformBlockBinding(GLuint uniformBlockIndex)231     GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const
232     {
233         ASSERT(uniformBlockIndex < mUniformBlocks.size());
234         return mUniformBlocks[uniformBlockIndex].binding;
235     }
getShaderStorageBlockBinding(GLuint blockIndex)236     GLuint getShaderStorageBlockBinding(GLuint blockIndex) const
237     {
238         ASSERT(blockIndex < mShaderStorageBlocks.size());
239         return mShaderStorageBlocks[blockIndex].binding;
240     }
getTransformFeedbackStrides()241     const std::vector<GLsizei> &getTransformFeedbackStrides() const
242     {
243         return mTransformFeedbackStrides;
244     }
getAtomicCounterBuffers()245     const std::vector<AtomicCounterBuffer> &getAtomicCounterBuffers() const
246     {
247         return mAtomicCounterBuffers;
248     }
getShaderStorageBlocks()249     const std::vector<InterfaceBlock> &getShaderStorageBlocks() const
250     {
251         return mShaderStorageBlocks;
252     }
getUniformByIndex(GLuint index)253     const LinkedUniform &getUniformByIndex(GLuint index) const
254     {
255         ASSERT(index < static_cast<size_t>(mUniforms.size()));
256         return mUniforms[index];
257     }
258 
getActiveUniformBlockCount()259     ANGLE_INLINE GLuint getActiveUniformBlockCount() const
260     {
261         return static_cast<GLuint>(mUniformBlocks.size());
262     }
263 
getActiveAtomicCounterBufferCount()264     ANGLE_INLINE GLuint getActiveAtomicCounterBufferCount() const
265     {
266         return static_cast<GLuint>(mAtomicCounterBuffers.size());
267     }
268 
getActiveShaderStorageBlockCount()269     ANGLE_INLINE GLuint getActiveShaderStorageBlockCount() const
270     {
271         return static_cast<GLuint>(mShaderStorageBlocks.size());
272     }
273 
getResources()274     gl::ProgramLinkedResources &getResources() const
275     {
276         ASSERT(mResources);
277         return *mResources;
278     }
279 
280     void saveLinkedStateInfo();
getLinkedOutputVaryings(ShaderType shaderType)281     std::vector<sh::ShaderVariable> getLinkedOutputVaryings(ShaderType shaderType)
282     {
283         return mLinkedOutputVaryings[shaderType];
284     }
getLinkedInputVaryings(ShaderType shaderType)285     std::vector<sh::ShaderVariable> getLinkedInputVaryings(ShaderType shaderType)
286     {
287         return mLinkedInputVaryings[shaderType];
288     }
getLinkedShaderVersion(ShaderType shaderType)289     int getLinkedShaderVersion(ShaderType shaderType) { return mLinkedShaderVersions[shaderType]; }
290 
291   private:
292     // TODO(timvp): http://anglebug.com/3570: Investigate removing these friend
293     // class declarations and accessing the necessary members with getters/setters.
294     friend class Program;
295     friend class ProgramPipeline;
296     friend class ProgramState;
297 
298     void updateActiveSamplers(const ProgramState &programState);
299     void updateActiveImages(std::vector<ImageBinding> &imageBindings);
300 
301     // Scans the sampler bindings for type conflicts with sampler 'textureUnitIndex'.
302     void setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex,
303                                                std::vector<SamplerBinding> &samplerBindings);
304 
305     // TODO: http://anglebug.com/4520: Remove mProgramState/mProgramPipelineState
306     ProgramState *mProgramState;
307     ProgramPipelineState *mProgramPipelineState;
308 
309     InfoLog mInfoLog;
310 
311     ShaderBitSet mLinkedGraphicsShaderStages;
312     ShaderBitSet mLinkedComputeShaderStages;
313 
314     angle::BitSet<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask;
315     unsigned int mMaxActiveAttribLocation;
316     ComponentTypeMask mAttributesTypeMask;
317     // mAttributesMask is identical to mActiveAttribLocationsMask with built-in attributes removed.
318     AttributesMask mAttributesMask;
319 
320     // Cached mask of active samplers and sampler types.
321     ActiveTextureMask mActiveSamplersMask;
322     ActiveTextureArray<uint32_t> mActiveSamplerRefCounts;
323     ActiveTextureArray<TextureType> mActiveSamplerTypes;
324     ActiveTextureArray<SamplerFormat> mActiveSamplerFormats;
325     ActiveTextureArray<ShaderBitSet> mActiveSamplerShaderBits;
326 
327     // Cached mask of active images.
328     ActiveTextureMask mActiveImagesMask;
329     ActiveTextureArray<ShaderBitSet> mActiveImageShaderBits;
330 
331     bool mCanDrawWith;
332 
333     // Names and mapped names of output variables that are arrays include [0] in the end, similarly
334     // to uniforms.
335     std::vector<sh::ShaderVariable> mOutputVariables;
336     std::vector<VariableLocation> mOutputLocations;
337     // Vertex attributes, Fragment input varyings, etc.
338     std::vector<sh::ShaderVariable> mProgramInputs;
339     std::vector<TransformFeedbackVarying> mLinkedTransformFeedbackVaryings;
340     // The size of the data written to each transform feedback buffer per vertex.
341     std::vector<GLsizei> mTransformFeedbackStrides;
342     GLenum mTransformFeedbackBufferMode;
343     // Uniforms are sorted in order:
344     //  1. Non-opaque uniforms
345     //  2. Sampler uniforms
346     //  3. Image uniforms
347     //  4. Atomic counter uniforms
348     //  5. Uniform block uniforms
349     // This makes opaque uniform validation easier, since we don't need a separate list.
350     // For generating the entries and naming them we follow the spec: GLES 3.1 November 2016 section
351     // 7.3.1.1 Naming Active Resources. There's a separate entry for each struct member and each
352     // inner array of an array of arrays. Names and mapped names of uniforms that are arrays include
353     // [0] in the end. This makes implementation of queries simpler.
354     std::vector<LinkedUniform> mUniforms;
355     RangeUI mSamplerUniformRange;
356     std::vector<InterfaceBlock> mUniformBlocks;
357     std::vector<AtomicCounterBuffer> mAtomicCounterBuffers;
358     RangeUI mImageUniformRange;
359     std::vector<InterfaceBlock> mShaderStorageBlocks;
360 
361     // TODO: http://anglebug.com/3570: Remove mPipelineHas*UniformBuffers once PPO's have valid data
362     // in mUniformBlocks
363     bool mPipelineHasGraphicsUniformBuffers;
364     bool mPipelineHasComputeUniformBuffers;
365     bool mPipelineHasGraphicsStorageBuffers;
366     bool mPipelineHasComputeStorageBuffers;
367     bool mPipelineHasGraphicsAtomicCounterBuffers;
368     bool mPipelineHasComputeAtomicCounterBuffers;
369 
370     ShaderMap<std::vector<sh::ShaderVariable>> mLinkedOutputVaryings;
371     ShaderMap<std::vector<sh::ShaderVariable>> mLinkedInputVaryings;
372     ShaderMap<int> mLinkedShaderVersions;
373     // TODO: http://anglebug.com/4514: Remove
374     std::unique_ptr<gl::ProgramLinkedResources> mResources;
375 };
376 
377 }  // namespace gl
378 
379 #endif  // LIBANGLE_PROGRAMEXECUTABLE_H_
380