Link atomic counters to buffers
Gather counters from each shader and group them according the
layout qualifier 'binding' into each buffer.
BUG=angleproject:1729
TEST=angle_end2end_tests:AtomicCounterBufferTest
Change-Id: I8d0cd0d2bf65be37c035b0e1540481c8bee0bae4
diff --git a/src/libANGLE/UniformLinker.cpp b/src/libANGLE/UniformLinker.cpp
index 1d70154..065d780 100644
--- a/src/libANGLE/UniformLinker.cpp
+++ b/src/libANGLE/UniformLinker.cpp
@@ -66,6 +66,11 @@
return false;
}
+ if (!checkMaxCombinedAtomicCounters(context->getCaps(), infoLog))
+ {
+ return false;
+ }
+
if (!indexUniforms(infoLog, uniformLocationBindings))
{
return false;
@@ -140,6 +145,12 @@
<< " 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;
}
@@ -326,17 +337,21 @@
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);
+ shaderUniformCount +=
+ flattenUniform(uniform, &samplerUniforms, &imageUniforms, &atomicCounterUniforms);
}
if (shaderUniformCount.vectorCount > maxUniformComponents)
@@ -357,6 +372,12 @@
return false;
}
+ if (shaderUniformCount.atomicCounterCount > maxAtomicCounters)
+ {
+ infoLog << atomicCounterErrorMessage << maxAtomicCounters << ").";
+ return false;
+ }
+
return true;
}
@@ -364,6 +385,7 @@
{
std::vector<LinkedUniform> samplerUniforms;
std::vector<LinkedUniform> imageUniforms;
+ std::vector<LinkedUniform> atomicCounterUniforms;
const Caps &caps = context->getCaps();
@@ -375,10 +397,12 @@
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 (", samplerUniforms,
- imageUniforms, infoLog))
+ "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;
}
@@ -390,10 +414,12 @@
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 (", samplerUniforms,
- imageUniforms, infoLog))
+ "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;
}
@@ -402,11 +428,12 @@
if (!flattenUniformsAndCheckCapsForShader(
context, fragmentShader, caps.maxFragmentUniformVectors, caps.maxTextureImageUnits,
- caps.maxFragmentImageUniforms,
+ 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 (",
- samplerUniforms, imageUniforms, infoLog))
+ "Fragment shader atomic counter count exceeds MAX_FRAGMENT_ATOMIC_COUNTERS (",
+ samplerUniforms, imageUniforms, atomicCounterUniforms, infoLog))
{
return false;
}
@@ -414,18 +441,20 @@
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> *imageUniforms,
+ std::vector<LinkedUniform> *atomicCounterUniforms)
{
int location = uniform.location;
- ShaderUniformCount shaderUniformCount =
- flattenUniformImpl(uniform, uniform.name, samplerUniforms, imageUniforms, uniform.staticUse,
- uniform.binding, &location);
+ ShaderUniformCount shaderUniformCount = flattenUniformImpl(
+ uniform, uniform.name, samplerUniforms, imageUniforms, atomicCounterUniforms,
+ uniform.staticUse, uniform.binding, uniform.offset, &location);
if (uniform.staticUse)
{
return shaderUniformCount;
@@ -438,8 +467,10 @@
const std::string &fullName,
std::vector<LinkedUniform> *samplerUniforms,
std::vector<LinkedUniform> *imageUniforms,
+ std::vector<LinkedUniform> *atomicCounterUniforms,
bool markStaticUse,
int binding,
+ int offset,
int *location)
{
ASSERT(location);
@@ -458,7 +489,7 @@
shaderUniformCount +=
flattenUniformImpl(field, fieldFullName, samplerUniforms, imageUniforms,
- markStaticUse, -1, location);
+ atomicCounterUniforms, markStaticUse, -1, -1, location);
}
}
@@ -468,16 +499,20 @@
// 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)
{
- // Store sampler uniforms separately, so we'll append them to the end of the list.
uniformList = samplerUniforms;
}
else if (isImage)
{
uniformList = imageUniforms;
}
+ else if (isAtomicCounter)
+ {
+ uniformList = atomicCounterUniforms;
+ }
LinkedUniform *existingUniform = FindUniform(*uniformList, fullName);
if (existingUniform)
{
@@ -485,6 +520,10 @@
{
existingUniform->binding = binding;
}
+ if (offset != -1)
+ {
+ existingUniform->offset = offset;
+ }
if (*location != -1)
{
existingUniform->location = *location;
@@ -497,20 +536,22 @@
else
{
LinkedUniform linkedUniform(uniform.type, uniform.precision, fullName, uniform.arraySize,
- binding, *location, -1,
+ binding, -1, *location, -1,
sh::BlockMemberInfo::getDefaultBlockInfo());
linkedUniform.staticUse = markStaticUse;
+
uniformList->push_back(linkedUniform);
}
unsigned int elementCount = uniform.elementCount();
// Samplers and images aren't "real" uniforms, so they don't count towards register usage.
- // Likewise, don't count "real" uniforms towards sampler and image count.
+ // Likewise, don't count "real" uniforms towards opaque count.
shaderUniformCount.vectorCount =
- ((isSampler || isImage) ? 0 : (VariableRegisterCount(uniform.type) * elementCount));
+ (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)
{
@@ -520,4 +561,23 @@
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.elementCount();
+ if (atomicCounterCount > caps.maxCombinedAtomicCounters)
+ {
+ infoLog << "atomic counter count exceeds MAX_COMBINED_ATOMIC_COUNTERS"
+ << caps.maxCombinedAtomicCounters << ").";
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
} // namespace gl