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