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