Use ShaderMap in Caps - Part II

This patch is the last one in the series of putting resource limits
on each shader stage into ShaderMap. With this patch, all such values
are organized in the corresponding ShaderMap.

This patch also cleans up all the related code by using this new
type of data structure.

BUG=angleproject:2169

Change-Id: I440643fe44ab63acf7da0a1611643beed1ba66d1
Reviewed-on: https://chromium-review.googlesource.com/1077748
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/libANGLE/ProgramLinkedResources.cpp b/src/libANGLE/ProgramLinkedResources.cpp
index 375546e..2263544 100644
--- a/src/libANGLE/ProgramLinkedResources.cpp
+++ b/src/libANGLE/ProgramLinkedResources.cpp
@@ -135,6 +135,115 @@
     return true;
 }
 
+GLuint GetMaximumShaderUniformVectors(ShaderType shaderType, const Caps &caps)
+{
+    switch (shaderType)
+    {
+        case ShaderType::Vertex:
+            return caps.maxVertexUniformVectors;
+        case ShaderType::Fragment:
+            return caps.maxFragmentUniformVectors;
+
+        case ShaderType::Compute:
+        case ShaderType::Geometry:
+            return caps.maxShaderUniformComponents[shaderType] / 4;
+
+        default:
+            UNREACHABLE();
+            return 0u;
+    }
+}
+
+enum class UniformType : uint8_t
+{
+    Variable      = 0,
+    Sampler       = 1,
+    Image         = 2,
+    AtomicCounter = 3,
+
+    InvalidEnum = 4,
+    EnumCount   = 4,
+};
+
+const char *GetUniformResourceNameString(UniformType uniformType)
+{
+    switch (uniformType)
+    {
+        case UniformType::Variable:
+            return "uniform";
+        case UniformType::Sampler:
+            return "texture image unit";
+        case UniformType::Image:
+            return "image uniform";
+        case UniformType::AtomicCounter:
+            return "atomic counter";
+        default:
+            UNREACHABLE();
+            return "";
+    }
+}
+
+std::string GetUniformResourceLimitName(ShaderType shaderType, UniformType uniformType)
+{
+    // Special case: MAX_TEXTURE_IMAGE_UNITS (no "MAX_FRAGMENT_TEXTURE_IMAGE_UNITS")
+    if (shaderType == ShaderType::Fragment && uniformType == UniformType::Sampler)
+    {
+        return "MAX_TEXTURE_IMAGE_UNITS";
+    }
+
+    std::ostringstream ostream;
+    ostream << "MAX_" << GetShaderTypeString(shaderType) << "_";
+
+    switch (uniformType)
+    {
+        case UniformType::Variable:
+            // For vertex and fragment shaders, ES 2.0 only defines MAX_VERTEX_UNIFORM_VECTORS and
+            // MAX_FRAGMENT_UNIFORM_VECTORS ([OpenGL ES 2.0] Table 6.20).
+            if (shaderType == ShaderType::Vertex || shaderType == ShaderType::Fragment)
+            {
+                ostream << "UNIFORM_VECTORS";
+                break;
+            }
+            // For compute and geometry shaders, there are no definitions on
+            // "MAX_COMPUTE_UNIFORM_VECTORS" or "MAX_GEOMETRY_UNIFORM_VECTORS_EXT"
+            // ([OpenGL ES 3.1] Table 20.45, [EXT_geometry_shader] Table 20.43gs).
+            else
+            {
+                ostream << "UNIFORM_COMPONENTS";
+            }
+            break;
+        case UniformType::Sampler:
+            ostream << "TEXTURE_IMAGE_UNITS";
+            break;
+        case UniformType::Image:
+            ostream << "IMAGE_UNIFORMS";
+            break;
+        case UniformType::AtomicCounter:
+            ostream << "ATOMIC_COUNTERS";
+            break;
+        default:
+            UNREACHABLE();
+            return "";
+    }
+
+    if (shaderType == ShaderType::Geometry)
+    {
+        ostream << "_EXT";
+    }
+
+    return ostream.str();
+}
+
+void LogUniformsExceedLimit(ShaderType shaderType,
+                            UniformType uniformType,
+                            GLuint limit,
+                            InfoLog &infoLog)
+{
+    infoLog << GetShaderTypeString(shaderType) << " shader "
+            << GetUniformResourceNameString(uniformType) << "s count exceeds "
+            << GetUniformResourceLimitName(shaderType, uniformType) << "(" << limit << ")";
+}
+
 }  // anonymous namespace
 
 UniformLinker::UniformLinker(const ProgramState &state) : mState(state)
@@ -400,14 +509,7 @@
 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,
+    const Caps &caps,
     std::vector<LinkedUniform> &samplerUniforms,
     std::vector<LinkedUniform> &imageUniforms,
     std::vector<LinkedUniform> &atomicCounterUniforms,
@@ -420,27 +522,46 @@
                                              &atomicCounterUniforms, shader->getType());
     }
 
