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() 128 { 129 mLinkedComputeShaderStages.reset(); 130 mLinkedGraphicsShaderStages.reset(); 131 } getLinkedShaderStages()132 const ShaderBitSet &getLinkedShaderStages() const 133 { 134 return isCompute() ? mLinkedComputeShaderStages : mLinkedGraphicsShaderStages; 135 } setLinkedShaderStages(ShaderType shaderType)136 void setLinkedShaderStages(ShaderType shaderType) 137 { 138 if (shaderType == ShaderType::Compute) 139 { 140 mLinkedComputeShaderStages.set(ShaderType::Compute); 141 } 142 else 143 { 144 mLinkedGraphicsShaderStages.set(shaderType); 145 } 146 147 updateCanDrawWith(); 148 } hasLinkedShaderStage(ShaderType shaderType)149 bool hasLinkedShaderStage(ShaderType shaderType) const 150 { 151 ASSERT(shaderType != ShaderType::InvalidEnum); 152 return (shaderType == ShaderType::Compute) ? mLinkedComputeShaderStages[shaderType] 153 : mLinkedGraphicsShaderStages[shaderType]; 154 } getLinkedShaderStageCount()155 size_t getLinkedShaderStageCount() const 156 { 157 return isCompute() ? mLinkedComputeShaderStages.count() 158 : mLinkedGraphicsShaderStages.count(); 159 } hasLinkedTessellationShader()160 bool hasLinkedTessellationShader() const 161 { 162 return mLinkedGraphicsShaderStages[ShaderType::TessControl] || 163 mLinkedGraphicsShaderStages[ShaderType::TessEvaluation]; 164 } 165 166 ShaderType getTransformFeedbackStage() const; 167 168 ShaderType getLinkedTransformFeedbackStage() const; 169 170 // A PPO can have both graphics and compute programs attached, so 171 // we don't know if the PPO is a 'graphics' or 'compute' PPO until the 172 // actual draw/dispatch call. isCompute()173 bool isCompute() const { return mIsCompute; } setIsCompute(bool isCompute)174 void setIsCompute(bool isCompute) { mIsCompute = isCompute; } 175 getActiveAttribLocationsMask()176 const AttributesMask &getActiveAttribLocationsMask() const 177 { 178 return mActiveAttribLocationsMask; 179 } 180 bool isAttribLocationActive(size_t attribLocation) const; getNonBuiltinAttribLocationsMask()181 const AttributesMask &getNonBuiltinAttribLocationsMask() const { return mAttributesMask; } getMaxActiveAttribLocation()182 unsigned int getMaxActiveAttribLocation() const { return mMaxActiveAttribLocation; } getAttributesTypeMask()183 const ComponentTypeMask &getAttributesTypeMask() const { return mAttributesTypeMask; } 184 AttributesMask getAttributesMask() const; 185 getActiveSamplersMask()186 const ActiveTextureMask &getActiveSamplersMask() const { return mActiveSamplersMask; } setActiveTextureMask(ActiveTextureMask mask)187 void setActiveTextureMask(ActiveTextureMask mask) { mActiveSamplersMask = mask; } getSamplerFormatForTextureUnitIndex(size_t textureUnitIndex)188 SamplerFormat getSamplerFormatForTextureUnitIndex(size_t textureUnitIndex) const 189 { 190 return mActiveSamplerFormats[textureUnitIndex]; 191 } getSamplerShaderBitsForTextureUnitIndex(size_t textureUnitIndex)192 const ShaderBitSet getSamplerShaderBitsForTextureUnitIndex(size_t textureUnitIndex) const 193 { 194 return mActiveSamplerShaderBits[textureUnitIndex]; 195 } getActiveImagesMask()196 const ActiveTextureMask &getActiveImagesMask() const { return mActiveImagesMask; } setActiveImagesMask(ActiveTextureMask mask)197 void setActiveImagesMask(ActiveTextureMask mask) { mActiveImagesMask = mask; } getActiveImageShaderBits()198 const ActiveTextureArray<ShaderBitSet> &getActiveImageShaderBits() const 199 { 200 return mActiveImageShaderBits; 201 } 202 getActiveYUVSamplers()203 const ActiveTextureMask &getActiveYUVSamplers() const { return mActiveSamplerYUV; } 204 getActiveSamplerTypes()205 const ActiveTextureArray<TextureType> &getActiveSamplerTypes() const 206 { 207 return mActiveSamplerTypes; 208 } 209 210 void updateActiveSamplers(const ProgramState &programState); 211 212 bool hasDefaultUniforms() const; 213 bool hasTextures() const; 214 bool hasUniformBuffers() const; 215 bool hasStorageBuffers() const; 216 bool hasGraphicsStorageBuffers() const; 217 bool hasComputeStorageBuffers() const; 218 bool hasAtomicCounterBuffers() const; 219 bool hasImages() const; 220 bool hasGraphicsImages() const; 221 bool hasComputeImages() const; hasTransformFeedbackOutput()222 bool hasTransformFeedbackOutput() const 223 { 224 return !getLinkedTransformFeedbackVaryings().empty(); 225 } 226 bool usesFramebufferFetch() const; 227 228 // Count the number of uniform and storage buffer declarations, counting arrays as one. getTransformFeedbackBufferCount()229 size_t getTransformFeedbackBufferCount() const { return mTransformFeedbackStrides.size(); } 230 231 void updateCanDrawWith(); hasVertexAndFragmentShader()232 bool hasVertexAndFragmentShader() const { return mCanDrawWith; } 233 getProgramInputs()234 const std::vector<sh::ShaderVariable> &getProgramInputs() const { return mProgramInputs; } getOutputVariables()235 const std::vector<sh::ShaderVariable> &getOutputVariables() const { return mOutputVariables; } getOutputLocations()236 const std::vector<VariableLocation> &getOutputLocations() const { return mOutputLocations; } getSecondaryOutputLocations()237 const std::vector<VariableLocation> &getSecondaryOutputLocations() const 238 { 239 return mSecondaryOutputLocations; 240 } getUniforms()241 const std::vector<LinkedUniform> &getUniforms() const { return mUniforms; } getUniformBlocks()242 const std::vector<InterfaceBlock> &getUniformBlocks() const { return mUniformBlocks; } getActiveUniformBlockBindings()243 const UniformBlockBindingMask &getActiveUniformBlockBindings() const 244 { 245 return mActiveUniformBlockBindings; 246 } getSamplerBindings()247 const std::vector<SamplerBinding> &getSamplerBindings() const { return mSamplerBindings; } getImageBindings()248 const std::vector<ImageBinding> &getImageBindings() const 249 { 250 return isCompute() ? mComputeImageBindings : mGraphicsImageBindings; 251 } getImageBindings()252 std::vector<ImageBinding> *getImageBindings() 253 { 254 return isCompute() ? &mComputeImageBindings : &mGraphicsImageBindings; 255 } getDefaultUniformRange()256 const RangeUI &getDefaultUniformRange() const { return mDefaultUniformRange; } getSamplerUniformRange()257 const RangeUI &getSamplerUniformRange() const { return mSamplerUniformRange; } getImageUniformRange()258 const RangeUI &getImageUniformRange() const { return mImageUniformRange; } getFragmentInoutRange()259 const RangeUI &getFragmentInoutRange() const { return mFragmentInoutRange; } getLinkedTransformFeedbackVaryings()260 const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const 261 { 262 return mLinkedTransformFeedbackVaryings; 263 } getTransformFeedbackBufferMode()264 GLint getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; } getUniformBlockBinding(GLuint uniformBlockIndex)265 GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const 266 { 267 ASSERT(uniformBlockIndex < mUniformBlocks.size()); 268 return mUniformBlocks[uniformBlockIndex].binding; 269 } getShaderStorageBlockBinding(GLuint blockIndex)270 GLuint getShaderStorageBlockBinding(GLuint blockIndex) const 271 { 272 ASSERT((isCompute() && (blockIndex < mComputeShaderStorageBlocks.size())) || 273 (!isCompute() && (blockIndex < mGraphicsShaderStorageBlocks.size()))); 274 return isCompute() ? mComputeShaderStorageBlocks[blockIndex].binding 275 : mGraphicsShaderStorageBlocks[blockIndex].binding; 276 } getTransformFeedbackStrides()277 const std::vector<GLsizei> &getTransformFeedbackStrides() const 278 { 279 return mTransformFeedbackStrides; 280 } getAtomicCounterBuffers()281 const std::vector<AtomicCounterBuffer> &getAtomicCounterBuffers() const 282 { 283 return mAtomicCounterBuffers; 284 } getShaderStorageBlocks()285 const std::vector<InterfaceBlock> &getShaderStorageBlocks() const 286 { 287 return isCompute() ? mComputeShaderStorageBlocks : mGraphicsShaderStorageBlocks; 288 } getUniformByIndex(GLuint index)289 const LinkedUniform &getUniformByIndex(GLuint index) const 290 { 291 ASSERT(index < static_cast<size_t>(mUniforms.size())); 292 return mUniforms[index]; 293 } 294 getActiveUniformBlockCount()295 ANGLE_INLINE GLuint getActiveUniformBlockCount() const 296 { 297 return static_cast<GLuint>(mUniformBlocks.size()); 298 } 299 getActiveAtomicCounterBufferCount()300 ANGLE_INLINE GLuint getActiveAtomicCounterBufferCount() const 301 { 302 return static_cast<GLuint>(mAtomicCounterBuffers.size()); 303 } 304 getActiveShaderStorageBlockCount()305 ANGLE_INLINE GLuint getActiveShaderStorageBlockCount() const 306 { 307 size_t shaderStorageBlocksSize = 308 isCompute() ? mComputeShaderStorageBlocks.size() : mGraphicsShaderStorageBlocks.size(); 309 return static_cast<GLuint>(shaderStorageBlocksSize); 310 } 311 312 GLuint getUniformIndexFromImageIndex(GLuint imageIndex) const; 313 314 void saveLinkedStateInfo(const ProgramState &state); getLinkedOutputVaryings(ShaderType shaderType)315 const std::vector<sh::ShaderVariable> &getLinkedOutputVaryings(ShaderType shaderType) const 316 { 317 return mLinkedOutputVaryings[shaderType]; 318 } getLinkedInputVaryings(ShaderType shaderType)319 const std::vector<sh::ShaderVariable> &getLinkedInputVaryings(ShaderType shaderType) const 320 { 321 return mLinkedInputVaryings[shaderType]; 322 } 323 getLinkedShaderVersion(ShaderType shaderType)324 int getLinkedShaderVersion(ShaderType shaderType) const 325 { 326 return mLinkedShaderVersions[shaderType]; 327 } 328 329 bool isYUVOutput() const; 330 getGeometryShaderInputPrimitiveType()331 PrimitiveMode getGeometryShaderInputPrimitiveType() const 332 { 333 return mGeometryShaderInputPrimitiveType; 334 } 335 getGeometryShaderOutputPrimitiveType()336 PrimitiveMode getGeometryShaderOutputPrimitiveType() const 337 { 338 return mGeometryShaderOutputPrimitiveType; 339 } 340 getGeometryShaderInvocations()341 int getGeometryShaderInvocations() const { return mGeometryShaderInvocations; } 342 getGeometryShaderMaxVertices()343 int getGeometryShaderMaxVertices() const { return mGeometryShaderMaxVertices; } 344 getTessGenMode()345 GLenum getTessGenMode() const { return mTessGenMode; } 346 resetCachedValidateSamplersResult()347 void resetCachedValidateSamplersResult() { mCachedValidateSamplersResult.reset(); } validateSamplers(InfoLog * infoLog,const Caps & caps)348 bool validateSamplers(InfoLog *infoLog, const Caps &caps) const 349 { 350 // Use the cache if: 351 // - we aren't using an infolog (which gives the full error). 352 // - The sample mapping hasn't changed and we've already validated. 353 if (infoLog == nullptr && mCachedValidateSamplersResult.valid()) 354 { 355 return mCachedValidateSamplersResult.value(); 356 } 357 358 return validateSamplersImpl(infoLog, caps); 359 } 360 361 private: 362 // TODO(timvp): http://anglebug.com/3570: Investigate removing these friend 363 // class declarations and accessing the necessary members with getters/setters. 364 friend class Program; 365 friend class ProgramPipeline; 366 friend class ProgramState; 367 368 void updateActiveImages(const ProgramExecutable &executable); 369 370 // Scans the sampler bindings for type conflicts with sampler 'textureUnitIndex'. 371 void setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex, 372 std::vector<SamplerBinding> &samplerBindings); 373 374 bool linkMergedVaryings(const Context *context, 375 const HasAttachedShaders &programOrPipeline, 376 const ProgramMergedVaryings &mergedVaryings, 377 const std::vector<std::string> &transformFeedbackVaryingNames, 378 bool isSeparable, 379 ProgramVaryingPacking *varyingPacking); 380 381 bool linkValidateTransformFeedback( 382 const Context *context, 383 const ProgramMergedVaryings &varyings, 384 ShaderType stage, 385 const std::vector<std::string> &transformFeedbackVaryingNames); 386 387 void gatherTransformFeedbackVaryings( 388 const ProgramMergedVaryings &varyings, 389 ShaderType stage, 390 const std::vector<std::string> &transformFeedbackVaryingNames); 391 392 void updateTransformFeedbackStrides(); 393 394 bool validateSamplersImpl(InfoLog *infoLog, const Caps &caps) const; 395 396 InfoLog mInfoLog; 397 398 ShaderBitSet mLinkedGraphicsShaderStages; 399 ShaderBitSet mLinkedComputeShaderStages; 400 401 angle::BitSet<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask; 402 unsigned int mMaxActiveAttribLocation; 403 ComponentTypeMask mAttributesTypeMask; 404 // mAttributesMask is identical to mActiveAttribLocationsMask with built-in attributes removed. 405 AttributesMask mAttributesMask; 406 407 // Cached mask of active samplers and sampler types. 408 ActiveTextureMask mActiveSamplersMask; 409 ActiveTextureArray<uint32_t> mActiveSamplerRefCounts; 410 ActiveTextureArray<TextureType> mActiveSamplerTypes; 411 ActiveTextureMask mActiveSamplerYUV; 412 ActiveTextureArray<SamplerFormat> mActiveSamplerFormats; 413 ActiveTextureArray<ShaderBitSet> mActiveSamplerShaderBits; 414 415 // Cached mask of active images. 416 ActiveTextureMask mActiveImagesMask; 417 ActiveTextureArray<ShaderBitSet> mActiveImageShaderBits; 418 419 bool mCanDrawWith; 420 421 // Names and mapped names of output variables that are arrays include [0] in the end, similarly 422 // to uniforms. 423 std::vector<sh::ShaderVariable> mOutputVariables; 424 std::vector<VariableLocation> mOutputLocations; 425 // EXT_blend_func_extended secondary outputs (ones with index 1) 426 std::vector<VariableLocation> mSecondaryOutputLocations; 427 bool mYUVOutput; 428 // Vertex attributes, Fragment input varyings, etc. 429 std::vector<sh::ShaderVariable> mProgramInputs; 430 std::vector<TransformFeedbackVarying> mLinkedTransformFeedbackVaryings; 431 // The size of the data written to each transform feedback buffer per vertex. 432 std::vector<GLsizei> mTransformFeedbackStrides; 433 GLenum mTransformFeedbackBufferMode; 434 // Uniforms are sorted in order: 435 // 1. Non-opaque uniforms 436 // 2. Sampler uniforms 437 // 3. Image uniforms 438 // 4. Atomic counter uniforms 439 // 5. Subpass Input uniforms (Only for Vulkan) 440 // 6. Uniform block uniforms 441 // This makes opaque uniform validation easier, since we don't need a separate list. 442 // For generating the entries and naming them we follow the spec: GLES 3.1 November 2016 section 443 // 7.3.1.1 Naming Active Resources. There's a separate entry for each struct member and each 444 // inner array of an array of arrays. Names and mapped names of uniforms that are arrays include 445 // [0] in the end. This makes implementation of queries simpler. 446 std::vector<LinkedUniform> mUniforms; 447 RangeUI mDefaultUniformRange; 448 RangeUI mSamplerUniformRange; 449 std::vector<InterfaceBlock> mUniformBlocks; 450 451 // For faster iteration on the blocks currently being bound. 452 UniformBlockBindingMask mActiveUniformBlockBindings; 453 454 std::vector<AtomicCounterBuffer> mAtomicCounterBuffers; 455 RangeUI mImageUniformRange; 456 std::vector<InterfaceBlock> mComputeShaderStorageBlocks; 457 std::vector<InterfaceBlock> mGraphicsShaderStorageBlocks; 458 RangeUI mFragmentInoutRange; 459 460 // An array of the samplers that are used by the program 461 std::vector<SamplerBinding> mSamplerBindings; 462 463 // An array of the images that are used by the program 464 std::vector<ImageBinding> mComputeImageBindings; 465 std::vector<ImageBinding> mGraphicsImageBindings; 466 467 // TODO: http://anglebug.com/3570: Remove mPipelineHas*UniformBuffers once PPO's have valid data 468 // in mUniformBlocks 469 bool mPipelineHasGraphicsUniformBuffers; 470 bool mPipelineHasComputeUniformBuffers; 471 bool mPipelineHasGraphicsStorageBuffers; 472 bool mPipelineHasComputeStorageBuffers; 473 bool mPipelineHasGraphicsAtomicCounterBuffers; 474 bool mPipelineHasComputeAtomicCounterBuffers; 475 bool mPipelineHasGraphicsDefaultUniforms; 476 bool mPipelineHasComputeDefaultUniforms; 477 bool mPipelineHasGraphicsTextures; 478 bool mPipelineHasComputeTextures; 479 bool mPipelineHasGraphicsImages; 480 bool mPipelineHasComputeImages; 481 482 bool mIsCompute; 483 484 ShaderMap<std::vector<sh::ShaderVariable>> mLinkedOutputVaryings; 485 ShaderMap<std::vector<sh::ShaderVariable>> mLinkedInputVaryings; 486 ShaderMap<int> mLinkedShaderVersions; 487 488 // GL_EXT_geometry_shader. 489 PrimitiveMode mGeometryShaderInputPrimitiveType; 490 PrimitiveMode mGeometryShaderOutputPrimitiveType; 491 int mGeometryShaderInvocations; 492 int mGeometryShaderMaxVertices; 493 494 // GL_EXT_tessellation_shader 495 int mTessControlShaderVertices; 496 GLenum mTessGenMode; 497 GLenum mTessGenSpacing; 498 GLenum mTessGenVertexOrder; 499 GLenum mTessGenPointMode; 500 501 // Cache for sampler validation 502 mutable Optional<bool> mCachedValidateSamplersResult; 503 }; 504 } // namespace gl 505 506 #endif // LIBANGLE_PROGRAMEXECUTABLE_H_ 507