aboutsummaryrefslogtreecommitdiff
path: root/glslang/MachineIndependent/linkValidate.cpp
diff options
context:
space:
mode:
authorJohn Kessenich <cepheus@frii.com>2013-12-05 20:07:56 +0000
committerJohn Kessenich <cepheus@frii.com>2013-12-05 20:07:56 +0000
commit0b39137009e736ca6d99a0a8225690118785c9b5 (patch)
treead46e8628730cb00c07875fd956f75dd4f4a509b /glslang/MachineIndependent/linkValidate.cpp
parent2f15597a7ebd5ed4b2089e3a44636df8f54c152f (diff)
downloadglslang-0b39137009e736ca6d99a0a8225690118785c9b5.tar.gz
Implement location overlap error checking.
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@24376 e7fa87d3-cd2b-0410-9028-fcbf551c1848
Diffstat (limited to 'glslang/MachineIndependent/linkValidate.cpp')
-rw-r--r--glslang/MachineIndependent/linkValidate.cpp91
1 files changed, 91 insertions, 0 deletions
diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp
index b0669128..bacf4449 100644
--- a/glslang/MachineIndependent/linkValidate.cpp
+++ b/glslang/MachineIndependent/linkValidate.cpp
@@ -443,4 +443,95 @@ bool TIntermediate::userOutputUsed() const
return found;
}
+// Accumulate locations used for inputs, outputs, and uniforms, and check for collisions
+// as the accumulation is done.
+//
+// Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value.
+int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& type)
+{
+ int set;
+ if (qualifier.isPipeInput())
+ set = 0;
+ else if (qualifier.isPipeOutput())
+ set = 1;
+ else if (qualifier.isUniform())
+ set = 2;
+ else
+ return -1;
+
+ int size;
+ if (qualifier.isUniform()) {
+ if (type.isArray())
+ size = type.getArraySize();
+ else
+ size = 1;
+ } else
+ size = computeTypeLocationSize(type);
+
+ TRange range = { qualifier.layoutSlotLocation, qualifier.layoutSlotLocation + size - 1 };
+
+ // check for collisions
+ for (size_t r = 0; r < usedLocations[set].size(); ++r) {
+ if (range.last >= usedLocations[set][r].start &&
+ range.start <= usedLocations[set][r].last) {
+ // there is a collision; pick one
+ return std::max(range.start, usedLocations[set][r].start);
+ }
+ }
+
+ usedLocations[set].push_back(range);
+
+ return -1;
+}
+
+// Recursively figure out how many locations are used up by an input or output type.
+// Return the size of type, as measured by "locations".
+int TIntermediate::computeTypeLocationSize(const TType& type)
+{
+ // "If the declared input is an array of size n and each element takes m locations, it will be assigned m * n
+ // consecutive locations..."
+ if (type.isArray()) {
+ TType elementType(type, 0);
+ return type.getArraySize() * computeTypeLocationSize(elementType);
+ }
+
+ // "The locations consumed by block and structure members are determined by applying the rules above
+ // recursively..."
+ if (type.isStruct()) {
+ // TODO: 440 functionality: input/output block locations when members also have locations
+ int size = 0;
+ for (size_t member = 0; member < type.getStruct()->size(); ++member) {
+ TType memberType(type, member);
+ size += computeTypeLocationSize(memberType);
+ }
+ return size;
+ }
+
+ // "If a vertex shader input is any scalar or vector type, it will consume a single location. If a non-vertex
+ // shader input is a scalar or vector type other than dvec3 or dvec4, it will consume a single location, while
+ // types dvec3 or dvec4 will consume two consecutive locations. Inputs of type double and dvec2 will
+ // consume only a single location, in all stages."
+ if (type.isScalar())
+ return 1;
+ if (type.isVector()) {
+ if (language == EShLangVertex && type.getQualifier().isPipeInput())
+ return 1;
+ if (type.getBasicType() == EbtDouble && type.getVectorSize() > 2)
+ return 2;
+ else
+ return 1;
+ }
+
+ // "If the declared input is an n x m single- or double-precision matrix, ...
+ // The number of locations assigned for each matrix will be the same as
+ // for an n-element array of m-component vectors..."
+ if (type.isMatrix()) {
+ TType columnType(type, 0);
+ return type.getMatrixCols() * computeTypeLocationSize(columnType);
+ }
+
+ assert(0);
+ return 1;
+}
+
} // end namespace glslang