• 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 rx
22 {
23 class GLImplFactory;
24 class LinkSubTask;
25 class ProgramExecutableImpl;
26 }  // namespace rx
27 
28 namespace gl
29 {
30 
31 // This small structure encapsulates binding sampler uniforms to active GL textures.
32 ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
33 struct SamplerBinding
34 {
35     SamplerBinding() = default;
SamplerBindingSamplerBinding36     SamplerBinding(TextureType textureTypeIn,
37                    GLenum samplerTypeIn,
38                    SamplerFormat formatIn,
39                    uint16_t startIndex,
40                    uint16_t elementCount)
41         : textureType(textureTypeIn),
42           format(formatIn),
43           textureUnitsStartIndex(startIndex),
44           textureUnitsCount(elementCount)
45     {
46         SetBitField(samplerType, samplerTypeIn);
47     }
48 
getTextureUnitSamplerBinding49     GLuint getTextureUnit(const std::vector<GLuint> &boundTextureUnits,
50                           unsigned int arrayIndex) const
51     {
52         return boundTextureUnits[textureUnitsStartIndex + arrayIndex];
53     }
54 
55     // Necessary for retrieving active textures from the GL state.
56     TextureType textureType;
57     SamplerFormat format;
58     uint16_t samplerType;
59     // [textureUnitsStartIndex, textureUnitsStartIndex+textureUnitsCount) Points to the subset in
60     // mSamplerBoundTextureUnits that stores the texture unit bound to this sampler. Cropped by the
61     // amount of unused elements reported by the driver.
62     uint16_t textureUnitsStartIndex;
63     uint16_t textureUnitsCount;
64 };
65 ANGLE_DISABLE_STRUCT_PADDING_WARNINGS
66 
67 struct ImageBinding
68 {
69     ImageBinding() = default;
ImageBindingImageBinding70     ImageBinding(size_t count, TextureType textureTypeIn)
71         : textureType(textureTypeIn), boundImageUnits(count, 0)
72     {}
73     ImageBinding(GLuint imageUnit, size_t count, TextureType textureTypeIn);
74 
75     // Necessary for distinguishing between textures with images and texture buffers.
76     TextureType textureType;
77 
78     // List of all textures bound.
79     // Cropped by the amount of unused elements reported by the driver.
80     std::vector<GLuint> boundImageUnits;
81 };
82 
83 ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
84 struct ProgramInput
85 {
86     ProgramInput() = default;
87     ProgramInput(const sh::ShaderVariable &var);
88 
getTypeProgramInput89     GLenum getType() const { return pod.type; }
isBuiltInProgramInput90     bool isBuiltIn() const { return pod.flagBits.isBuiltIn; }
isArrayProgramInput91     bool isArray() const { return pod.flagBits.isArray; }
isActiveProgramInput92     bool isActive() const { return pod.flagBits.active; }
isPatchProgramInput93     bool isPatch() const { return pod.flagBits.isPatch; }
getLocationProgramInput94     int getLocation() const { return pod.location; }
getBasicTypeElementCountProgramInput95     unsigned int getBasicTypeElementCount() const { return pod.basicTypeElementCount; }
getArraySizeProductProgramInput96     unsigned int getArraySizeProduct() const { return pod.arraySizeProduct; }
getIdProgramInput97     uint32_t getId() const { return pod.id; }
getInterpolationProgramInput98     sh::InterpolationType getInterpolation() const
99     {
100         return static_cast<sh::InterpolationType>(pod.interpolation);
101     }
102 
setLocationProgramInput103     void setLocation(int location) { pod.location = location; }
resetEffectiveLocationProgramInput104     void resetEffectiveLocation()
105     {
106         if (pod.flagBits.hasImplicitLocation)
107         {
108             pod.location = -1;
109         }
110     }
111 
112     std::string name;
113     std::string mappedName;
114 
115     // The struct bellow must only contain data of basic type so that entire struct can memcpy-able.
116     struct PODStruct
117     {
118         uint16_t type;  // GLenum
119         uint16_t arraySizeProduct;
120 
121         int location;
122 
123         uint8_t interpolation;  // sh::InterpolationType
124         union
125         {
126             struct
127             {
128                 uint8_t active : 1;
129                 uint8_t isPatch : 1;
130                 uint8_t hasImplicitLocation : 1;
131                 uint8_t isArray : 1;
132                 uint8_t isBuiltIn : 1;
133                 uint8_t padding : 3;
134             } flagBits;
135             uint8_t flagBitsAsUByte;
136         };
137         int16_t basicTypeElementCount;
138 
139         uint32_t id;
140     } pod;
141 };
142 ANGLE_DISABLE_STRUCT_PADDING_WARNINGS
143 
144 ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
145 struct ProgramOutput
146 {
147     ProgramOutput() = default;
148     ProgramOutput(const sh::ShaderVariable &var);
isBuiltInProgramOutput149     bool isBuiltIn() const { return pod.isBuiltIn; }
isArrayProgramOutput150     bool isArray() const { return pod.isArray; }
getOutermostArraySizeProgramOutput151     unsigned int getOutermostArraySize() const { return pod.outermostArraySize; }
resetEffectiveLocationProgramOutput152     void resetEffectiveLocation()
153     {
154         if (pod.hasImplicitLocation)
155         {
156             pod.location = -1;
157         }
158     }
159 
160     std::string name;
161     std::string mappedName;
162 
163     struct PODStruct
164     {
165         GLenum type;
166         int location;
167         int index;
168         uint32_t id;
169 
170         uint16_t outermostArraySize;
171         uint16_t basicTypeElementCount;
172 
173         uint32_t isPatch : 1;
174         uint32_t yuv : 1;
175         uint32_t isBuiltIn : 1;
176         uint32_t isArray : 1;
177         uint32_t hasImplicitLocation : 1;
178         uint32_t pad : 27;
179     } pod;
180 };
181 ANGLE_DISABLE_STRUCT_PADDING_WARNINGS
182 
183 // A varying with transform feedback enabled. If it's an array, either the whole array or one of its
184 // elements specified by 'arrayIndex' can set to be enabled.
185 struct TransformFeedbackVarying : public sh::ShaderVariable
186 {
187     TransformFeedbackVarying() = default;
188 
TransformFeedbackVaryingTransformFeedbackVarying189     TransformFeedbackVarying(const sh::ShaderVariable &varyingIn, GLuint arrayIndexIn)
190         : sh::ShaderVariable(varyingIn), arrayIndex(arrayIndexIn)
191     {
192         ASSERT(!isArrayOfArrays());
193     }
194 
TransformFeedbackVaryingTransformFeedbackVarying195     TransformFeedbackVarying(const sh::ShaderVariable &field, const sh::ShaderVariable &parent)
196         : arrayIndex(GL_INVALID_INDEX)
197     {
198         sh::ShaderVariable *thisVar = this;
199         *thisVar                    = field;
200         interpolation               = parent.interpolation;
201         isInvariant                 = parent.isInvariant;
202         ASSERT(parent.isShaderIOBlock || !parent.name.empty());
203         if (!parent.name.empty())
204         {
205             name       = parent.name + "." + name;
206             mappedName = parent.mappedName + "." + mappedName;
207         }
208         structOrBlockName       = parent.structOrBlockName;
209         mappedStructOrBlockName = parent.mappedStructOrBlockName;
210     }
211 
nameWithArrayIndexTransformFeedbackVarying212     std::string nameWithArrayIndex() const
213     {
214         std::stringstream fullNameStr;
215         fullNameStr << name;
216         if (arrayIndex != GL_INVALID_INDEX)
217         {
218             fullNameStr << "[" << arrayIndex << "]";
219         }
220         return fullNameStr.str();
221     }
sizeTransformFeedbackVarying222     GLsizei size() const
223     {
224         return (isArray() && arrayIndex == GL_INVALID_INDEX ? getOutermostArraySize() : 1);
225     }
226 
227     GLuint arrayIndex;
228 };
229 
230 class ProgramState;
231 class ProgramPipelineState;
232 
233 class ProgramExecutable;
234 using SharedProgramExecutable = std::shared_ptr<ProgramExecutable>;
235 
236 class ProgramExecutable final : public angle::Subject
237 {
238   public:
239     ProgramExecutable(rx::GLImplFactory *factory, InfoLog *infoLog);
240     ~ProgramExecutable() override;
241 
242     void destroy(const Context *context);
243 
getImplementation()244     ANGLE_INLINE rx::ProgramExecutableImpl *getImplementation() const { return mImplementation; }
245 
246     void save(gl::BinaryOutputStream *stream) const;
247     void load(gl::BinaryInputStream *stream);
248 
getInfoLog()249     InfoLog &getInfoLog() const { return *mInfoLog; }
250     std::string getInfoLogString() const;
resetInfoLog()251     void resetInfoLog() const { mInfoLog->reset(); }
252 
resetLinkedShaderStages()253     void resetLinkedShaderStages() { mPod.linkedShaderStages.reset(); }
getLinkedShaderStages()254     const ShaderBitSet getLinkedShaderStages() const { return mPod.linkedShaderStages; }
setLinkedShaderStages(ShaderType shaderType)255     void setLinkedShaderStages(ShaderType shaderType)
256     {
257         mPod.linkedShaderStages.set(shaderType);
258         updateCanDrawWith();
259     }
hasLinkedShaderStage(ShaderType shaderType)260     bool hasLinkedShaderStage(ShaderType shaderType) const
261     {
262         ASSERT(shaderType != ShaderType::InvalidEnum);
263         return mPod.linkedShaderStages[shaderType];
264     }
getLinkedShaderStageCount()265     size_t getLinkedShaderStageCount() const { return mPod.linkedShaderStages.count(); }
hasLinkedGraphicsShader()266     bool hasLinkedGraphicsShader() const
267     {
268         return mPod.linkedShaderStages.any() &&
269                mPod.linkedShaderStages != gl::ShaderBitSet{gl::ShaderType::Compute};
270     }
hasLinkedTessellationShader()271     bool hasLinkedTessellationShader() const
272     {
273         return mPod.linkedShaderStages[ShaderType::TessEvaluation];
274     }
275     ShaderType getFirstLinkedShaderStageType() const;
276     ShaderType getLastLinkedShaderStageType() const;
277 
getLinkedTransformFeedbackStage()278     ShaderType getLinkedTransformFeedbackStage() const
279     {
280         return GetLastPreFragmentStage(mPod.linkedShaderStages);
281     }
282 
getActiveAttribLocationsMask()283     const AttributesMask &getActiveAttribLocationsMask() const
284     {
285         return mPod.activeAttribLocationsMask;
286     }
isAttribLocationActive(size_t attribLocation)287     bool isAttribLocationActive(size_t attribLocation) const
288     {
289         ASSERT(attribLocation < mPod.activeAttribLocationsMask.size());
290         return mPod.activeAttribLocationsMask[attribLocation];
291     }
292 
getNonBuiltinAttribLocationsMask()293     AttributesMask getNonBuiltinAttribLocationsMask() const { return mPod.attributesMask; }
getMaxActiveAttribLocation()294     unsigned int getMaxActiveAttribLocation() const { return mPod.maxActiveAttribLocation; }
getAttributesTypeMask()295     ComponentTypeMask getAttributesTypeMask() const { return mPod.attributesTypeMask; }
getAttributesMask()296     AttributesMask getAttributesMask() const { return mPod.attributesMask; }
297 
getActiveSamplersMask()298     const ActiveTextureMask &getActiveSamplersMask() const { return mActiveSamplersMask; }
setActiveTextureMask(ActiveTextureMask mask)299     void setActiveTextureMask(ActiveTextureMask mask) { mActiveSamplersMask = mask; }
getSamplerFormatForTextureUnitIndex(size_t textureUnitIndex)300     SamplerFormat getSamplerFormatForTextureUnitIndex(size_t textureUnitIndex) const
301     {
302         return mActiveSamplerFormats[textureUnitIndex];
303     }
getSamplerShaderBitsForTextureUnitIndex(size_t textureUnitIndex)304     const ShaderBitSet getSamplerShaderBitsForTextureUnitIndex(size_t textureUnitIndex) const
305     {
306         return mActiveSamplerShaderBits[textureUnitIndex];
307     }
getActiveImagesMask()308     const ActiveTextureMask &getActiveImagesMask() const { return mActiveImagesMask; }
setActiveImagesMask(ActiveTextureMask mask)309     void setActiveImagesMask(ActiveTextureMask mask) { mActiveImagesMask = mask; }
getActiveImageShaderBits()310     const ActiveTextureArray<ShaderBitSet> &getActiveImageShaderBits() const
311     {
312         return mActiveImageShaderBits;
313     }
314 
getActiveYUVSamplers()315     const ActiveTextureMask &getActiveYUVSamplers() const { return mActiveSamplerYUV; }
316 
getActiveSamplerTypes()317     const ActiveTextureArray<TextureType> &getActiveSamplerTypes() const
318     {
319         return mActiveSamplerTypes;
320     }
321 
322     void setActive(size_t textureUnit,
323                    const SamplerBinding &samplerBinding,
324                    const gl::LinkedUniform &samplerUniform);
325     void setInactive(size_t textureUnit);
326     void hasSamplerTypeConflict(size_t textureUnit);
327     void hasSamplerFormatConflict(size_t textureUnit);
328 
329     void updateActiveSamplers(const ProgramExecutable &executable);
330 
hasDefaultUniforms()331     bool hasDefaultUniforms() const { return !getDefaultUniformRange().empty(); }
hasTextures()332     bool hasTextures() const { return !getSamplerBindings().empty(); }
hasUniformBuffers()333     bool hasUniformBuffers() const { return !mUniformBlocks.empty(); }
hasStorageBuffers()334     bool hasStorageBuffers() const { return !mShaderStorageBlocks.empty(); }
hasAtomicCounterBuffers()335     bool hasAtomicCounterBuffers() const { return !mAtomicCounterBuffers.empty(); }
hasImages()336     bool hasImages() const { return !mImageBindings.empty(); }
hasTransformFeedbackOutput()337     bool hasTransformFeedbackOutput() const
338     {
339         return !getLinkedTransformFeedbackVaryings().empty();
340     }
usesFramebufferFetch()341     bool usesFramebufferFetch() const { return mPod.fragmentInoutIndices.any(); }
342 
343     // Count the number of uniform and storage buffer declarations, counting arrays as one.
getTransformFeedbackBufferCount()344     size_t getTransformFeedbackBufferCount() const { return mTransformFeedbackStrides.size(); }
345 
updateCanDrawWith()346     void updateCanDrawWith() { mPod.canDrawWith = hasLinkedShaderStage(ShaderType::Vertex); }
hasVertexShader()347     bool hasVertexShader() const { return mPod.canDrawWith; }
348 
getProgramInputs()349     const std::vector<ProgramInput> &getProgramInputs() const { return mProgramInputs; }
getOutputVariables()350     const std::vector<ProgramOutput> &getOutputVariables() const { return mOutputVariables; }
getOutputLocations()351     const std::vector<VariableLocation> &getOutputLocations() const { return mOutputLocations; }
getSecondaryOutputLocations()352     const std::vector<VariableLocation> &getSecondaryOutputLocations() const
353     {
354         return mSecondaryOutputLocations;
355     }
getUniforms()356     const std::vector<LinkedUniform> &getUniforms() const { return mUniforms; }
getUniformNames()357     const std::vector<std::string> &getUniformNames() const { return mUniformNames; }
getUniformMappedNames()358     const std::vector<std::string> &getUniformMappedNames() const { return mUniformMappedNames; }
getUniformBlocks()359     const std::vector<InterfaceBlock> &getUniformBlocks() const { return mUniformBlocks; }
getUniformLocations()360     const std::vector<VariableLocation> &getUniformLocations() const { return mUniformLocations; }
getSamplerBindings()361     const std::vector<SamplerBinding> &getSamplerBindings() const { return mSamplerBindings; }
getSamplerBoundTextureUnits()362     const std::vector<GLuint> &getSamplerBoundTextureUnits() const
363     {
364         return mSamplerBoundTextureUnits;
365     }
getImageBindings()366     const std::vector<ImageBinding> &getImageBindings() const { return mImageBindings; }
getImageBindings()367     std::vector<ImageBinding> *getImageBindings() { return &mImageBindings; }
getDefaultUniformRange()368     const RangeUI &getDefaultUniformRange() const { return mPod.defaultUniformRange; }
getSamplerUniformRange()369     const RangeUI &getSamplerUniformRange() const { return mPod.samplerUniformRange; }
getImageUniformRange()370     const RangeUI &getImageUniformRange() const { return mPod.imageUniformRange; }
getAtomicCounterUniformRange()371     const RangeUI &getAtomicCounterUniformRange() const { return mPod.atomicCounterUniformRange; }
getFragmentInoutIndices()372     DrawBufferMask getFragmentInoutIndices() const { return mPod.fragmentInoutIndices; }
hasClipDistance()373     bool hasClipDistance() const { return mPod.hasClipDistance; }
hasDiscard()374     bool hasDiscard() const { return mPod.hasDiscard; }
enablesPerSampleShading()375     bool enablesPerSampleShading() const { return mPod.enablesPerSampleShading; }
getAdvancedBlendEquations()376     BlendEquationBitSet getAdvancedBlendEquations() const { return mPod.advancedBlendEquations; }
getLinkedTransformFeedbackVaryings()377     const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const
378     {
379         return mLinkedTransformFeedbackVaryings;
380     }
getTransformFeedbackBufferMode()381     GLint getTransformFeedbackBufferMode() const { return mPod.transformFeedbackBufferMode; }
getComputeShaderLocalSize()382     const sh::WorkGroupSize &getComputeShaderLocalSize() const
383     {
384         return mPod.computeShaderLocalSize;
385     }
386     void remapUniformBlockBinding(UniformBlockIndex uniformBlockIndex, GLuint uniformBlockBinding);
getUniformBlockBinding(size_t uniformBlockIndex)387     GLuint getUniformBlockBinding(size_t uniformBlockIndex) const
388     {
389         ASSERT(uniformBlockIndex < mUniformBlocks.size());
390 
391         // Unlike SSBOs and atomic counter buffers, GLES allows UBOs bindings to be remapped.  Note
392         // that desktop GL allows SSBO bindings to also be remapped, but that's not allowed in GLES.
393         //
394         // It's therefore important to never directly reference block.pod.inShaderBinding unless the
395         // specific shader-specified binding is required.
396         return mUniformBlockIndexToBufferBinding[uniformBlockIndex];
397     }
getShaderStorageBlockBinding(size_t blockIndex)398     GLuint getShaderStorageBlockBinding(size_t blockIndex) const
399     {
400         ASSERT(blockIndex < mShaderStorageBlocks.size());
401         // The buffer binding for SSBOs is the one specified in the shader
402         return mShaderStorageBlocks[blockIndex].pod.inShaderBinding;
403     }
getAtomicCounterBufferBinding(size_t blockIndex)404     GLuint getAtomicCounterBufferBinding(size_t blockIndex) const
405     {
406         ASSERT(blockIndex < mAtomicCounterBuffers.size());
407         // The buffer binding for atomic counter buffers is the one specified in the shader
408         return mAtomicCounterBuffers[blockIndex].pod.inShaderBinding;
409     }
getUniformBlockByIndex(size_t index)410     const InterfaceBlock &getUniformBlockByIndex(size_t index) const
411     {
412         ASSERT(index < mUniformBlocks.size());
413         return mUniformBlocks[index];
414     }
getShaderStorageBlockByIndex(size_t index)415     const InterfaceBlock &getShaderStorageBlockByIndex(size_t index) const
416     {
417         ASSERT(index < mShaderStorageBlocks.size());
418         return mShaderStorageBlocks[index];
419     }
getBufferVariableByIndex(size_t index)420     const BufferVariable &getBufferVariableByIndex(size_t index) const
421     {
422         ASSERT(index < mBufferVariables.size());
423         return mBufferVariables[index];
424     }
getTransformFeedbackStrides()425     const std::vector<GLsizei> &getTransformFeedbackStrides() const
426     {
427         return mTransformFeedbackStrides;
428     }
getAtomicCounterBuffers()429     const std::vector<AtomicCounterBuffer> &getAtomicCounterBuffers() const
430     {
431         return mAtomicCounterBuffers;
432     }
getShaderStorageBlocks()433     const std::vector<InterfaceBlock> &getShaderStorageBlocks() const
434     {
435         return mShaderStorageBlocks;
436     }
getBufferVariables()437     const std::vector<BufferVariable> &getBufferVariables() const { return mBufferVariables; }
getUniformByIndex(size_t index)438     const LinkedUniform &getUniformByIndex(size_t index) const
439     {
440         ASSERT(index < static_cast<size_t>(mUniforms.size()));
441         return mUniforms[index];
442     }
getUniformNameByIndex(size_t index)443     const std::string &getUniformNameByIndex(size_t index) const
444     {
445         ASSERT(index < static_cast<size_t>(mUniforms.size()));
446         return mUniformNames[index];
447     }
448 
getUniformIndexFromImageIndex(size_t imageIndex)449     GLuint getUniformIndexFromImageIndex(size_t imageIndex) const
450     {
451         ASSERT(imageIndex < mPod.imageUniformRange.length());
452         return static_cast<GLuint>(imageIndex) + mPod.imageUniformRange.low();
453     }
454 
getUniformIndexFromSamplerIndex(size_t samplerIndex)455     GLuint getUniformIndexFromSamplerIndex(size_t samplerIndex) const
456     {
457         ASSERT(samplerIndex < mPod.samplerUniformRange.length());
458         return static_cast<GLuint>(samplerIndex) + mPod.samplerUniformRange.low();
459     }
460 
461     void saveLinkedStateInfo(const ProgramState &state);
getLinkedOutputVaryings(ShaderType shaderType)462     const std::vector<sh::ShaderVariable> &getLinkedOutputVaryings(ShaderType shaderType) const
463     {
464         return mLinkedOutputVaryings[shaderType];
465     }
getLinkedInputVaryings(ShaderType shaderType)466     const std::vector<sh::ShaderVariable> &getLinkedInputVaryings(ShaderType shaderType) const
467     {
468         return mLinkedInputVaryings[shaderType];
469     }
470 
getLinkedUniforms(ShaderType shaderType)471     const std::vector<sh::ShaderVariable> &getLinkedUniforms(ShaderType shaderType) const
472     {
473         return mLinkedUniforms[shaderType];
474     }
475 
getLinkedUniformBlocks(ShaderType shaderType)476     const std::vector<sh::InterfaceBlock> &getLinkedUniformBlocks(ShaderType shaderType) const
477     {
478         return mLinkedUniformBlocks[shaderType];
479     }
480 
getLinkedShaderVersion(ShaderType shaderType)481     int getLinkedShaderVersion(ShaderType shaderType) const
482     {
483         return mPod.linkedShaderVersions[shaderType];
484     }
485 
isYUVOutput()486     bool isYUVOutput() const { return mPod.hasYUVOutput; }
487 
getGeometryShaderInputPrimitiveType()488     PrimitiveMode getGeometryShaderInputPrimitiveType() const
489     {
490         return mPod.geometryShaderInputPrimitiveType;
491     }
492 
getGeometryShaderOutputPrimitiveType()493     PrimitiveMode getGeometryShaderOutputPrimitiveType() const
494     {
495         return mPod.geometryShaderOutputPrimitiveType;
496     }
497 
getGeometryShaderInvocations()498     int getGeometryShaderInvocations() const { return mPod.geometryShaderInvocations; }
499 
getGeometryShaderMaxVertices()500     int getGeometryShaderMaxVertices() const { return mPod.geometryShaderMaxVertices; }
501 
getTessControlShaderVertices()502     GLint getTessControlShaderVertices() const { return mPod.tessControlShaderVertices; }
getTessGenMode()503     GLenum getTessGenMode() const { return mPod.tessGenMode; }
getTessGenPointMode()504     GLenum getTessGenPointMode() const { return mPod.tessGenPointMode; }
getTessGenSpacing()505     GLenum getTessGenSpacing() const { return mPod.tessGenSpacing; }
getTessGenVertexOrder()506     GLenum getTessGenVertexOrder() const { return mPod.tessGenVertexOrder; }
507 
getNumViews()508     int getNumViews() const { return mPod.numViews; }
usesMultiview()509     bool usesMultiview() const { return mPod.numViews != -1; }
510 
getSpecConstUsageBits()511     rx::SpecConstUsageBits getSpecConstUsageBits() const { return mPod.specConstUsageBits; }
512 
getDrawIDLocation()513     int getDrawIDLocation() const { return mPod.drawIDLocation; }
getBaseVertexLocation()514     int getBaseVertexLocation() const { return mPod.baseVertexLocation; }
getBaseInstanceLocation()515     int getBaseInstanceLocation() const { return mPod.baseInstanceLocation; }
516 
hasDrawIDUniform()517     bool hasDrawIDUniform() const { return getDrawIDLocation() >= 0; }
hasBaseVertexUniform()518     bool hasBaseVertexUniform() const { return getBaseVertexLocation() >= 0; }
hasBaseInstanceUniform()519     bool hasBaseInstanceUniform() const { return getBaseInstanceLocation() >= 0; }
520 
resetCachedValidateSamplersResult()521     void resetCachedValidateSamplersResult() { mCachedValidateSamplersResult.reset(); }
validateSamplers(const Caps & caps)522     bool validateSamplers(const Caps &caps) const
523     {
524         // Use the cache if:
525         // - we aren't using an info log (which gives the full error).
526         // - The sample mapping hasn't changed and we've already validated.
527         if (mCachedValidateSamplersResult.valid())
528         {
529             return mCachedValidateSamplersResult.value();
530         }
531 
532         return validateSamplersImpl(caps);
533     }
534 
getFragmentOutputsTypeMask()535     ComponentTypeMask getFragmentOutputsTypeMask() const { return mPod.drawBufferTypeMask; }
getActiveOutputVariablesMask()536     DrawBufferMask getActiveOutputVariablesMask() const { return mPod.activeOutputVariablesMask; }
getActiveSecondaryOutputVariablesMask()537     DrawBufferMask getActiveSecondaryOutputVariablesMask() const
538     {
539         return mPod.activeSecondaryOutputVariablesMask;
540     }
541 
542     GLuint getInputResourceIndex(const GLchar *name) const;
543     GLuint getOutputResourceIndex(const GLchar *name) const;
544     void getInputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
545     void getOutputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
546     void getUniformResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
547     void getBufferVariableResourceName(GLuint index,
548                                        GLsizei bufSize,
549                                        GLsizei *length,
550                                        GLchar *name) const;
getInputResource(size_t index)551     const ProgramInput &getInputResource(size_t index) const
552     {
553         ASSERT(index < mProgramInputs.size());
554         return mProgramInputs[index];
555     }
556     GLuint getInputResourceMaxNameSize() const;
557     GLuint getOutputResourceMaxNameSize() const;
558     GLuint getInputResourceLocation(const GLchar *name) const;
559     GLuint getOutputResourceLocation(const GLchar *name) const;
560     const std::string getInputResourceName(GLuint index) const;
561     const std::string getOutputResourceName(GLuint index) const;
getOutputResource(size_t index)562     const gl::ProgramOutput &getOutputResource(size_t index) const
563     {
564         ASSERT(index < mOutputVariables.size());
565         return mOutputVariables[index];
566     }
567 
568     GLint getFragDataLocation(const std::string &name) const;
569 
570     // EXT_blend_func_extended
571     GLint getFragDataIndex(const std::string &name) const;
572 
573     GLsizei getTransformFeedbackVaryingMaxLength() const;
574     GLuint getTransformFeedbackVaryingResourceIndex(const GLchar *name) const;
575     const TransformFeedbackVarying &getTransformFeedbackVaryingResource(GLuint index) const;
576     void getTransformFeedbackVarying(GLuint index,
577                                      GLsizei bufSize,
578                                      GLsizei *length,
579                                      GLsizei *size,
580                                      GLenum *type,
581                                      GLchar *name) const;
582 
583     void getActiveAttribute(GLuint index,
584                             GLsizei bufsize,
585                             GLsizei *length,
586                             GLint *size,
587                             GLenum *type,
588                             GLchar *name) const;
589     GLint getActiveAttributeMaxLength() const;
590     GLuint getAttributeLocation(const std::string &name) const;
591 
592     void getActiveUniform(GLuint index,
593                           GLsizei bufsize,
594                           GLsizei *length,
595                           GLint *size,
596                           GLenum *type,
597                           GLchar *name) const;
598     GLint getActiveUniformMaxLength() const;
599     bool isValidUniformLocation(UniformLocation location) const;
600     const LinkedUniform &getUniformByLocation(UniformLocation location) const;
601     const VariableLocation &getUniformLocation(UniformLocation location) const;
602     UniformLocation getUniformLocation(const std::string &name) const;
603     GLuint getUniformIndex(const std::string &name) const;
604 
605     void getActiveUniformBlockName(const Context *context,
606                                    const UniformBlockIndex blockIndex,
607                                    GLsizei bufSize,
608                                    GLsizei *length,
609                                    GLchar *blockName) const;
610     void getActiveShaderStorageBlockName(const GLuint blockIndex,
611                                          GLsizei bufSize,
612                                          GLsizei *length,
613                                          GLchar *blockName) const;
614 
615     GLint getActiveUniformBlockMaxNameLength() const;
616     GLint getActiveShaderStorageBlockMaxNameLength() const;
617 
618     GLuint getUniformBlockIndex(const std::string &name) const;
619     GLuint getShaderStorageBlockIndex(const std::string &name) const;
620 
621     GLuint getUniformIndexFromName(const std::string &name) const;
622     GLuint getUniformIndexFromLocation(UniformLocation location) const;
623     Optional<GLuint> getSamplerIndex(UniformLocation location) const;
624     bool isSamplerUniformIndex(GLuint index) const;
625     GLuint getSamplerIndexFromUniformIndex(GLuint uniformIndex) const;
626     bool isImageUniformIndex(GLuint index) const;
627     GLuint getImageIndexFromUniformIndex(GLuint uniformIndex) const;
628     GLuint getBufferVariableIndexFromName(const std::string &name) const;
629 
630     bool linkUniforms(const Caps &caps,
631                       const ShaderMap<std::vector<sh::ShaderVariable>> &shaderUniforms,
632                       const ProgramAliasedBindings &uniformLocationBindings,
633                       GLuint *combinedImageUniformsCount,
634                       std::vector<UnusedUniform> *unusedUniforms);
635 
636     void copyInputsFromProgram(const ProgramExecutable &executable);
637     void copyUniformBuffersFromProgram(const ProgramExecutable &executable,
638                                        ShaderType shaderType,
639                                        ProgramUniformBlockArray<GLuint> *ppoUniformBlockMap);
640     void copyStorageBuffersFromProgram(const ProgramExecutable &executable, ShaderType shaderType);
641     void clearSamplerBindings();
642     void copySamplerBindingsFromProgram(const ProgramExecutable &executable);
643     void copyImageBindingsFromProgram(const ProgramExecutable &executable);
644     void copyOutputsFromProgram(const ProgramExecutable &executable);
645     void copyUniformsFromProgramMap(const ShaderMap<SharedProgramExecutable> &executables);
646 
647     void setUniform1fv(UniformLocation location, GLsizei count, const GLfloat *v);
648     void setUniform2fv(UniformLocation location, GLsizei count, const GLfloat *v);
649     void setUniform3fv(UniformLocation location, GLsizei count, const GLfloat *v);
650     void setUniform4fv(UniformLocation location, GLsizei count, const GLfloat *v);
651     void setUniform1iv(Context *context, UniformLocation location, GLsizei count, const GLint *v);
652     void setUniform2iv(UniformLocation location, GLsizei count, const GLint *v);
653     void setUniform3iv(UniformLocation location, GLsizei count, const GLint *v);
654     void setUniform4iv(UniformLocation location, GLsizei count, const GLint *v);
655     void setUniform1uiv(UniformLocation location, GLsizei count, const GLuint *v);
656     void setUniform2uiv(UniformLocation location, GLsizei count, const GLuint *v);
657     void setUniform3uiv(UniformLocation location, GLsizei count, const GLuint *v);
658     void setUniform4uiv(UniformLocation location, GLsizei count, const GLuint *v);
659     void setUniformMatrix2fv(UniformLocation location,
660                              GLsizei count,
661                              GLboolean transpose,
662                              const GLfloat *value);
663     void setUniformMatrix3fv(UniformLocation location,
664                              GLsizei count,
665                              GLboolean transpose,
666                              const GLfloat *value);
667     void setUniformMatrix4fv(UniformLocation location,
668                              GLsizei count,
669                              GLboolean transpose,
670                              const GLfloat *value);
671     void setUniformMatrix2x3fv(UniformLocation location,
672                                GLsizei count,
673                                GLboolean transpose,
674                                const GLfloat *value);
675     void setUniformMatrix3x2fv(UniformLocation location,
676                                GLsizei count,
677                                GLboolean transpose,
678                                const GLfloat *value);
679     void setUniformMatrix2x4fv(UniformLocation location,
680                                GLsizei count,
681                                GLboolean transpose,
682                                const GLfloat *value);
683     void setUniformMatrix4x2fv(UniformLocation location,
684                                GLsizei count,
685                                GLboolean transpose,
686                                const GLfloat *value);
687     void setUniformMatrix3x4fv(UniformLocation location,
688                                GLsizei count,
689                                GLboolean transpose,
690                                const GLfloat *value);
691     void setUniformMatrix4x3fv(UniformLocation location,
692                                GLsizei count,
693                                GLboolean transpose,
694                                const GLfloat *value);
695 
696     void getUniformfv(const Context *context, UniformLocation location, GLfloat *params) const;
697     void getUniformiv(const Context *context, UniformLocation location, GLint *params) const;
698     void getUniformuiv(const Context *context, UniformLocation location, GLuint *params) const;
699 
700     void setDrawIDUniform(GLint drawid);
701     void setBaseVertexUniform(GLint baseVertex);
702     void setBaseInstanceUniform(GLuint baseInstance);
703 
getUniformBufferBlocksMappedToBinding(size_t uniformBufferIndex)704     ProgramUniformBlockMask getUniformBufferBlocksMappedToBinding(size_t uniformBufferIndex)
705     {
706         return mUniformBufferBindingToUniformBlocks[uniformBufferIndex];
707     }
708 
getUniformBlockIndexToBufferBindingForCapture()709     const ProgramUniformBlockArray<GLuint> &getUniformBlockIndexToBufferBindingForCapture() const
710     {
711         return mUniformBlockIndexToBufferBinding;
712     }
713 
getPPOProgramExecutables()714     const ShaderMap<SharedProgramExecutable> &getPPOProgramExecutables() const
715     {
716         return mPPOProgramExecutables;
717     }
718 
IsPPO()719     bool IsPPO() const { return mIsPPO; }
720 
721     // Post-link task helpers
getPostLinkSubTasks()722     const std::vector<std::shared_ptr<rx::LinkSubTask>> &getPostLinkSubTasks() const
723     {
724         return mPostLinkSubTasks;
725     }
726 
getPostLinkSubTaskWaitableEvents()727     const std::vector<std::shared_ptr<angle::WaitableEvent>> &getPostLinkSubTaskWaitableEvents()
728         const
729     {
730         return mPostLinkSubTaskWaitableEvents;
731     }
732 
onPostLinkTasksComplete()733     void onPostLinkTasksComplete() const
734     {
735         mPostLinkSubTasks.clear();
736         mPostLinkSubTaskWaitableEvents.clear();
737     }
738 
739     void waitForPostLinkTasks(const Context *context);
740 
741   private:
742     friend class Program;
743     friend class ProgramPipeline;
744     friend class ProgramState;
745     friend class ProgramPipelineState;
746 
747     void reset();
748 
749     void updateActiveImages(const ProgramExecutable &executable);
750 
751     bool linkMergedVaryings(const Caps &caps,
752                             const Limitations &limitations,
753                             const Version &clientVersion,
754                             bool webglCompatibility,
755                             const ProgramMergedVaryings &mergedVaryings,
756                             const LinkingVariables &linkingVariables,
757                             ProgramVaryingPacking *varyingPacking);
758 
759     bool linkValidateTransformFeedback(const Caps &caps,
760                                        const Version &clientVersion,
761                                        const ProgramMergedVaryings &varyings,
762                                        ShaderType stage);
763 
764     void gatherTransformFeedbackVaryings(const ProgramMergedVaryings &varyings, ShaderType stage);
765 
766     void updateTransformFeedbackStrides();
767 
768     bool validateSamplersImpl(const Caps &caps) const;
769 
770     bool linkValidateOutputVariables(const Caps &caps,
771                                      const Version &version,
772                                      GLuint combinedImageUniformsCount,
773                                      GLuint combinedShaderStorageBlocksCount,
774                                      int fragmentShaderVersion,
775                                      const ProgramAliasedBindings &fragmentOutputLocations,
776                                      const ProgramAliasedBindings &fragmentOutputIndices);
777 
778     bool gatherOutputTypes();
779 
780     void linkSamplerAndImageBindings(GLuint *combinedImageUniformsCount);
781     bool linkAtomicCounterBuffers(const Caps &caps);
782 
783     void getResourceName(const std::string name,
784                          GLsizei bufSize,
785                          GLsizei *length,
786                          GLchar *dest) const;
787     bool shouldIgnoreUniform(UniformLocation location) const;
788     GLuint getSamplerUniformBinding(const VariableLocation &uniformLocation) const;
789     GLuint getImageUniformBinding(const VariableLocation &uniformLocation) const;
790 
791     void initInterfaceBlockBindings();
792     void setUniformValuesFromBindingQualifiers();
793 
794     // Both these function update the cached uniform values and return a modified "count"
795     // so that the uniform update doesn't overflow the uniform.
796     template <typename T>
797     GLsizei clampUniformCount(const VariableLocation &locationInfo,
798                               GLsizei count,
799                               int vectorSize,
800                               const T *v);
801     template <size_t cols, size_t rows, typename T>
802     GLsizei clampMatrixUniformCount(UniformLocation location,
803                                     GLsizei count,
804                                     GLboolean transpose,
805                                     const T *v);
806 
807     void updateSamplerUniform(Context *context,
808                               const VariableLocation &locationInfo,
809                               GLsizei clampedCount,
810                               const GLint *v);
811 
812     // Scans the sampler bindings for type conflicts with sampler 'textureUnitIndex'.
813     void setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex);
814 
815     template <typename DestT>
816     void getUniformInternal(const Context *context,
817                             DestT *dataOut,
818                             UniformLocation location,
819                             GLenum nativeType,
820                             int components) const;
821 
822     template <typename UniformT,
823               GLint UniformSize,
824               void (rx::ProgramExecutableImpl::*SetUniformFunc)(GLint, GLsizei, const UniformT *)>
825     void setUniformGeneric(UniformLocation location, GLsizei count, const UniformT *v);
826 
827     template <typename UniformT,
828               GLint MatrixC,
829               GLint MatrixR,
830               void (rx::ProgramExecutableImpl::*
831                         SetUniformMatrixFunc)(GLint, GLsizei, GLboolean, const UniformT *)>
832     void setUniformMatrixGeneric(UniformLocation location,
833                                  GLsizei count,
834                                  GLboolean transpose,
835                                  const UniformT *v);
836 
837     rx::ProgramExecutableImpl *mImplementation;
838 
839     // A reference to the owning object's (Program or ProgramPipeline) info log.  It's kept here for
840     // convenience as numerous functions reference it.
841     InfoLog *mInfoLog;
842 
843     ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
844     struct PODStruct
845     {
846         // 8 bytes each
847         angle::BitSet<MAX_VERTEX_ATTRIBS> activeAttribLocationsMask;
848         ComponentTypeMask attributesTypeMask;
849         // attributesMask is identical to mActiveAttribLocationsMask with built-in attributes
850         // removed.
851         AttributesMask attributesMask;
852         ComponentTypeMask drawBufferTypeMask;
853 
854         // 4 bytes each
855         uint32_t maxActiveAttribLocation;
856         // KHR_blend_equation_advanced supported equation list
857         BlendEquationBitSet advancedBlendEquations;
858 
859         // 1 byte each
860         ShaderBitSet linkedShaderStages;
861         DrawBufferMask activeOutputVariablesMask;
862         DrawBufferMask activeSecondaryOutputVariablesMask;
863         uint8_t hasClipDistance : 1;
864         uint8_t hasDiscard : 1;
865         uint8_t hasYUVOutput : 1;
866         uint8_t enablesPerSampleShading : 1;
867         uint8_t canDrawWith : 1;
868         uint8_t isSeparable : 1;
869         uint8_t pad : 2;
870 
871         // 12 bytes
872         sh::WorkGroupSize computeShaderLocalSize;
873 
874         // 8 bytes each
875         RangeUI defaultUniformRange;
876         RangeUI samplerUniformRange;
877         RangeUI imageUniformRange;
878         RangeUI atomicCounterUniformRange;
879 
880         // 1 byte.  Bitset of which input attachments have been declared
881         DrawBufferMask fragmentInoutIndices;
882 
883         // GL_EXT_geometry_shader.
884         uint8_t pad0;
885         PrimitiveMode geometryShaderInputPrimitiveType;
886         PrimitiveMode geometryShaderOutputPrimitiveType;
887         int32_t geometryShaderInvocations;
888         int32_t geometryShaderMaxVertices;
889         GLenum transformFeedbackBufferMode;
890 
891         // 4 bytes each. GL_OVR_multiview / GL_OVR_multiview2
892         int32_t numViews;
893         // GL_ANGLE_multi_draw
894         int32_t drawIDLocation;
895 
896         // GL_ANGLE_base_vertex_base_instance_shader_builtin
897         int32_t baseVertexLocation;
898         int32_t baseInstanceLocation;
899 
900         // GL_EXT_tessellation_shader
901         int32_t tessControlShaderVertices;
902         GLenum tessGenMode;
903         GLenum tessGenSpacing;
904         GLenum tessGenVertexOrder;
905         GLenum tessGenPointMode;
906 
907         // 4 bytes
908         rx::SpecConstUsageBits specConstUsageBits;
909 
910         // 24 bytes
911         ShaderMap<int> linkedShaderVersions;
912     } mPod;
913     ANGLE_DISABLE_STRUCT_PADDING_WARNINGS
914 
915     // Cached mask of active samplers and sampler types.
916     ActiveTextureMask mActiveSamplersMask;
917     ActiveTextureArray<uint32_t> mActiveSamplerRefCounts;
918     ActiveTextureArray<TextureType> mActiveSamplerTypes;
919     ActiveTextureMask mActiveSamplerYUV;
920     ActiveTextureArray<SamplerFormat> mActiveSamplerFormats;
921     ActiveTextureArray<ShaderBitSet> mActiveSamplerShaderBits;
922 
923     // Cached mask of active images.
924     ActiveTextureMask mActiveImagesMask;
925     ActiveTextureArray<ShaderBitSet> mActiveImageShaderBits;
926 
927     // Names and mapped names of output variables that are arrays include [0] in the end, similarly
928     // to uniforms.
929     std::vector<ProgramOutput> mOutputVariables;
930     std::vector<VariableLocation> mOutputLocations;
931     // EXT_blend_func_extended secondary outputs (ones with index 1)
932     std::vector<VariableLocation> mSecondaryOutputLocations;
933     // Vertex attributes, Fragment input varyings, etc.
934     std::vector<ProgramInput> mProgramInputs;
935     std::vector<TransformFeedbackVarying> mLinkedTransformFeedbackVaryings;
936     // Duplicate of ProgramState::mTransformFeedbackVaryingNames.  This is cached here because the
937     // xfb names may change, relink may fail, yet program pipeline link should be able to function
938     // with the last installed executable.  In truth, program pipeline link should have been able to
939     // hoist transform feedback varyings directly from the executable, among most other things, but
940     // that is currently not done.
941     //
942     // This array is not serialized, it's already done by the program, and will be duplicated during
943     // deserialization.
944     std::vector<std::string> mTransformFeedbackVaryingNames;
945     // The size of the data written to each transform feedback buffer per vertex.
946     std::vector<GLsizei> mTransformFeedbackStrides;
947     // Uniforms are sorted in order:
948     //  1. Non-opaque uniforms
949     //  2. Sampler uniforms
950     //  3. Image uniforms
951     //  4. Atomic counter uniforms
952     //  5. Uniform block uniforms
953     // This makes opaque uniform validation easier, since we don't need a separate list.
954     // For generating the entries and naming them we follow the spec: GLES 3.1 November 2016 section
955     // 7.3.1.1 Naming Active Resources. There's a separate entry for each struct member and each
956     // inner array of an array of arrays. Names and mapped names of uniforms that are arrays include
957     // [0] in the end. This makes implementation of queries simpler.
958     std::vector<LinkedUniform> mUniforms;
959     std::vector<std::string> mUniformNames;
960     // Only used by GL and D3D backend
961     std::vector<std::string> mUniformMappedNames;
962     std::vector<InterfaceBlock> mUniformBlocks;
963     std::vector<VariableLocation> mUniformLocations;
964 
965     std::vector<AtomicCounterBuffer> mAtomicCounterBuffers;
966     std::vector<InterfaceBlock> mShaderStorageBlocks;
967     std::vector<BufferVariable> mBufferVariables;
968 
969     // An array of the samplers that are used by the program
970     std::vector<SamplerBinding> mSamplerBindings;
971     // List of all textures bound to all samplers. Each SamplerBinding will point to a subset in
972     // this vector.
973     std::vector<GLuint> mSamplerBoundTextureUnits;
974 
975     // An array of the images that are used by the program
976     std::vector<ImageBinding> mImageBindings;
977 
978     ShaderMap<std::vector<sh::ShaderVariable>> mLinkedOutputVaryings;
979     ShaderMap<std::vector<sh::ShaderVariable>> mLinkedInputVaryings;
980     ShaderMap<std::vector<sh::ShaderVariable>> mLinkedUniforms;
981     ShaderMap<std::vector<sh::InterfaceBlock>> mLinkedUniformBlocks;
982 
983     // Cached value of base vertex and base instance
984     // need to reset them to zero if using non base vertex or base instance draw calls.
985     GLint mCachedBaseVertex;
986     GLuint mCachedBaseInstance;
987 
988     // GLES allows uniform block indices in the program to be remapped to arbitrary buffer bindings
989     // through calls to glUniformBlockBinding.  (Desktop GL also includes
990     // glShaderStorageBlockBinding, which does not exist in GLES).
991     // This is not a part of the link results, and must be reset on glProgramBinary, so it's not
992     // serialized.
993     // A map from the program uniform block index to the buffer binding it is mapped to.
994     ProgramUniformBlockArray<GLuint> mUniformBlockIndexToBufferBinding;
995     // The reverse of the above map, i.e. from buffer bindings to the uniform blocks that are mapped
996     // to it.  For example, if the program's uniform blocks 1, 3 and 4 are mapped to buffer binding
997     // 2, then mUniformBufferBindingToUniformBlocks[2] will be {1, 3, 4}.
998     //
999     // This is used to efficiently mark uniform blocks dirty when a buffer bound to a binding has
1000     // been modified.
1001     UniformBufferBindingArray<ProgramUniformBlockMask> mUniformBufferBindingToUniformBlocks;
1002 
1003     // PPO only: installed executables from the programs.  Note that these may be different from the
1004     // programs' current executables, because they may have been unsuccessfully relinked.
1005     ShaderMap<SharedProgramExecutable> mPPOProgramExecutables;
1006     // Flag for an easy check for PPO without inspecting mPPOProgramExecutables
1007     bool mIsPPO;
1008 
1009     // Cache for sampler validation
1010     mutable Optional<bool> mCachedValidateSamplersResult;
1011 
1012     // Post-link subtask and wait events
1013     // These tasks are not waited on in |resolveLink|, but instead they are free to
1014     // run until first usage of the program (or relink).  This is used by the backends (currently
1015     // only Vulkan) to run post-link optimization tasks which don't affect the link results.
1016     mutable std::vector<std::shared_ptr<rx::LinkSubTask>> mPostLinkSubTasks;
1017     mutable std::vector<std::shared_ptr<angle::WaitableEvent>> mPostLinkSubTaskWaitableEvents;
1018 };
1019 
1020 void InstallExecutable(const Context *context,
1021                        const SharedProgramExecutable &toInstall,
1022                        SharedProgramExecutable *executable);
1023 void UninstallExecutable(const Context *context, SharedProgramExecutable *executable);
1024 }  // namespace gl
1025 
1026 #endif  // LIBANGLE_PROGRAMEXECUTABLE_H_
1027