-    if (shaderUniformCount.vectorCount > maxUniformComponents)
+    ShaderType shaderType = shader->getType();
+
+    // TODO (jiawei.shao@intel.com): check whether we need finer-grained component counting
+    GLuint maxUniformVectorsCount = GetMaximumShaderUniformVectors(shaderType, caps);
+    if (shaderUniformCount.vectorCount > maxUniformVectorsCount)
     {
-        infoLog << componentsErrorMessage << maxUniformComponents << ").";
+        GLuint maxUniforms = 0u;
+
+        // See comments in GetUniformResourceLimitName()
+        if (shaderType == ShaderType::Vertex || shaderType == ShaderType::Fragment)
+        {
+            maxUniforms = maxUniformVectorsCount;
+        }
+        else
+        {
+            maxUniforms = maxUniformVectorsCount * 4;
+        }
+
+        LogUniformsExceedLimit(shaderType, UniformType::Variable, maxUniforms, infoLog);
         return false;
     }
 
-    if (shaderUniformCount.samplerCount > maxTextureImageUnits)
+    if (shaderUniformCount.samplerCount > caps.maxShaderTextureImageUnits[shaderType])
     {
-        infoLog << samplerErrorMessage << maxTextureImageUnits << ").";
+        LogUniformsExceedLimit(shaderType, UniformType::Sampler,
+                               caps.maxShaderTextureImageUnits[shaderType], infoLog);
         return false;
     }
 
-    if (shaderUniformCount.imageCount > maxImageUnits)
+    if (shaderUniformCount.imageCount > caps.maxShaderImageUniforms[shaderType])
     {
-        infoLog << imageErrorMessage << maxImageUnits << ").";
+        LogUniformsExceedLimit(shaderType, UniformType::Image,
+                               caps.maxShaderImageUniforms[shaderType], infoLog);
         return false;
     }
 
-    if (shaderUniformCount.atomicCounterCount > maxAtomicCounters)
+    if (shaderUniformCount.atomicCounterCount > caps.maxShaderAtomicCounters[shaderType])
     {
-        infoLog << atomicCounterErrorMessage << maxAtomicCounters << ").";
+        LogUniformsExceedLimit(shaderType, UniformType::AtomicCounter,
+                               caps.maxShaderAtomicCounters[shaderType], infoLog);
         return false;
     }
 
@@ -454,69 +575,16 @@
     std::vector<LinkedUniform> atomicCounterUniforms;
 
     const Caps &caps = context->getCaps();
-
-    if (mState.getAttachedShader(ShaderType::Compute))
+    for (ShaderType shaderType : AllShaderTypes())
     {
-        Shader *computeShader = mState.getAttachedShader(ShaderType::Compute);
-
-        // TODO (mradev): check whether we need finer-grained component counting
-        if (!flattenUniformsAndCheckCapsForShader(
-                context, computeShader, caps.maxComputeUniformComponents / 4,
-                caps.maxShaderTextureImageUnits[ShaderType::Compute], 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))
+        Shader *shader = mState.getAttachedShader(shaderType);
+        if (!shader)
         {
-            return false;
-        }
-    }
-    else
-    {
-        Shader *vertexShader = mState.getAttachedShader(ShaderType::Vertex);
-
-        if (!flattenUniformsAndCheckCapsForShader(
-                context, vertexShader, caps.maxVertexUniformVectors,
-                caps.maxShaderTextureImageUnits[ShaderType::Vertex], 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;
+            continue;
         }
 
-        Shader *fragmentShader = mState.getAttachedShader(ShaderType::Fragment);
-
-        if (!flattenUniformsAndCheckCapsForShader(
-                context, fragmentShader, caps.maxFragmentUniformVectors,
-                caps.maxShaderTextureImageUnits[ShaderType::Fragment],
-                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;
-        }
-
-        Shader *geometryShader = mState.getAttachedShader(ShaderType::Geometry);
-        // TODO (jiawei.shao@intel.com): check whether we need finer-grained component counting
-        if (geometryShader &&
-            !flattenUniformsAndCheckCapsForShader(
-                context, geometryShader, caps.maxGeometryUniformComponents / 4,
-                caps.maxShaderTextureImageUnits[ShaderType::Geometry],
-                caps.maxGeometryImageUniforms, caps.maxGeometryAtomicCounters,
-                "Geometry shader active uniforms exceed MAX_GEOMETRY_UNIFORM_VECTORS_EXT (",
-                "Geometry shader sampler count exceeds MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT (",
-                "Geometry shader image count exceeds MAX_GEOMETRY_IMAGE_UNIFORMS_EXT (",
-                "Geometry shader atomic counter count exceeds MAX_GEOMETRY_ATOMIC_COUNTERS_EXT (",
-                samplerUniforms, imageUniforms, atomicCounterUniforms, infoLog))
+        if (!flattenUniformsAndCheckCapsForShader(context, shader, caps, samplerUniforms,
+                                                  imageUniforms, atomicCounterUniforms, infoLog))
         {
             return false;
         }