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