summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/libANGLE/ProgramLinkedResources.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/libANGLE/ProgramLinkedResources.cpp')
-rw-r--r--src/3rdparty/angle/src/libANGLE/ProgramLinkedResources.cpp1040
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