diff options
Diffstat (limited to 'src/3rdparty/angle/src/libANGLE/ProgramLinkedResources.cpp')
-rw-r--r-- | src/3rdparty/angle/src/libANGLE/ProgramLinkedResources.cpp | 1040 |
1 files changed, 0 insertions, 1040 deletions
diff --git a/src/3rdparty/angle/src/libANGLE/ProgramLinkedResources.cpp b/src/3rdparty/angle/src/libANGLE/ProgramLinkedResources.cpp deleted file mode 100644 index a33f751525..0000000000 --- a/src/3rdparty/angle/src/libANGLE/ProgramLinkedResources.cpp +++ /dev/null @@ -1,1040 +0,0 @@ -// -// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// UniformLinker.cpp: implements link-time checks for default block uniforms, and generates uniform -// locations. Populates data structures related to uniforms so that they can be stored in program -// state. - -#include "libANGLE/ProgramLinkedResources.h" - -#include "common/string_utils.h" -#include "common/utilities.h" -#include "libANGLE/Caps.h" -#include "libANGLE/Context.h" -#include "libANGLE/Shader.h" -#include "libANGLE/features.h" - -namespace gl -{ - -namespace -{ - -LinkedUniform *FindUniform(std::vector<LinkedUniform> &list, const std::string &name) -{ - for (LinkedUniform &uniform : list) - { - if (uniform.name == name) - return &uniform; - } - - return nullptr; -} - -int GetUniformLocationBinding(const Program::Bindings &uniformLocationBindings, - const sh::Uniform &uniform) -{ - int binding = uniformLocationBindings.getBinding(uniform.name); - if (uniform.isArray() && binding == -1) - { - // Bindings for array uniforms can be set either with or without [0] in the end. - ASSERT(angle::EndsWith(uniform.name, "[0]")); - std::string nameWithoutIndex = uniform.name.substr(0u, uniform.name.length() - 3u); - return uniformLocationBindings.getBinding(nameWithoutIndex); - } - return binding; -} - -} // anonymous namespace - -UniformLinker::UniformLinker(const ProgramState &state) : mState(state) -{ -} - -UniformLinker::~UniformLinker() = default; - -void UniformLinker::getResults(std::vector<LinkedUniform> *uniforms, - std::vector<VariableLocation> *uniformLocations) -{ - uniforms->swap(mUniforms); - uniformLocations->swap(mUniformLocations); -} - -bool UniformLinker::link(const Context *context, - InfoLog &infoLog, - const Program::Bindings &uniformLocationBindings) -{ - if (mState.getAttachedVertexShader() && mState.getAttachedFragmentShader()) - { - ASSERT(mState.getAttachedComputeShader() == nullptr); - if (!validateVertexAndFragmentUniforms(context, infoLog)) - { - return false; - } - } - - // Flatten the uniforms list (nested fields) into a simple list (no nesting). - // Also check the maximum uniform vector and sampler counts. - if (!flattenUniformsAndCheckCaps(context, infoLog)) - { - return false; - } - - if (!checkMaxCombinedAtomicCounters(context->getCaps(), infoLog)) - { - return false; - } - - if (!indexUniforms(infoLog, uniformLocationBindings)) - { - return false; - } - - return true; -} - -bool UniformLinker::validateVertexAndFragmentUniforms(const Context *context, - InfoLog &infoLog) const -{ - // Check that uniforms defined in the vertex and fragment shaders are identical - std::map<std::string, sh::Uniform> linkedUniforms; - const std::vector<sh::Uniform> &vertexUniforms = - mState.getAttachedVertexShader()->getUniforms(context); - const std::vector<sh::Uniform> &fragmentUniforms = - mState.getAttachedFragmentShader()->getUniforms(context); - - for (const sh::Uniform &vertexUniform : vertexUniforms) - { - linkedUniforms[vertexUniform.name] = vertexUniform; - } - - for (const sh::Uniform &fragmentUniform : fragmentUniforms) - { - auto entry = linkedUniforms.find(fragmentUniform.name); - if (entry != linkedUniforms.end()) - { - const sh::Uniform &linkedUniform = entry->second; - const std::string &uniformName = "uniform '" + linkedUniform.name + "'"; - if (!linkValidateUniforms(infoLog, uniformName, linkedUniform, fragmentUniform)) - { - return false; - } - } - } - return true; -} - -// GLSL ES Spec 3.00.3, section 4.3.5. -bool UniformLinker::linkValidateUniforms(InfoLog &infoLog, - const std::string &uniformName, - const sh::Uniform &vertexUniform, - const sh::Uniform &fragmentUniform) -{ -#if ANGLE_PROGRAM_LINK_VALIDATE_UNIFORM_PRECISION == ANGLE_ENABLED - const bool validatePrecision = true; -#else - const bool validatePrecision = false; -#endif - - if (!Program::linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, - validatePrecision)) - { - return false; - } - - // GLSL ES Spec 3.10.4, section 4.4.5. - if (vertexUniform.binding != -1 && fragmentUniform.binding != -1 && - vertexUniform.binding != fragmentUniform.binding) - { - infoLog << "Binding layout qualifiers for " << uniformName - << " differ between vertex and fragment shaders."; - return false; - } - - // GLSL ES Spec 3.10.4, section 9.2.1. - if (vertexUniform.location != -1 && fragmentUniform.location != -1 && - vertexUniform.location != fragmentUniform.location) - { - infoLog << "Location layout qualifiers for " << uniformName - << " differ between vertex and fragment shaders."; - return false; - } - if (vertexUniform.offset != fragmentUniform.offset) - { - infoLog << "Offset layout qualifiers for " << uniformName - << " differ between vertex and fragment shaders."; - return false; - } - - return true; -} - -bool UniformLinker::indexUniforms(InfoLog &infoLog, - const Program::Bindings &uniformLocationBindings) -{ - // All the locations where another uniform can't be located. - std::set<GLuint> reservedLocations; - // Locations which have been allocated for an unused uniform. - std::set<GLuint> ignoredLocations; - - int maxUniformLocation = -1; - - // Gather uniform locations that have been set either using the bindUniformLocation API or by - // using a location layout qualifier and check conflicts between them. - if (!gatherUniformLocationsAndCheckConflicts(infoLog, uniformLocationBindings, - &reservedLocations, &ignoredLocations, - &maxUniformLocation)) - { - return false; - } - - // Conflicts have been checked, now we can prune non-statically used uniforms. Code further down - // the line relies on only having statically used uniforms in mUniforms. - pruneUnusedUniforms(); - - // Gather uniforms that have their location pre-set and uniforms that don't yet have a location. - std::vector<VariableLocation> unlocatedUniforms; - std::map<GLuint, VariableLocation> preLocatedUniforms; - - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) - { - const LinkedUniform &uniform = mUniforms[uniformIndex]; - - if (uniform.isBuiltIn() || IsAtomicCounterType(uniform.type)) - { - continue; - } - - int preSetLocation = GetUniformLocationBinding(uniformLocationBindings, uniform); - int shaderLocation = uniform.location; - - if (shaderLocation != -1) - { - preSetLocation = shaderLocation; - } - - unsigned int elementCount = uniform.getBasicTypeElementCount(); - for (unsigned int arrayIndex = 0; arrayIndex < elementCount; arrayIndex++) - { - VariableLocation location(arrayIndex, static_cast<unsigned int>(uniformIndex)); - - if ((arrayIndex == 0 && preSetLocation != -1) || shaderLocation != -1) - { - int elementLocation = preSetLocation + arrayIndex; - preLocatedUniforms[elementLocation] = location; - } - else - { - unlocatedUniforms.push_back(location); - } - } - } - - // Make enough space for all uniforms, with pre-set locations or not. - mUniformLocations.resize( - std::max(unlocatedUniforms.size() + preLocatedUniforms.size() + ignoredLocations.size(), - static_cast<size_t>(maxUniformLocation + 1))); - - // Assign uniforms with pre-set locations - for (const auto &uniform : preLocatedUniforms) - { - mUniformLocations[uniform.first] = uniform.second; - } - - // Assign ignored uniforms - for (const auto &ignoredLocation : ignoredLocations) - { - mUniformLocations[ignoredLocation].markIgnored(); - } - - // Automatically assign locations for the rest of the uniforms - size_t nextUniformLocation = 0; - for (const auto &unlocatedUniform : unlocatedUniforms) - { - while (mUniformLocations[nextUniformLocation].used() || - mUniformLocations[nextUniformLocation].ignored) - { - nextUniformLocation++; - } - - ASSERT(nextUniformLocation < mUniformLocations.size()); - mUniformLocations[nextUniformLocation] = unlocatedUniform; - nextUniformLocation++; - } - - return true; -} - -bool UniformLinker::gatherUniformLocationsAndCheckConflicts( - InfoLog &infoLog, - const Program::Bindings &uniformLocationBindings, - std::set<GLuint> *reservedLocations, - std::set<GLuint> *ignoredLocations, - int *maxUniformLocation) -{ - for (const LinkedUniform &uniform : mUniforms) - { - if (uniform.isBuiltIn()) - { - continue; - } - - int apiBoundLocation = GetUniformLocationBinding(uniformLocationBindings, uniform); - int shaderLocation = uniform.location; - - if (shaderLocation != -1) - { - unsigned int elementCount = uniform.getBasicTypeElementCount(); - - for (unsigned int arrayIndex = 0; arrayIndex < elementCount; arrayIndex++) - { - // GLSL ES 3.10 section 4.4.3 - int elementLocation = shaderLocation + arrayIndex; - *maxUniformLocation = std::max(*maxUniformLocation, elementLocation); - if (reservedLocations->find(elementLocation) != reservedLocations->end()) - { - infoLog << "Multiple uniforms bound to location " << elementLocation << "."; - return false; - } - reservedLocations->insert(elementLocation); - if (!uniform.staticUse) - { - ignoredLocations->insert(elementLocation); - } - } - } - else if (apiBoundLocation != -1 && uniform.staticUse) - { - // Only the first location is reserved even if the uniform is an array. - *maxUniformLocation = std::max(*maxUniformLocation, apiBoundLocation); - if (reservedLocations->find(apiBoundLocation) != reservedLocations->end()) - { - infoLog << "Multiple uniforms bound to location " << apiBoundLocation << "."; - return false; - } - reservedLocations->insert(apiBoundLocation); - } - } - - // Record the uniform locations that were bound using the API for uniforms that were not found - // from the shader. Other uniforms should not be assigned to those locations. - for (const auto &locationBinding : uniformLocationBindings) - { - GLuint location = locationBinding.second; - if (reservedLocations->find(location) == reservedLocations->end()) - { - ignoredLocations->insert(location); - *maxUniformLocation = std::max(*maxUniformLocation, static_cast<int>(location)); - } - } - - return true; -} - -void UniformLinker::pruneUnusedUniforms() -{ - auto uniformIter = mUniforms.begin(); - while (uniformIter != mUniforms.end()) - { - if (uniformIter->staticUse) - { - ++uniformIter; - } - else - { - uniformIter = mUniforms.erase(uniformIter); - } - } -} - -bool UniformLinker::flattenUniformsAndCheckCapsForShader( - const Context *context, - Shader *shader, - GLuint maxUniformComponents, - GLuint maxTextureImageUnits, - GLuint maxImageUnits, - GLuint maxAtomicCounters, - const std::string &componentsErrorMessage, - const std::string &samplerErrorMessage, - const std::string &imageErrorMessage, - const std::string &atomicCounterErrorMessage, - std::vector<LinkedUniform> &samplerUniforms, - std::vector<LinkedUniform> &imageUniforms, - std::vector<LinkedUniform> &atomicCounterUniforms, - InfoLog &infoLog) -{ - ShaderUniformCount shaderUniformCount; - for (const sh::Uniform &uniform : shader->getUniforms(context)) - { - shaderUniformCount += flattenUniform(uniform, &samplerUniforms, &imageUniforms, - &atomicCounterUniforms, shader->getType()); - } - - if (shaderUniformCount.vectorCount > maxUniformComponents) - { - infoLog << componentsErrorMessage << maxUniformComponents << ")."; - return false; - } - - if (shaderUniformCount.samplerCount > maxTextureImageUnits) - { - infoLog << samplerErrorMessage << maxTextureImageUnits << ")."; - return false; - } - - if (shaderUniformCount.imageCount > maxImageUnits) - { - infoLog << imageErrorMessage << maxImageUnits << ")."; - return false; - } - - if (shaderUniformCount.atomicCounterCount > maxAtomicCounters) - { - infoLog << atomicCounterErrorMessage << maxAtomicCounters << ")."; - return false; - } - - return true; -} - -bool UniformLinker::flattenUniformsAndCheckCaps(const Context *context, InfoLog &infoLog) -{ - std::vector<LinkedUniform> samplerUniforms; - std::vector<LinkedUniform> imageUniforms; - std::vector<LinkedUniform> atomicCounterUniforms; - - const Caps &caps = context->getCaps(); - - if (mState.getAttachedComputeShader()) - { - Shader *computeShader = mState.getAttachedComputeShader(); - - // TODO (mradev): check whether we need finer-grained component counting - if (!flattenUniformsAndCheckCapsForShader( - context, computeShader, caps.maxComputeUniformComponents / 4, - caps.maxComputeTextureImageUnits, caps.maxComputeImageUniforms, - caps.maxComputeAtomicCounters, - "Compute shader active uniforms exceed MAX_COMPUTE_UNIFORM_COMPONENTS (", - "Compute shader sampler count exceeds MAX_COMPUTE_TEXTURE_IMAGE_UNITS (", - "Compute shader image count exceeds MAX_COMPUTE_IMAGE_UNIFORMS (", - "Compute shader atomic counter count exceeds MAX_COMPUTE_ATOMIC_COUNTERS (", - samplerUniforms, imageUniforms, atomicCounterUniforms, infoLog)) - { - return false; - } - } - else - { - Shader *vertexShader = mState.getAttachedVertexShader(); - - if (!flattenUniformsAndCheckCapsForShader( - context, vertexShader, caps.maxVertexUniformVectors, - caps.maxVertexTextureImageUnits, caps.maxVertexImageUniforms, - caps.maxVertexAtomicCounters, - "Vertex shader active uniforms exceed MAX_VERTEX_UNIFORM_VECTORS (", - "Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS (", - "Vertex shader image count exceeds MAX_VERTEX_IMAGE_UNIFORMS (", - "Vertex shader atomic counter count exceeds MAX_VERTEX_ATOMIC_COUNTERS (", - samplerUniforms, imageUniforms, atomicCounterUniforms, infoLog)) - { - return false; - } - - Shader *fragmentShader = mState.getAttachedFragmentShader(); - - if (!flattenUniformsAndCheckCapsForShader( - context, fragmentShader, caps.maxFragmentUniformVectors, caps.maxTextureImageUnits, - caps.maxFragmentImageUniforms, caps.maxFragmentAtomicCounters, - "Fragment shader active uniforms exceed MAX_FRAGMENT_UNIFORM_VECTORS (", - "Fragment shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (", - "Fragment shader image count exceeds MAX_FRAGMENT_IMAGE_UNIFORMS (", - "Fragment shader atomic counter count exceeds MAX_FRAGMENT_ATOMIC_COUNTERS (", - samplerUniforms, imageUniforms, atomicCounterUniforms, infoLog)) - { - return false; - } - } - - mUniforms.insert(mUniforms.end(), samplerUniforms.begin(), samplerUniforms.end()); - mUniforms.insert(mUniforms.end(), imageUniforms.begin(), imageUniforms.end()); - mUniforms.insert(mUniforms.end(), atomicCounterUniforms.begin(), atomicCounterUniforms.end()); - return true; -} - -UniformLinker::ShaderUniformCount UniformLinker::flattenUniform( - const sh::Uniform &uniform, - std::vector<LinkedUniform> *samplerUniforms, - std::vector<LinkedUniform> *imageUniforms, - std::vector<LinkedUniform> *atomicCounterUniforms, - GLenum shaderType) -{ - int location = uniform.location; - ShaderUniformCount shaderUniformCount = - flattenUniformImpl(uniform, uniform.name, uniform.mappedName, samplerUniforms, - imageUniforms, atomicCounterUniforms, shaderType, uniform.staticUse, - uniform.binding, uniform.offset, &location); - if (uniform.staticUse) - { - return shaderUniformCount; - } - return ShaderUniformCount(); -} - -UniformLinker::ShaderUniformCount UniformLinker::flattenArrayOfStructsUniform( - const sh::ShaderVariable &uniform, - unsigned int arrayNestingIndex, - const std::string &namePrefix, - const std::string &mappedNamePrefix, - std::vector<LinkedUniform> *samplerUniforms, - std::vector<LinkedUniform> *imageUniforms, - std::vector<LinkedUniform> *atomicCounterUniforms, - GLenum shaderType, - bool markStaticUse, - int binding, - int offset, - int *location) -{ - // Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the - // innermost. - ShaderUniformCount shaderUniformCount; - const unsigned int currentArraySize = uniform.getNestedArraySize(arrayNestingIndex); - for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++arrayElement) - { - const std::string elementName = namePrefix + ArrayString(arrayElement); - const std::string elementMappedName = mappedNamePrefix + ArrayString(arrayElement); - if (arrayNestingIndex + 1u < uniform.arraySizes.size()) - { - shaderUniformCount += flattenArrayOfStructsUniform( - uniform, arrayNestingIndex + 1u, elementName, elementMappedName, samplerUniforms, - imageUniforms, atomicCounterUniforms, shaderType, markStaticUse, binding, offset, - location); - } - else - { - shaderUniformCount += flattenStructUniform( - uniform.fields, elementName, elementMappedName, samplerUniforms, imageUniforms, - atomicCounterUniforms, shaderType, markStaticUse, binding, offset, location); - } - } - return shaderUniformCount; -} - -UniformLinker::ShaderUniformCount UniformLinker::flattenStructUniform( - const std::vector<sh::ShaderVariable> &fields, - const std::string &namePrefix, - const std::string &mappedNamePrefix, - std::vector<LinkedUniform> *samplerUniforms, - std::vector<LinkedUniform> *imageUniforms, - std::vector<LinkedUniform> *atomicCounterUniforms, - GLenum shaderType, - bool markStaticUse, - int binding, - int offset, - int *location) -{ - ShaderUniformCount shaderUniformCount; - for (const sh::ShaderVariable &field : fields) - { - const std::string &fieldName = namePrefix + "." + field.name; - const std::string &fieldMappedName = mappedNamePrefix + "." + field.mappedName; - - shaderUniformCount += - flattenUniformImpl(field, fieldName, fieldMappedName, samplerUniforms, imageUniforms, - atomicCounterUniforms, shaderType, markStaticUse, -1, -1, location); - } - return shaderUniformCount; -} - -UniformLinker::ShaderUniformCount UniformLinker::flattenArrayUniform( - const sh::ShaderVariable &uniform, - const std::string &namePrefix, - const std::string &mappedNamePrefix, - std::vector<LinkedUniform> *samplerUniforms, - std::vector<LinkedUniform> *imageUniforms, - std::vector<LinkedUniform> *atomicCounterUniforms, - GLenum shaderType, - bool markStaticUse, - int binding, - int offset, - int *location) -{ - ShaderUniformCount shaderUniformCount; - - ASSERT(uniform.isArray()); - for (unsigned int arrayElement = 0u; arrayElement < uniform.getOutermostArraySize(); - ++arrayElement) - { - sh::ShaderVariable uniformElement = uniform; - uniformElement.indexIntoArray(arrayElement); - const std::string elementName = namePrefix + ArrayString(arrayElement); - const std::string elementMappedName = mappedNamePrefix + ArrayString(arrayElement); - - shaderUniformCount += flattenUniformImpl( - uniformElement, elementName, elementMappedName, samplerUniforms, imageUniforms, - atomicCounterUniforms, shaderType, markStaticUse, binding, offset, location); - } - return shaderUniformCount; -} - -UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl( - const sh::ShaderVariable &uniform, - const std::string &fullName, - const std::string &fullMappedName, - std::vector<LinkedUniform> *samplerUniforms, - std::vector<LinkedUniform> *imageUniforms, - std::vector<LinkedUniform> *atomicCounterUniforms, - GLenum shaderType, - bool markStaticUse, - int binding, - int offset, - int *location) -{ - ASSERT(location); - ShaderUniformCount shaderUniformCount; - - if (uniform.isStruct()) - { - if (uniform.isArray()) - { - shaderUniformCount += flattenArrayOfStructsUniform( - uniform, 0u, fullName, fullMappedName, samplerUniforms, imageUniforms, - atomicCounterUniforms, shaderType, markStaticUse, binding, offset, location); - } - else - { - shaderUniformCount += flattenStructUniform( - uniform.fields, fullName, fullMappedName, samplerUniforms, imageUniforms, - atomicCounterUniforms, shaderType, markStaticUse, binding, offset, location); - } - return shaderUniformCount; - } - if (uniform.isArrayOfArrays()) - { - // GLES 3.1 November 2016 section 7.3.1 page 77: - // "For an active variable declared as an array of an aggregate data type (structures or - // arrays), a separate entry will be generated for each active array element" - return flattenArrayUniform(uniform, fullName, fullMappedName, samplerUniforms, - imageUniforms, atomicCounterUniforms, shaderType, markStaticUse, - binding, offset, location); - } - - // Not a struct - bool isSampler = IsSamplerType(uniform.type); - bool isImage = IsImageType(uniform.type); - bool isAtomicCounter = IsAtomicCounterType(uniform.type); - std::vector<gl::LinkedUniform> *uniformList = &mUniforms; - if (isSampler) - { - uniformList = samplerUniforms; - } - else if (isImage) - { - uniformList = imageUniforms; - } - else if (isAtomicCounter) - { - uniformList = atomicCounterUniforms; - } - - std::string fullNameWithArrayIndex(fullName); - std::string fullMappedNameWithArrayIndex(fullMappedName); - - if (uniform.isArray()) - { - // We're following the GLES 3.1 November 2016 spec section 7.3.1.1 Naming Active Resources - // and including [0] at the end of array variable names. - fullNameWithArrayIndex += "[0]"; - fullMappedNameWithArrayIndex += "[0]"; - } - - LinkedUniform *existingUniform = FindUniform(*uniformList, fullNameWithArrayIndex); - if (existingUniform) - { - if (binding != -1) - { - existingUniform->binding = binding; - } - if (offset != -1) - { - existingUniform->offset = offset; - } - if (*location != -1) - { - existingUniform->location = *location; - } - if (markStaticUse) - { - existingUniform->staticUse = true; - existingUniform->setStaticUse(shaderType, true); - } - } - else - { - ASSERT(uniform.arraySizes.size() <= 1u); - LinkedUniform linkedUniform(uniform.type, uniform.precision, fullNameWithArrayIndex, - uniform.arraySizes, binding, offset, *location, -1, - sh::BlockMemberInfo::getDefaultBlockInfo()); - linkedUniform.mappedName = fullMappedNameWithArrayIndex; - linkedUniform.staticUse = markStaticUse; - linkedUniform.flattenedOffsetInParentArrays = uniform.flattenedOffsetInParentArrays; - if (markStaticUse) - { - linkedUniform.setStaticUse(shaderType, true); - } - - uniformList->push_back(linkedUniform); - } - - // Struct and array of arrays uniforms get flattened so we can use getBasicTypeElementCount(). - unsigned int elementCount = uniform.getBasicTypeElementCount(); - - // Samplers and images aren't "real" uniforms, so they don't count towards register usage. - // Likewise, don't count "real" uniforms towards opaque count. - shaderUniformCount.vectorCount = - (IsOpaqueType(uniform.type) ? 0 : (VariableRegisterCount(uniform.type) * elementCount)); - shaderUniformCount.samplerCount = (isSampler ? elementCount : 0); - shaderUniformCount.imageCount = (isImage ? elementCount : 0); - shaderUniformCount.atomicCounterCount = (isAtomicCounter ? elementCount : 0); - - if (*location != -1) - { - *location += elementCount; - } - - return shaderUniformCount; -} - -bool UniformLinker::checkMaxCombinedAtomicCounters(const Caps &caps, InfoLog &infoLog) -{ - unsigned int atomicCounterCount = 0; - for (const auto &uniform : mUniforms) - { - if (IsAtomicCounterType(uniform.type) && uniform.staticUse) - { - atomicCounterCount += uniform.getBasicTypeElementCount(); - if (atomicCounterCount > caps.maxCombinedAtomicCounters) - { - infoLog << "atomic counter count exceeds MAX_COMBINED_ATOMIC_COUNTERS" - << caps.maxCombinedAtomicCounters << ")."; - return false; - } - } - } - return true; -} - -// InterfaceBlockLinker implementation. -InterfaceBlockLinker::InterfaceBlockLinker(std::vector<InterfaceBlock> *blocksOut) - : mBlocksOut(blocksOut) -{ -} - -InterfaceBlockLinker::~InterfaceBlockLinker() -{ -} - -void InterfaceBlockLinker::addShaderBlocks(GLenum shader, - const std::vector<sh::InterfaceBlock> *blocks) -{ - mShaderBlocks.push_back(std::make_pair(shader, blocks)); -} - -void InterfaceBlockLinker::linkBlocks(const GetBlockSize &getBlockSize, - const GetBlockMemberInfo &getMemberInfo) const -{ - ASSERT(mBlocksOut->empty()); - - std::set<std::string> visitedList; - - for (const auto &shaderBlocks : mShaderBlocks) - { - const GLenum shaderType = shaderBlocks.first; - - for (const auto &block : *shaderBlocks.second) - { - // Only 'packed' blocks are allowed to be considered inactive. - if (!block.staticUse && block.layout == sh::BLOCKLAYOUT_PACKED) - continue; - - if (visitedList.count(block.name) > 0) - { - if (block.staticUse) - { - for (InterfaceBlock &priorBlock : *mBlocksOut) - { - if (block.name == priorBlock.name) - { - priorBlock.setStaticUse(shaderType, true); - // TODO(jiajia.qin@intel.com): update the block members static use. - } - } - } - } - else - { - defineInterfaceBlock(getBlockSize, getMemberInfo, block, shaderType); - visitedList.insert(block.name); - } - } - } -} - -template <typename VarT> -void InterfaceBlockLinker::defineArrayOfStructsBlockMembers(const GetBlockMemberInfo &getMemberInfo, - const VarT &field, - unsigned int arrayNestingIndex, - const std::string &prefix, - const std::string &mappedPrefix, - int blockIndex, - bool singleEntryForTopLevelArray, - int topLevelArraySize) const -{ - // Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the - // innermost. - unsigned int entryGenerationArraySize = field.getNestedArraySize(arrayNestingIndex); - if (singleEntryForTopLevelArray) - { - entryGenerationArraySize = 1; - } - for (unsigned int arrayElement = 0u; arrayElement < entryGenerationArraySize; ++arrayElement) - { - const std::string elementName = prefix + ArrayString(arrayElement); - const std::string elementMappedName = mappedPrefix + ArrayString(arrayElement); - if (arrayNestingIndex + 1u < field.arraySizes.size()) - { - defineArrayOfStructsBlockMembers(getMemberInfo, field, arrayNestingIndex + 1u, - elementName, elementMappedName, blockIndex, false, - topLevelArraySize); - } - else - { - defineBlockMembers(getMemberInfo, field.fields, elementName, elementMappedName, - blockIndex, false, topLevelArraySize); - } - } -} - -template <typename VarT> -void InterfaceBlockLinker::defineBlockMembers(const GetBlockMemberInfo &getMemberInfo, - const std::vector<VarT> &fields, - const std::string &prefix, - const std::string &mappedPrefix, - int blockIndex, - bool singleEntryForTopLevelArray, - int topLevelArraySize) const -{ - for (const VarT &field : fields) - { - std::string fullName = (prefix.empty() ? field.name : prefix + "." + field.name); - std::string fullMappedName = - (mappedPrefix.empty() ? field.mappedName : mappedPrefix + "." + field.mappedName); - - defineBlockMember(getMemberInfo, field, fullName, fullMappedName, blockIndex, - singleEntryForTopLevelArray, topLevelArraySize); - } -} - -template <typename VarT> -void InterfaceBlockLinker::defineBlockMember(const GetBlockMemberInfo &getMemberInfo, - const VarT &field, - const std::string &fullName, - const std::string &fullMappedName, - int blockIndex, - bool singleEntryForTopLevelArray, - int topLevelArraySize) const -{ - int nextArraySize = topLevelArraySize; - if (((field.isArray() && field.isStruct()) || field.isArrayOfArrays()) && - singleEntryForTopLevelArray) - { - // In OpenGL ES 3.10 spec, session 7.3.1.1 'For an active shader storage block - // member declared as an array of an aggregate type, an entry will be generated only - // for the first array element, regardless of its type.' - nextArraySize = field.getOutermostArraySize(); - } - - if (field.isStruct()) - { - if (field.isArray()) - { - defineArrayOfStructsBlockMembers(getMemberInfo, field, 0u, fullName, fullMappedName, - blockIndex, singleEntryForTopLevelArray, - nextArraySize); - } - else - { - ASSERT(nextArraySize == topLevelArraySize); - defineBlockMembers(getMemberInfo, field.fields, fullName, fullMappedName, blockIndex, - false, nextArraySize); - } - return; - } - if (field.isArrayOfArrays()) - { - unsigned int entryGenerationArraySize = field.getOutermostArraySize(); - if (singleEntryForTopLevelArray) - { - entryGenerationArraySize = 1u; - } - for (unsigned int arrayElement = 0u; arrayElement < entryGenerationArraySize; - ++arrayElement) - { - VarT fieldElement = field; - fieldElement.indexIntoArray(arrayElement); - const std::string elementName = fullName + ArrayString(arrayElement); - const std::string elementMappedName = fullMappedName + ArrayString(arrayElement); - - defineBlockMember(getMemberInfo, fieldElement, elementName, elementMappedName, - blockIndex, false, nextArraySize); - } - return; - } - - // If getBlockMemberInfo returns false, the variable is optimized out. - sh::BlockMemberInfo memberInfo; - if (!getMemberInfo(fullName, fullMappedName, &memberInfo)) - { - return; - } - - std::string fullNameWithArrayIndex = fullName; - std::string fullMappedNameWithArrayIndex = fullMappedName; - - if (field.isArray()) - { - fullNameWithArrayIndex += "[0]"; - fullMappedNameWithArrayIndex += "[0]"; - } - - ASSERT(nextArraySize == topLevelArraySize); - defineBlockMemberImpl(field, fullNameWithArrayIndex, fullMappedNameWithArrayIndex, blockIndex, - memberInfo, nextArraySize); -} - -void InterfaceBlockLinker::defineInterfaceBlock(const GetBlockSize &getBlockSize, - const GetBlockMemberInfo &getMemberInfo, - const sh::InterfaceBlock &interfaceBlock, - GLenum shaderType) const -{ - size_t blockSize = 0; - std::vector<unsigned int> blockIndexes; - - int blockIndex = static_cast<int>(mBlocksOut->size()); - // Track the first and last block member index to determine the range of active block members in - // the block. - size_t firstBlockMemberIndex = getCurrentBlockMemberIndex(); - defineBlockMembers(getMemberInfo, interfaceBlock.fields, interfaceBlock.fieldPrefix(), - interfaceBlock.fieldMappedPrefix(), blockIndex, - interfaceBlock.blockType == sh::BlockType::BLOCK_BUFFER, 1); - size_t lastBlockMemberIndex = getCurrentBlockMemberIndex(); - - for (size_t blockMemberIndex = firstBlockMemberIndex; blockMemberIndex < lastBlockMemberIndex; - ++blockMemberIndex) - { - blockIndexes.push_back(static_cast<unsigned int>(blockMemberIndex)); - } - - // ESSL 3.10 section 4.4.4 page 58: - // Any uniform or shader storage block declared without a binding qualifier is initially - // assigned to block binding point zero. - int blockBinding = (interfaceBlock.binding == -1 ? 0 : interfaceBlock.binding); - for (unsigned int arrayElement = 0; arrayElement < interfaceBlock.elementCount(); - ++arrayElement) - { - std::string blockArrayName = interfaceBlock.name; - std::string blockMappedArrayName = interfaceBlock.mappedName; - if (interfaceBlock.isArray()) - { - blockArrayName += ArrayString(arrayElement); - blockMappedArrayName += ArrayString(arrayElement); - } - - // Don't define this block at all if it's not active in the implementation. - if (!getBlockSize(blockArrayName, blockMappedArrayName, &blockSize)) - { - continue; - } - - InterfaceBlock block(interfaceBlock.name, interfaceBlock.mappedName, - interfaceBlock.isArray(), arrayElement, blockBinding + arrayElement); - block.memberIndexes = blockIndexes; - block.setStaticUse(shaderType, interfaceBlock.staticUse); - - // Since all block elements in an array share the same active interface blocks, they - // will all be active once any block member is used. So, since interfaceBlock.name[0] - // was active, here we will add every block element in the array. - block.dataSize = static_cast<unsigned int>(blockSize); - mBlocksOut->push_back(block); - } -} - -// UniformBlockLinker implementation. -UniformBlockLinker::UniformBlockLinker(std::vector<InterfaceBlock> *blocksOut, - std::vector<LinkedUniform> *uniformsOut) - : InterfaceBlockLinker(blocksOut), mUniformsOut(uniformsOut) -{ -} - -UniformBlockLinker::~UniformBlockLinker() -{ -} - -void UniformBlockLinker::defineBlockMemberImpl(const sh::ShaderVariable &field, - const std::string &fullName, - const std::string &fullMappedName, - int blockIndex, - const sh::BlockMemberInfo &memberInfo, - int /*topLevelArraySize*/) const -{ - LinkedUniform newUniform(field.type, field.precision, fullName, field.arraySizes, -1, -1, -1, - blockIndex, memberInfo); - newUniform.mappedName = fullMappedName; - // TODO(jiajia.qin@intel.com): update the block memeber static use. - - // Since block uniforms have no location, we don't need to store them in the uniform locations - // list. - mUniformsOut->push_back(newUniform); -} - -size_t UniformBlockLinker::getCurrentBlockMemberIndex() const -{ - return mUniformsOut->size(); -} - -// ShaderStorageBlockLinker implementation. -ShaderStorageBlockLinker::ShaderStorageBlockLinker(std::vector<InterfaceBlock> *blocksOut, - std::vector<BufferVariable> *bufferVariablesOut) - : InterfaceBlockLinker(blocksOut), mBufferVariablesOut(bufferVariablesOut) -{ -} - -ShaderStorageBlockLinker::~ShaderStorageBlockLinker() -{ -} - -void ShaderStorageBlockLinker::defineBlockMemberImpl(const sh::ShaderVariable &field, - const std::string &fullName, - const std::string &fullMappedName, - int blockIndex, - const sh::BlockMemberInfo &memberInfo, - int topLevelArraySize) const -{ - BufferVariable newBufferVariable(field.type, field.precision, fullName, field.arraySizes, - blockIndex, memberInfo); - newBufferVariable.mappedName = fullMappedName; - // TODO(jiajia.qin@intel.com): update the block memeber static use. - - newBufferVariable.topLevelArraySize = topLevelArraySize; - - mBufferVariablesOut->push_back(newBufferVariable); -} - -size_t ShaderStorageBlockLinker::getCurrentBlockMemberIndex() const -{ - return mBufferVariablesOut->size(); -} - -} // namespace gl |