OpenGL: retrieve driver limits.

Query the OpenGL driver for values for the V1 limits.

I couldn't find GL equivalents for some limits, so I left them at
default and added comments.

Bug: dawn:1834

Change-Id: I0ffad5960c100033151d3fa895ac42c7520ab5b4
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/133720
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Stephen White <senorblanco@chromium.org>
diff --git a/src/dawn/native/opengl/PhysicalDeviceGL.cpp b/src/dawn/native/opengl/PhysicalDeviceGL.cpp
index bdcfc4f..a02f6a5 100644
--- a/src/dawn/native/opengl/PhysicalDeviceGL.cpp
+++ b/src/dawn/native/opengl/PhysicalDeviceGL.cpp
@@ -14,6 +14,7 @@
 
 #include "dawn/native/opengl/PhysicalDeviceGL.h"
 
+#include <algorithm>
 #include <memory>
 #include <string>
 #include <utility>
@@ -147,8 +148,71 @@
     }
 }
 
+namespace {
+GLint Get(const OpenGLFunctions& gl, GLenum pname) {
+    GLint value;
+    gl.GetIntegerv(pname, &value);
+    return value;
+}
+
+GLint GetIndexed(const OpenGLFunctions& gl, GLenum pname, GLuint index) {
+    GLint value;
+    gl.GetIntegeri_v(pname, index, &value);
+    return value;
+}
+}  // namespace
+
 MaybeError PhysicalDevice::InitializeSupportedLimitsImpl(CombinedLimits* limits) {
+    const OpenGLFunctions& gl = mFunctions;
     GetDefaultLimits(&limits->v1);
+
+    limits->v1.maxTextureDimension1D = limits->v1.maxTextureDimension2D =
+        Get(gl, GL_MAX_TEXTURE_SIZE);
+    limits->v1.maxTextureDimension3D = Get(gl, GL_MAX_3D_TEXTURE_SIZE);
+    limits->v1.maxTextureArrayLayers = Get(gl, GL_MAX_ARRAY_TEXTURE_LAYERS);
+
+    // Since we flatten bindings, leave maxBindGroups and maxBindingsPerBindGroup at the default.
+
+    limits->v1.maxDynamicUniformBuffersPerPipelineLayout = Get(gl, GL_MAX_UNIFORM_BUFFER_BINDINGS);
+    limits->v1.maxDynamicStorageBuffersPerPipelineLayout =
+        Get(gl, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS);
+    limits->v1.maxSampledTexturesPerShaderStage =
+        std::min(Get(gl, GL_MAX_TEXTURE_IMAGE_UNITS), Get(gl, GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS));
+    limits->v1.maxSamplersPerShaderStage = Get(gl, GL_MAX_TEXTURE_IMAGE_UNITS);
+    limits->v1.maxStorageBuffersPerShaderStage = Get(gl, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS);
+    // TODO(crbug.com/dawn/1834): Note that OpenGLES allows an implementation to have zero vertex
+    // image uniforms, so this isn't technically correct for vertex shaders.
+    limits->v1.maxStorageTexturesPerShaderStage = Get(gl, GL_MAX_FRAGMENT_IMAGE_UNIFORMS);
+
+    limits->v1.maxUniformBuffersPerShaderStage = Get(gl, GL_MAX_UNIFORM_BUFFER_BINDINGS);
+    limits->v1.maxUniformBufferBindingSize = Get(gl, GL_MAX_UNIFORM_BLOCK_SIZE);
+    limits->v1.maxStorageBufferBindingSize = Get(gl, GL_MAX_SHADER_STORAGE_BLOCK_SIZE);
+
+    limits->v1.minUniformBufferOffsetAlignment = Get(gl, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT);
+    limits->v1.minStorageBufferOffsetAlignment = Get(gl, GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT);
+    limits->v1.maxVertexBuffers = Get(gl, GL_MAX_VERTEX_ATTRIB_BINDINGS);
+    limits->v1.maxBufferSize = kAssumedMaxBufferSize;
+    GLint maxVertexAttribs = Get(gl, GL_MAX_VERTEX_ATTRIBS);
+    limits->v1.maxVertexAttributes = limits->v1.maxVertexBuffers * maxVertexAttribs;
+    limits->v1.maxVertexBufferArrayStride = Get(gl, GL_MAX_VERTEX_ATTRIB_STRIDE);
+    limits->v1.maxInterStageShaderComponents = Get(gl, GL_MAX_VARYING_COMPONENTS);
+    limits->v1.maxInterStageShaderVariables = Get(gl, GL_MAX_VARYING_VECTORS);
+    limits->v1.maxColorAttachments =
+        std::min(Get(gl, GL_MAX_COLOR_ATTACHMENTS), Get(gl, GL_MAX_DRAW_BUFFERS));
+
+    // TODO(crbug.com/dawn/1834): determine if GL has an equivalent value here.
+    //    limits->v1.maxColorAttachmentBytesPerSample = WGPU_LIMIT_U32_UNDEFINED;
+
+    limits->v1.maxComputeWorkgroupStorageSize = Get(gl, GL_MAX_COMPUTE_SHARED_MEMORY_SIZE);
+    limits->v1.maxComputeInvocationsPerWorkgroup = Get(gl, GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS);
+    limits->v1.maxComputeWorkgroupSizeX = GetIndexed(gl, GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0);
+    limits->v1.maxComputeWorkgroupSizeY = GetIndexed(gl, GL_MAX_COMPUTE_WORK_GROUP_SIZE, 1);
+    limits->v1.maxComputeWorkgroupSizeZ = GetIndexed(gl, GL_MAX_COMPUTE_WORK_GROUP_SIZE, 2);
+    GLint v[3];
+    v[0] = GetIndexed(gl, GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0);
+    v[1] = GetIndexed(gl, GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1);
+    v[2] = GetIndexed(gl, GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2);
+    limits->v1.maxComputeWorkgroupsPerDimension = std::min(v[0], std::min(v[1], v[2]));
     return {};
 }
 
diff --git a/src/dawn/tests/end2end/MaxLimitTests.cpp b/src/dawn/tests/end2end/MaxLimitTests.cpp
index 9d3192f..eef687e 100644
--- a/src/dawn/tests/end2end/MaxLimitTests.cpp
+++ b/src/dawn/tests/end2end/MaxLimitTests.cpp
@@ -250,6 +250,9 @@
 
 // Test using the maximum number of dynamic uniform and storage buffers
 TEST_P(MaxLimitTests, MaxDynamicBuffers) {
+    // TODO(https://anglebug.com/8177) Causes assertion failure in ANGLE.
+    DAWN_SUPPRESS_TEST_IF(IsANGLE() && IsWindows());
+
     wgpu::Limits limits = GetSupportedLimits().limits;
 
     std::vector<wgpu::BindGroupLayoutEntry> bglEntries;