• 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                    GLenum samplerTypeIn,
29                    SamplerFormat formatIn,
30                    size_t elementCount);
31     SamplerBinding(const SamplerBinding &other);
32     ~SamplerBinding();
33 
34     // Necessary for retrieving active textures from the GL state.
35     TextureType textureType;
36 
37     GLenum samplerType;
38 
39     SamplerFormat format;
40 
41     // List of all textures bound to this sampler, of type textureType.
42     // Cropped by the amount of unused elements reported by the driver.
43     std::vector<GLuint> boundTextureUnits;
44 };
45 
46 struct ImageBinding
47 {
48     ImageBinding(size_t count, TextureType textureTypeIn);
49     ImageBinding(GLuint imageUnit, size_t count, TextureType textureTypeIn);
50     ImageBinding(const ImageBinding &other);
51     ~ImageBinding();
52 
53     // Necessary for distinguishing between textures with images and texture buffers.
54     TextureType textureType;
55 
56     // List of all textures bound.
57     // Cropped by the amount of unused elements reported by the driver.
58     std::vector<GLuint> boundImageUnits;
59 };
60 
61 // A varying with transform feedback enabled. If it's an array, either the whole array or one of its
62 // elements specified by 'arrayIndex' can set to be enabled.
63 struct TransformFeedbackVarying : public sh::ShaderVariable
64 {
TransformFeedbackVaryingTransformFeedbackVarying65     TransformFeedbackVarying(const sh::ShaderVariable &varyingIn, GLuint arrayIndexIn)
66         : sh::ShaderVariable(varyingIn), arrayIndex(arrayIndexIn)
67     {
68         ASSERT(!isArrayOfArrays());
69     }
70 
TransformFeedbackVaryingTransformFeedbackVarying71     TransformFeedbackVarying(const sh::ShaderVariable &field, const sh::ShaderVariable &parent)
72         : arrayIndex(GL_INVALID_INDEX)
73     {
74         sh::ShaderVariable *thisVar = this;
75         *thisVar                    = field;
76         interpolation               = parent.interpolation;
77         isInvariant                 = parent.isInvariant;
78         ASSERT(parent.isShaderIOBlock || !parent.name.empty());
79         if (!parent.name.empty())
80         {
81             name       = parent.name + "." + name;
82             mappedName = parent.mappedName + "." + mappedName;
83         }
84         structOrBlockName       = parent.structOrBlockName;
85         mappedStructOrBlockName = parent.mappedStructOrBlockName;
86     }
87 
nameWithArrayIndexTransformFeedbackVarying88     std::string nameWithArrayIndex() const
89     {
90         std::stringstream fullNameStr;
91         fullNameStr << name;
92         if (arrayIndex != GL_INVALID_INDEX)
93         {
94             fullNameStr << "[" << arrayIndex << "]";
95         }
96         return fullNameStr.str();
97     }
sizeTransformFeedbackVarying98     GLsizei size() const
99     {
100         return (isArray() && arrayIndex == GL_INVALID_INDEX ? getOutermostArraySize() : 1);
101     }
102 
103     GLuint arrayIndex;
104 };
105 
106 class ProgramState;
107 class ProgramPipelineState;
108 
109 class ProgramExecutable final : public angle::Subject
110 {
111   public:
112     ProgramExecutable();
113     ProgramExecutable(const ProgramExecutable &other);
114     ~ProgramExecutable() override;
115 
116     void reset();
117 
118     void save(bool isSeparable, gl::BinaryOutputStream *stream) const;
119     void load(bool isSeparable, gl::BinaryInputStream *stream);
120 
121     int getInfoLogLength() const;
getInfoLog()122     InfoLog &getInfoLog() { return mInfoLog; }
123     void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
124     std::string getInfoLogString() const;
resetInfoLog()125     void resetInfoLog() { mInfoLog.reset(); }
126 
resetLinkedShaderStages()127     void resetLinkedShaderStages() { mLinkedShaderStages.reset(); }
getLinkedShaderStages()128     const ShaderBitSet &getLinkedShaderStages() const { return mLinkedShaderStages; }
setLinkedShaderStages(ShaderType shaderType)129     void setLinkedShaderStages(ShaderType shaderType)
130     {
131         mLinkedShaderStages.set(shaderType);
132         updateCanDrawWith();
133     }
hasLinkedShaderStage(ShaderType shaderType)134     bool hasLinkedShaderStage(ShaderType shaderType) const
135     {
136         ASSERT(shaderType != ShaderType::InvalidEnum);
137         return mLinkedShaderStages[shaderType];
138     }
getLinkedShaderStageCount()139     size_t getLinkedShaderStageCount() const { return mLinkedShaderStages.count(); }
hasLinkedTessellationShader()140     bool hasLinkedTessellationShader() const
141     {
142         return mLinkedShaderStages[ShaderType::TessEvaluation];
143     }
144 
145     ShaderType getLinkedTransformFeedbackStage() const;
146 
getActiveAttribLocationsMask()147     const AttributesMask &getActiveAttribLocationsMask() const
148     {
149         return mActiveAttribLocationsMask;
150     }
151     bool isAttribLocationActive(size_t attribLocation) const;
getNonBuiltinAttribLocationsMask()152     const AttributesMask &getNonBuiltinAttribLocationsMask() const { return mAttributesMask; }
getMaxActiveAttribLocation()153     unsigned int getMaxActiveAttribLocation() const { return mMaxActiveAttribLocation; }
getAttributesTypeMask()154     const ComponentTypeMask &getAttributesTypeMask() const { return mAttributesTypeMask; }
155     AttributesMask getAttributesMask() const;
156 
getActiveSamplersMask()157     const ActiveTextureMask &getActiveSamplersMask() const { return mActiveSamplersMask; }
setActiveTextureMask(ActiveTextureMask mask)158     void setActiveTextureMask(ActiveTextureMask mask) { mActiveSamplersMask = mask; }
getSamplerFormatForTextureUnitIndex(size_t textureUnitIndex)159     SamplerFormat getSamplerFormatForTextureUnitIndex(size_t textureUnitIndex) const
160     {
161         return mActiveSamplerFormats[textureUnitIndex];
162     }
getSamplerShaderBitsForTextureUnitIndex(size_t textureUnitIndex)163     const ShaderBitSet getSamplerShaderBitsForTextureUnitIndex(size_t textureUnitIndex) const
164     {
165         return mActiveSamplerShaderBits[textureUnitIndex];
166     }
getActiveImagesMask()167     const ActiveTextureMask &getActiveImagesMask() const { return mActiveImagesMask; }
setActiveImagesMask(ActiveTextureMask mask)168     void setActiveImagesMask(ActiveTextureMask mask) { mActiveImagesMask = mask; }
getActiveImageShaderBits()169     const ActiveTextureArray<ShaderBitSet> &getActiveImageShaderBits() const
170     {
171         return mActiveImageShaderBits;
172     }
173 
getActiveYUVSamplers()174     const ActiveTextureMask &getActiveYUVSamplers() const { return mActiveSamplerYUV; }
175 
getActiveSamplerTypes()176     const ActiveTextureArray<TextureType> &getActiveSamplerTypes() const
177     {
178         return mActiveSamplerTypes;
179     }
180 
181     void updateActiveSamplers(const ProgramState &programState);
182 
183     bool hasDefaultUniforms() const;
184     bool hasTextures() const;
185     bool hasUniformBuffers() const;
186     bool hasStorageBuffers() const;
187     bool hasAtomicCounterBuffers() const;
188     bool hasImages() const;
hasTransformFeedbackOutput()189     bool hasTransformFeedbackOutput() const
190     {
191         return !getLinkedTransformFeedbackVaryings().empty();
192     }
193     bool usesFramebufferFetch() const;
194 
195     // Count the number of uniform and storage buffer declarations, counting arrays as one.
getTransformFeedbackBufferCount()196     size_t getTransformFeedbackBufferCount() const { return mTransformFeedbackStrides.size(); }
197 
198     void updateCanDrawWith();
hasVertexShader()199     bool hasVertexShader() const { return mCanDrawWith; }
200 
getProgramInputs()201     const std::vector<sh::ShaderVariable> &getProgramInputs() const { return mProgramInputs; }
getOutputVariables()202     const std::vector<sh::ShaderVariable> &getOutputVariables() const { return mOutputVariables; }
getOutputLocations()203     const std::vector<VariableLocation> &getOutputLocations() const { return mOutputLocations; }
getSecondaryOutputLocations()204     const std::vector<VariableLocation> &getSecondaryOutputLocations() const
205     {
206         return mSecondaryOutputLocations;
207     }
getUniforms()208     const std::vector<LinkedUniform> &getUniforms() const { return mUniforms; }
getUniformBlocks()209     const std::vector<InterfaceBlock> &getUniformBlocks() const { return mUniformBlocks; }
getActiveUniformBlockBindings()210     const UniformBlockBindingMask &getActiveUniformBlockBindings() const
211     {
212         return mActiveUniformBlockBindings;
213     }
getSamplerBindings()214     const std::vector<SamplerBinding> &getSamplerBindings() const { return mSamplerBindings; }
getImageBindings()215     const std::vector<ImageBinding> &getImageBindings() const { return mImageBindings; }
getImageBindings()216     std::vector<ImageBinding> *getImageBindings() { return &mImageBindings; }
getDefaultUniformRange()217     const RangeUI &getDefaultUniformRange() const { return mDefaultUniformRange; }
getSamplerUniformRange()218     const RangeUI &getSamplerUniformRange() const { return mSamplerUniformRange; }
getImageUniformRange()219     const RangeUI &getImageUniformRange() const { return mImageUniformRange; }
getFragmentInoutRange()220     const RangeUI &getFragmentInoutRange() const { return mFragmentInoutRange; }
getLinkedTransformFeedbackVaryings()221     const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const
222     {
223         return mLinkedTransformFeedbackVaryings;
224     }
getTransformFeedbackBufferMode()225     GLint getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; }
getUniformBlockBinding(GLuint uniformBlockIndex)226     GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const
227     {
228         ASSERT(uniformBlockIndex < mUniformBlocks.size());
229         return mUniformBlocks[uniformBlockIndex].binding;
230     }
getShaderStorageBlockBinding(GLuint blockIndex)231     GLuint getShaderStorageBlockBinding(GLuint blockIndex) const
232     {
233         ASSERT(blockIndex < mShaderStorageBlocks.size());
234         return mShaderStorageBlocks[blockIndex].binding;
235     }
getTransformFeedbackStrides()236     const std::vector<GLsizei> &getTransformFeedbackStrides() const
237     {
238         return mTransformFeedbackStrides;
239     }
getAtomicCounterBuffers()240     const std::vector<AtomicCounterBuffer> &getAtomicCounterBuffers() const
241     {
242         return mAtomicCounterBuffers;
243     }
getShaderStorageBlocks()244     const std::vector<InterfaceBlock> &getShaderStorageBlocks() const
245     {
246         return mShaderStorageBlocks;
247     }
getUniformByIndex(GLuint index)248     const LinkedUniform &getUniformByIndex(GLuint index) const
249     {
250         ASSERT(index < static_cast<size_t>(mUniforms.size()));
251         return mUniforms[index];
252     }
253 
getActiveUniformBlockCount()254     ANGLE_INLINE GLuint getActiveUniformBlockCount() const
255     {
256         return static_cast<GLuint>(mUniformBlocks.size());
257     }
258 
getActiveAtomicCounterBufferCount()259     ANGLE_INLINE GLuint getActiveAtomicCounterBufferCount() const
260     {
261         return static_cast<GLuint>(mAtomicCounterBuffers.size());
262     }
263 
getActiveShaderStorageBlockCount()264     ANGLE_INLINE GLuint getActiveShaderStorageBlockCount() const
265     {
266         size_t shaderStorageBlocksSize = mShaderStorageBlocks.size();
267         return static_cast<GLuint>(shaderStorageBlocksSize);
268     }
269 
270     GLuint getUniformIndexFromImageIndex(GLuint imageIndex) const;
271 
272     void saveLinkedStateInfo(const ProgramState &state);
getLinkedOutputVaryings(ShaderType shaderType)273     const std::vector<sh::ShaderVariable> &getLinkedOutputVaryings(ShaderType shaderType) const
274     {
275         return mLinkedOutputVaryings[shaderType];
276     }
getLinkedInputVaryings(ShaderType shaderType)277     const std::vector<sh::ShaderVariable> &getLinkedInputVaryings(ShaderType shaderType) const
278     {
279         return mLinkedInputVaryings[shaderType];
280     }
281 
getLinkedUniforms(ShaderType shaderType)282     const std::vector<sh::ShaderVariable> &getLinkedUniforms(ShaderType shaderType) const
283     {
284         return mLinkedUniforms[shaderType];
285     }
286 
getLinkedUniformBlocks(ShaderType shaderType)287     const std::vector<sh::InterfaceBlock> &getLinkedUniformBlocks(ShaderType shaderType) const
288     {
289         return mLinkedUniformBlocks[shaderType];
290     }
291 
getLinkedShaderVersion(ShaderType shaderType)292     int getLinkedShaderVersion(ShaderType shaderType) const
293     {
294         return mLinkedShaderVersions[shaderType];
295     }
296 
297     bool isYUVOutput() const;
298 
getGeometryShaderInputPrimitiveType()299     PrimitiveMode getGeometryShaderInputPrimitiveType() const
300     {
301         return mGeometryShaderInputPrimitiveType;
302     }
303 
getGeometryShaderOutputPrimitiveType()304     PrimitiveMode getGeometryShaderOutputPrimitiveType() const
305     {
306         return mGeometryShaderOutputPrimitiveType;
307     }
308 
getGeometryShaderInvocations()309     int getGeometryShaderInvocations() const { return mGeometryShaderInvocations; }
310 
getGeometryShaderMaxVertices()311     int getGeometryShaderMaxVertices() const { return mGeometryShaderMaxVertices; }
312 
getTessGenMode()313     GLenum getTessGenMode() const { return mTessGenMode; }
314 
resetCachedValidateSamplersResult()315     void resetCachedValidateSamplersResult() { mCachedValidateSamplersResult.reset(); }
validateSamplers(InfoLog * infoLog,const Caps & caps)316     bool validateSamplers(InfoLog *infoLog, const Caps &caps) const
317     {
318         // Use the cache if:
319         // - we aren't using an info log (which gives the full error).
320         // - The sample mapping hasn't changed and we've already validated.
321         if (infoLog == nullptr && mCachedValidateSamplersResult.valid())
322         {
323             return mCachedValidateSamplersResult.value();
324         }
325 
326         return validateSamplersImpl(infoLog, caps);
327     }
328 
getFragmentOutputsTypeMask()329     ComponentTypeMask getFragmentOutputsTypeMask() const { return mDrawBufferTypeMask; }
getActiveOutputVariablesMask()330     DrawBufferMask getActiveOutputVariablesMask() const { return mActiveOutputVariablesMask; }
331 
332   private:
333     // TODO(timvp): http://anglebug.com/3570: Investigate removing these friend
334     // class declarations and accessing the necessary members with getters/setters.
335     friend class Program;
336     friend class ProgramPipeline;
337     friend class ProgramState;
338 
339     void updateActiveImages(const ProgramExecutable &executable);
340 
341     // Scans the sampler bindings for type conflicts with sampler 'textureUnitIndex'.
342     void setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex,
343                                                std::vector<SamplerBinding> &samplerBindings);
344 
345     bool linkMergedVaryings(const Context *context,
346                             const ProgramMergedVaryings &mergedVaryings,
347                             const std::vector<std::string> &transformFeedbackVaryingNames,
348                             const LinkingVariables &linkingVariables,
349                             bool isSeparable,
350                             ProgramVaryingPacking *varyingPacking);
351 
352     bool linkValidateTransformFeedback(
353         const Context *context,
354         const ProgramMergedVaryings &varyings,
355         ShaderType stage,
356         const std::vector<std::string> &transformFeedbackVaryingNames);
357 
358     void gatherTransformFeedbackVaryings(
359         const ProgramMergedVaryings &varyings,
360         ShaderType stage,
361         const std::vector<std::string> &transformFeedbackVaryingNames);
362 
363     void updateTransformFeedbackStrides();
364 
365     bool validateSamplersImpl(InfoLog *infoLog, const Caps &caps) const;
366 
367     bool linkValidateOutputVariables(const Caps &caps,
368                                      const Extensions &extensions,
369                                      const Version &version,
370                                      GLuint combinedImageUniformsCount,
371                                      GLuint combinedShaderStorageBlocksCount,
372                                      const std::vector<sh::ShaderVariable> &outputVariables,
373                                      int fragmentShaderVersion,
374                                      const ProgramAliasedBindings &fragmentOutputLocations,
375                                      const ProgramAliasedBindings &fragmentOutputIndices);
376 
377     InfoLog mInfoLog;
378 
379     ShaderBitSet mLinkedShaderStages;
380 
381     angle::BitSet<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask;
382     unsigned int mMaxActiveAttribLocation;
383     ComponentTypeMask mAttributesTypeMask;
384     // mAttributesMask is identical to mActiveAttribLocationsMask with built-in attributes removed.
385     AttributesMask mAttributesMask;
386 
387     // Cached mask of active samplers and sampler types.
388     ActiveTextureMask mActiveSamplersMask;
389     ActiveTextureArray<uint32_t> mActiveSamplerRefCounts;
390     ActiveTextureArray<TextureType> mActiveSamplerTypes;
391     ActiveTextureMask mActiveSamplerYUV;
392     ActiveTextureArray<SamplerFormat> mActiveSamplerFormats;
393     ActiveTextureArray<ShaderBitSet> mActiveSamplerShaderBits;
394 
395     // Cached mask of active images.
396     ActiveTextureMask mActiveImagesMask;
397     ActiveTextureArray<ShaderBitSet> mActiveImageShaderBits;
398 
399     bool mCanDrawWith;
400 
401     // Names and mapped names of output variables that are arrays include [0] in the end, similarly
402     // to uniforms.
403     std::vector<sh::ShaderVariable> mOutputVariables;
404     std::vector<VariableLocation> mOutputLocations;
405     DrawBufferMask mActiveOutputVariablesMask;
406     // EXT_blend_func_extended secondary outputs (ones with index 1)
407     std::vector<VariableLocation> mSecondaryOutputLocations;
408     bool mYUVOutput;
409     // Vertex attributes, Fragment input varyings, etc.
410     std::vector<sh::ShaderVariable> mProgramInputs;
411     std::vector<TransformFeedbackVarying> mLinkedTransformFeedbackVaryings;
412     // The size of the data written to each transform feedback buffer per vertex.
413     std::vector<GLsizei> mTransformFeedbackStrides;
414     GLenum mTransformFeedbackBufferMode;
415     // Uniforms are sorted in order:
416     //  1. Non-opaque uniforms
417     //  2. Sampler uniforms
418     //  3. Image uniforms
419     //  4. Atomic counter uniforms
420     //  5. Subpass Input uniforms (Only for Vulkan)
421     //  6. Uniform block uniforms
422     // This makes opaque uniform validation easier, since we don't need a separate list.
423     // For generating the entries and naming them we follow the spec: GLES 3.1 November 2016 section
424     // 7.3.1.1 Naming Active Resources. There's a separate entry for each struct member and each
425     // inner array of an array of arrays. Names and mapped names of uniforms that are arrays include
426     // [0] in the end. This makes implementation of queries simpler.
427     std::vector<LinkedUniform> mUniforms;
428     RangeUI mDefaultUniformRange;
429     RangeUI mSamplerUniformRange;
430     std::vector<InterfaceBlock> mUniformBlocks;
431 
432     // For faster iteration on the blocks currently being bound.
433     UniformBlockBindingMask mActiveUniformBlockBindings;
434 
435     std::vector<AtomicCounterBuffer> mAtomicCounterBuffers;
436     RangeUI mImageUniformRange;
437     std::vector<InterfaceBlock> mShaderStorageBlocks;
438     RangeUI mFragmentInoutRange;
439 
440     // An array of the samplers that are used by the program
441     std::vector<SamplerBinding> mSamplerBindings;
442 
443     // An array of the images that are used by the program
444     std::vector<ImageBinding> mImageBindings;
445 
446     // TODO: http://anglebug.com/3570: Remove mPipelineHas*UniformBuffers once PPO's have valid data
447     // in mUniformBlocks
448     bool mPipelineHasUniformBuffers;
449     bool mPipelineHasStorageBuffers;
450     bool mPipelineHasAtomicCounterBuffers;
451     bool mPipelineHasDefaultUniforms;
452     bool mPipelineHasTextures;
453     bool mPipelineHasImages;
454 
455     ShaderMap<std::vector<sh::ShaderVariable>> mLinkedOutputVaryings;
456     ShaderMap<std::vector<sh::ShaderVariable>> mLinkedInputVaryings;
457     ShaderMap<std::vector<sh::ShaderVariable>> mLinkedUniforms;
458     ShaderMap<std::vector<sh::InterfaceBlock>> mLinkedUniformBlocks;
459 
460     ShaderMap<int> mLinkedShaderVersions;
461 
462     // GL_EXT_geometry_shader.
463     PrimitiveMode mGeometryShaderInputPrimitiveType;
464     PrimitiveMode mGeometryShaderOutputPrimitiveType;
465     int mGeometryShaderInvocations;
466     int mGeometryShaderMaxVertices;
467 
468     // GL_EXT_tessellation_shader
469     int mTessControlShaderVertices;
470     GLenum mTessGenMode;
471     GLenum mTessGenSpacing;
472     GLenum mTessGenVertexOrder;
473     GLenum mTessGenPointMode;
474 
475     // Fragment output variable base types: FLOAT, INT, or UINT.  Ordered by location.
476     std::vector<GLenum> mOutputVariableTypes;
477     ComponentTypeMask mDrawBufferTypeMask;
478 
479     // Cache for sampler validation
480     mutable Optional<bool> mCachedValidateSamplersResult;
481 };
482 }  // namespace gl
483 
484 #endif  // LIBANGLE_PROGRAMEXECUTABLE_H_
485