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 SamplerFormat formatIn, 29 size_t elementCount, 30 bool unreferenced); 31 SamplerBinding(const SamplerBinding &other); 32 ~SamplerBinding(); 33 34 // Necessary for retrieving active textures from the GL state. 35 TextureType textureType; 36 37 SamplerFormat format; 38 39 // List of all textures bound to this sampler, of type textureType. 40 std::vector<GLuint> boundTextureUnits; 41 42 // A note if this sampler is an unreferenced uniform. 43 bool unreferenced; 44 }; 45 46 struct ImageBinding 47 { 48 ImageBinding(size_t count); 49 ImageBinding(GLuint imageUnit, size_t count, bool unreferenced); 50 ImageBinding(const ImageBinding &other); 51 ~ImageBinding(); 52 53 std::vector<GLuint> boundImageUnits; 54 55 // A note if this image unit is an unreferenced uniform. 56 bool unreferenced; 57 }; 58 59 // A varying with transform feedback enabled. If it's an array, either the whole array or one of its 60 // elements specified by 'arrayIndex' can set to be enabled. 61 struct TransformFeedbackVarying : public sh::ShaderVariable 62 { TransformFeedbackVaryingTransformFeedbackVarying63 TransformFeedbackVarying(const sh::ShaderVariable &varyingIn, GLuint arrayIndexIn) 64 : sh::ShaderVariable(varyingIn), arrayIndex(arrayIndexIn) 65 { 66 ASSERT(!isArrayOfArrays()); 67 } 68 TransformFeedbackVaryingTransformFeedbackVarying69 TransformFeedbackVarying(const sh::ShaderVariable &field, const sh::ShaderVariable &parent) 70 : arrayIndex(GL_INVALID_INDEX) 71 { 72 sh::ShaderVariable *thisVar = this; 73 *thisVar = field; 74 interpolation = parent.interpolation; 75 isInvariant = parent.isInvariant; 76 name = parent.name + "." + name; 77 mappedName = parent.mappedName + "." + mappedName; 78 } 79 nameWithArrayIndexTransformFeedbackVarying80 std::string nameWithArrayIndex() const 81 { 82 std::stringstream fullNameStr; 83 fullNameStr << name; 84 if (arrayIndex != GL_INVALID_INDEX) 85 { 86 fullNameStr << "[" << arrayIndex << "]"; 87 } 88 return fullNameStr.str(); 89 } sizeTransformFeedbackVarying90 GLsizei size() const 91 { 92 return (isArray() && arrayIndex == GL_INVALID_INDEX ? getOutermostArraySize() : 1); 93 } 94 95 GLuint arrayIndex; 96 }; 97 98 class ProgramState; 99 class ProgramPipelineState; 100 101 class ProgramExecutable 102 { 103 public: 104 ProgramExecutable(); 105 ProgramExecutable(const ProgramExecutable &other); 106 virtual ~ProgramExecutable(); 107 108 void reset(); 109 110 void save(gl::BinaryOutputStream *stream) const; 111 void load(gl::BinaryInputStream *stream); 112 113 const ProgramState *getProgramState(ShaderType shaderType) const; 114 115 int getInfoLogLength() const; getInfoLog()116 InfoLog &getInfoLog() { return mInfoLog; } 117 void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const; 118 std::string getInfoLogString() const; resetInfoLog()119 void resetInfoLog() { mInfoLog.reset(); } 120 resetLinkedShaderStages()121 void resetLinkedShaderStages() 122 { 123 mLinkedComputeShaderStages.reset(); 124 mLinkedGraphicsShaderStages.reset(); 125 } getLinkedShaderStages()126 const ShaderBitSet &getLinkedShaderStages() const 127 { 128 return isCompute() ? mLinkedComputeShaderStages : mLinkedGraphicsShaderStages; 129 } setLinkedShaderStages(ShaderType shaderType)130 void setLinkedShaderStages(ShaderType shaderType) 131 { 132 if (shaderType == ShaderType::Compute) 133 { 134 mLinkedComputeShaderStages.set(ShaderType::Compute); 135 } 136 else 137 { 138 mLinkedGraphicsShaderStages.set(shaderType); 139 } 140 141 updateCanDrawWith(); 142 } hasLinkedShaderStage(ShaderType shaderType)143 bool hasLinkedShaderStage(ShaderType shaderType) const 144 { 145 ASSERT(shaderType != ShaderType::InvalidEnum); 146 return (shaderType == ShaderType::Compute) ? mLinkedComputeShaderStages[shaderType] 147 : mLinkedGraphicsShaderStages[shaderType]; 148 } getLinkedShaderStageCount()149 size_t getLinkedShaderStageCount() const 150 { 151 return isCompute() ? mLinkedComputeShaderStages.count() 152 : mLinkedGraphicsShaderStages.count(); 153 } 154 bool isCompute() const; 155 getActiveAttribLocationsMask()156 const AttributesMask &getActiveAttribLocationsMask() const 157 { 158 return mActiveAttribLocationsMask; 159 } 160 bool isAttribLocationActive(size_t attribLocation) const; getNonBuiltinAttribLocationsMask()161 const AttributesMask &getNonBuiltinAttribLocationsMask() const { return mAttributesMask; } getMaxActiveAttribLocation()162 unsigned int getMaxActiveAttribLocation() const { return mMaxActiveAttribLocation; } getAttributesTypeMask()163 const ComponentTypeMask &getAttributesTypeMask() const { return mAttributesTypeMask; } 164 AttributesMask getAttributesMask() const; 165 getActiveSamplersMask()166 const ActiveTextureMask &getActiveSamplersMask() const { return mActiveSamplersMask; } getSamplerFormatForTextureUnitIndex(size_t textureUnitIndex)167 SamplerFormat getSamplerFormatForTextureUnitIndex(size_t textureUnitIndex) const 168 { 169 return mActiveSamplerFormats[textureUnitIndex]; 170 } getSamplerShaderBitsForTextureUnitIndex(size_t textureUnitIndex)171 const ShaderBitSet getSamplerShaderBitsForTextureUnitIndex(size_t textureUnitIndex) const 172 { 173 return mActiveSamplerShaderBits[textureUnitIndex]; 174 } getActiveImagesMask()175 const ActiveTextureMask &getActiveImagesMask() const { return mActiveImagesMask; } getActiveImageShaderBits()176 const ActiveTextureArray<ShaderBitSet> &getActiveImageShaderBits() const 177 { 178 return mActiveImageShaderBits; 179 } 180 getActiveSamplerTypes()181 const ActiveTextureArray<TextureType> &getActiveSamplerTypes() const 182 { 183 return mActiveSamplerTypes; 184 } 185 186 bool hasDefaultUniforms() const; 187 bool hasTextures() const; 188 bool hasUniformBuffers() const; 189 bool hasStorageBuffers() const; 190 bool hasAtomicCounterBuffers() const; 191 bool hasImages() const; hasTransformFeedbackOutput()192 bool hasTransformFeedbackOutput() const 193 { 194 return !getLinkedTransformFeedbackVaryings().empty(); 195 } 196 197 // Count the number of uniform and storage buffer declarations, counting arrays as one. getTransformFeedbackBufferCount()198 size_t getTransformFeedbackBufferCount() const { return mTransformFeedbackStrides.size(); } 199 200 bool linkValidateGlobalNames(InfoLog &infoLog) const; 201 202 // TODO: http://anglebug.com/4520: Remove mProgramState/mProgramPipelineState setProgramState(ProgramState * state)203 void setProgramState(ProgramState *state) 204 { 205 ASSERT(!mProgramState && !mProgramPipelineState); 206 mProgramState = state; 207 } setProgramPipelineState(ProgramPipelineState * state)208 void setProgramPipelineState(ProgramPipelineState *state) 209 { 210 ASSERT(!mProgramState && !mProgramPipelineState); 211 mProgramPipelineState = state; 212 } 213 214 void setIsCompute(bool isComputeIn); 215 216 void updateCanDrawWith(); hasVertexAndFragmentShader()217 bool hasVertexAndFragmentShader() const { return mCanDrawWith; } 218 getProgramInputs()219 const std::vector<sh::ShaderVariable> &getProgramInputs() const { return mProgramInputs; } getOutputVariables()220 const std::vector<sh::ShaderVariable> &getOutputVariables() const { return mOutputVariables; } getOutputLocations()221 const std::vector<VariableLocation> &getOutputLocations() const { return mOutputLocations; } getUniforms()222 const std::vector<LinkedUniform> &getUniforms() const { return mUniforms; } getUniformBlocks()223 const std::vector<InterfaceBlock> &getUniformBlocks() const { return mUniformBlocks; } getSamplerUniformRange()224 const RangeUI &getSamplerUniformRange() const { return mSamplerUniformRange; } getImageUniformRange()225 const RangeUI &getImageUniformRange() const { return mImageUniformRange; } getLinkedTransformFeedbackVaryings()226 const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const 227 { 228 return mLinkedTransformFeedbackVaryings; 229 } getTransformFeedbackBufferMode()230 GLint getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; } getUniformBlockBinding(GLuint uniformBlockIndex)231 GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const 232 { 233 ASSERT(uniformBlockIndex < mUniformBlocks.size()); 234 return mUniformBlocks[uniformBlockIndex].binding; 235 } getShaderStorageBlockBinding(GLuint blockIndex)236 GLuint getShaderStorageBlockBinding(GLuint blockIndex) const 237 { 238 ASSERT(blockIndex < mShaderStorageBlocks.size()); 239 return mShaderStorageBlocks[blockIndex].binding; 240 } getTransformFeedbackStrides()241 const std::vector<GLsizei> &getTransformFeedbackStrides() const 242 { 243 return mTransformFeedbackStrides; 244 } getAtomicCounterBuffers()245 const std::vector<AtomicCounterBuffer> &getAtomicCounterBuffers() const 246 { 247 return mAtomicCounterBuffers; 248 } getShaderStorageBlocks()249 const std::vector<InterfaceBlock> &getShaderStorageBlocks() const 250 { 251 return mShaderStorageBlocks; 252 } getUniformByIndex(GLuint index)253 const LinkedUniform &getUniformByIndex(GLuint index) const 254 { 255 ASSERT(index < static_cast<size_t>(mUniforms.size())); 256 return mUniforms[index]; 257 } 258 getActiveUniformBlockCount()259 ANGLE_INLINE GLuint getActiveUniformBlockCount() const 260 { 261 return static_cast<GLuint>(mUniformBlocks.size()); 262 } 263 getActiveAtomicCounterBufferCount()264 ANGLE_INLINE GLuint getActiveAtomicCounterBufferCount() const 265 { 266 return static_cast<GLuint>(mAtomicCounterBuffers.size()); 267 } 268 getActiveShaderStorageBlockCount()269 ANGLE_INLINE GLuint getActiveShaderStorageBlockCount() const 270 { 271 return static_cast<GLuint>(mShaderStorageBlocks.size()); 272 } 273 getResources()274 gl::ProgramLinkedResources &getResources() const 275 { 276 ASSERT(mResources); 277 return *mResources; 278 } 279 280 void saveLinkedStateInfo(); getLinkedOutputVaryings(ShaderType shaderType)281 std::vector<sh::ShaderVariable> getLinkedOutputVaryings(ShaderType shaderType) 282 { 283 return mLinkedOutputVaryings[shaderType]; 284 } getLinkedInputVaryings(ShaderType shaderType)285 std::vector<sh::ShaderVariable> getLinkedInputVaryings(ShaderType shaderType) 286 { 287 return mLinkedInputVaryings[shaderType]; 288 } getLinkedShaderVersion(ShaderType shaderType)289 int getLinkedShaderVersion(ShaderType shaderType) { return mLinkedShaderVersions[shaderType]; } 290 291 private: 292 // TODO(timvp): http://anglebug.com/3570: Investigate removing these friend 293 // class declarations and accessing the necessary members with getters/setters. 294 friend class Program; 295 friend class ProgramPipeline; 296 friend class ProgramState; 297 298 void updateActiveSamplers(const ProgramState &programState); 299 void updateActiveImages(std::vector<ImageBinding> &imageBindings); 300 301 // Scans the sampler bindings for type conflicts with sampler 'textureUnitIndex'. 302 void setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex, 303 std::vector<SamplerBinding> &samplerBindings); 304 305 // TODO: http://anglebug.com/4520: Remove mProgramState/mProgramPipelineState 306 ProgramState *mProgramState; 307 ProgramPipelineState *mProgramPipelineState; 308 309 InfoLog mInfoLog; 310 311 ShaderBitSet mLinkedGraphicsShaderStages; 312 ShaderBitSet mLinkedComputeShaderStages; 313 314 angle::BitSet<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask; 315 unsigned int mMaxActiveAttribLocation; 316 ComponentTypeMask mAttributesTypeMask; 317 // mAttributesMask is identical to mActiveAttribLocationsMask with built-in attributes removed. 318 AttributesMask mAttributesMask; 319 320 // Cached mask of active samplers and sampler types. 321 ActiveTextureMask mActiveSamplersMask; 322 ActiveTextureArray<uint32_t> mActiveSamplerRefCounts; 323 ActiveTextureArray<TextureType> mActiveSamplerTypes; 324 ActiveTextureArray<SamplerFormat> mActiveSamplerFormats; 325 ActiveTextureArray<ShaderBitSet> mActiveSamplerShaderBits; 326 327 // Cached mask of active images. 328 ActiveTextureMask mActiveImagesMask; 329 ActiveTextureArray<ShaderBitSet> mActiveImageShaderBits; 330 331 bool mCanDrawWith; 332 333 // Names and mapped names of output variables that are arrays include [0] in the end, similarly 334 // to uniforms. 335 std::vector<sh::ShaderVariable> mOutputVariables; 336 std::vector<VariableLocation> mOutputLocations; 337 // Vertex attributes, Fragment input varyings, etc. 338 std::vector<sh::ShaderVariable> mProgramInputs; 339 std::vector<TransformFeedbackVarying> mLinkedTransformFeedbackVaryings; 340 // The size of the data written to each transform feedback buffer per vertex. 341 std::vector<GLsizei> mTransformFeedbackStrides; 342 GLenum mTransformFeedbackBufferMode; 343 // Uniforms are sorted in order: 344 // 1. Non-opaque uniforms 345 // 2. Sampler uniforms 346 // 3. Image uniforms 347 // 4. Atomic counter uniforms 348 // 5. Uniform block uniforms 349 // This makes opaque uniform validation easier, since we don't need a separate list. 350 // For generating the entries and naming them we follow the spec: GLES 3.1 November 2016 section 351 // 7.3.1.1 Naming Active Resources. There's a separate entry for each struct member and each 352 // inner array of an array of arrays. Names and mapped names of uniforms that are arrays include 353 // [0] in the end. This makes implementation of queries simpler. 354 std::vector<LinkedUniform> mUniforms; 355 RangeUI mSamplerUniformRange; 356 std::vector<InterfaceBlock> mUniformBlocks; 357 std::vector<AtomicCounterBuffer> mAtomicCounterBuffers; 358 RangeUI mImageUniformRange; 359 std::vector<InterfaceBlock> mShaderStorageBlocks; 360 361 // TODO: http://anglebug.com/3570: Remove mPipelineHas*UniformBuffers once PPO's have valid data 362 // in mUniformBlocks 363 bool mPipelineHasGraphicsUniformBuffers; 364 bool mPipelineHasComputeUniformBuffers; 365 bool mPipelineHasGraphicsStorageBuffers; 366 bool mPipelineHasComputeStorageBuffers; 367 bool mPipelineHasGraphicsAtomicCounterBuffers; 368 bool mPipelineHasComputeAtomicCounterBuffers; 369 370 ShaderMap<std::vector<sh::ShaderVariable>> mLinkedOutputVaryings; 371 ShaderMap<std::vector<sh::ShaderVariable>> mLinkedInputVaryings; 372 ShaderMap<int> mLinkedShaderVersions; 373 // TODO: http://anglebug.com/4514: Remove 374 std::unique_ptr<gl::ProgramLinkedResources> mResources; 375 }; 376 377 } // namespace gl 378 379 #endif // LIBANGLE_PROGRAMEXECUTABLE_H_ 380