From 449f06985c69e1b18f2492b6dc47963a59e1bd5d Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Tue, 13 Sep 2022 19:35:03 +0200
Subject: [PATCH] glsl/glslang: move resources declaration to C file

This struct has a nasty habit of breaking whenever there's any upstream
change. Fortunately for us, however, the struct definition lives
entirely in its own file, allowing us to easily include it from C99
code, allowing us to use C99 designated initializers to make the code
robust against struct extensions.

Fixes: https://code.videolan.org/videolan/libplacebo/-/issues/225
---
 src/glsl/glslang.cc          | 110 -----------------------------
 src/glsl/glslang.h           |   6 ++
 src/glsl/glslang_resources.c | 132 +++++++++++++++++++++++++++++++++++
 src/meson.build              |   1 +
 4 files changed, 139 insertions(+), 110 deletions(-)
 create mode 100644 src/glsl/glslang_resources.c

diff --git a/src/glsl/glslang.cc b/src/glsl/glslang.cc
index 21f7ccb4..563d46c6 100644
--- a/src/glsl/glslang.cc
+++ b/src/glsl/glslang.cc
@@ -112,113 +112,3 @@ struct pl_glslang_res *pl_glslang_compile(const struct pl_glsl_version *glsl,
     delete prog;
     return res;
 }
-
-// Taken from glslang's examples, which apparently generally bases the choices
-// on OpenGL specification limits
-const TBuiltInResource DefaultTBuiltInResource = {
-    /* .MaxLights = */ 32,
-    /* .MaxClipPlanes = */ 6,
-    /* .MaxTextureUnits = */ 32,
-    /* .MaxTextureCoords = */ 32,
-    /* .MaxVertexAttribs = */ 64,
-    /* .MaxVertexUniformComponents = */ 4096,
-    /* .MaxVaryingFloats = */ 64,
-    /* .MaxVertexTextureImageUnits = */ 32,
-    /* .MaxCombinedTextureImageUnits = */ 80,
-    /* .MaxTextureImageUnits = */ 32,
-    /* .MaxFragmentUniformComponents = */ 4096,
-    /* .MaxDrawBuffers = */ 32,
-    /* .MaxVertexUniformVectors = */ 128,
-    /* .MaxVaryingVectors = */ 8,
-    /* .MaxFragmentUniformVectors = */ 16,
-    /* .MaxVertexOutputVectors = */ 16,
-    /* .MaxFragmentInputVectors = */ 15,
-    /* .MinProgramTexelOffset = */ -8,
-    /* .MaxProgramTexelOffset = */ 7,
-    /* .MaxClipDistances = */ 8,
-    /* .MaxComputeWorkGroupCountX = */ 65535,
-    /* .MaxComputeWorkGroupCountY = */ 65535,
-    /* .MaxComputeWorkGroupCountZ = */ 65535,
-    /* .MaxComputeWorkGroupSizeX = */ 1024,
-    /* .MaxComputeWorkGroupSizeY = */ 1024,
-    /* .MaxComputeWorkGroupSizeZ = */ 64,
-    /* .MaxComputeUniformComponents = */ 1024,
-    /* .MaxComputeTextureImageUnits = */ 16,
-    /* .MaxComputeImageUniforms = */ 8,
-    /* .MaxComputeAtomicCounters = */ 8,
-    /* .MaxComputeAtomicCounterBuffers = */ 1,
-    /* .MaxVaryingComponents = */ 60,
-    /* .MaxVertexOutputComponents = */ 64,
-    /* .MaxGeometryInputComponents = */ 64,
-    /* .MaxGeometryOutputComponents = */ 128,
-    /* .MaxFragmentInputComponents = */ 128,
-    /* .MaxImageUnits = */ 8,
-    /* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8,
-    /* .MaxCombinedShaderOutputResources = */ 8,
-    /* .MaxImageSamples = */ 0,
-    /* .MaxVertexImageUniforms = */ 0,
-    /* .MaxTessControlImageUniforms = */ 0,
-    /* .MaxTessEvaluationImageUniforms = */ 0,
-    /* .MaxGeometryImageUniforms = */ 0,
-    /* .MaxFragmentImageUniforms = */ 8,
-    /* .MaxCombinedImageUniforms = */ 8,
-    /* .MaxGeometryTextureImageUnits = */ 16,
-    /* .MaxGeometryOutputVertices = */ 256,
-    /* .MaxGeometryTotalOutputComponents = */ 1024,
-    /* .MaxGeometryUniformComponents = */ 1024,
-    /* .MaxGeometryVaryingComponents = */ 64,
-    /* .MaxTessControlInputComponents = */ 128,
-    /* .MaxTessControlOutputComponents = */ 128,
-    /* .MaxTessControlTextureImageUnits = */ 16,
-    /* .MaxTessControlUniformComponents = */ 1024,
-    /* .MaxTessControlTotalOutputComponents = */ 4096,
-    /* .MaxTessEvaluationInputComponents = */ 128,
-    /* .MaxTessEvaluationOutputComponents = */ 128,
-    /* .MaxTessEvaluationTextureImageUnits = */ 16,
-    /* .MaxTessEvaluationUniformComponents = */ 1024,
-    /* .MaxTessPatchComponents = */ 120,
-    /* .MaxPatchVertices = */ 32,
-    /* .MaxTessGenLevel = */ 64,
-    /* .MaxViewports = */ 16,
-    /* .MaxVertexAtomicCounters = */ 0,
-    /* .MaxTessControlAtomicCounters = */ 0,
-    /* .MaxTessEvaluationAtomicCounters = */ 0,
-    /* .MaxGeometryAtomicCounters = */ 0,
-    /* .MaxFragmentAtomicCounters = */ 8,
-    /* .MaxCombinedAtomicCounters = */ 8,
-    /* .MaxAtomicCounterBindings = */ 1,
-    /* .MaxVertexAtomicCounterBuffers = */ 0,
-    /* .MaxTessControlAtomicCounterBuffers = */ 0,
-    /* .MaxTessEvaluationAtomicCounterBuffers = */ 0,
-    /* .MaxGeometryAtomicCounterBuffers = */ 0,
-    /* .MaxFragmentAtomicCounterBuffers = */ 1,
-    /* .MaxCombinedAtomicCounterBuffers = */ 1,
-    /* .MaxAtomicCounterBufferSize = */ 16384,
-    /* .MaxTransformFeedbackBuffers = */ 4,
-    /* .MaxTransformFeedbackInterleavedComponents = */ 64,
-    /* .MaxCullDistances = */ 8,
-    /* .MaxCombinedClipAndCullDistances = */ 8,
-    /* .MaxSamples = */ 4,
-    /* .maxMeshOutputVerticesNV = */ 256,
-    /* .maxMeshOutputPrimitivesNV = */ 512,
-    /* .maxMeshWorkGroupSizeX_NV = */ 32,
-    /* .maxMeshWorkGroupSizeY_NV = */ 1,
-    /* .maxMeshWorkGroupSizeZ_NV = */ 1,
-    /* .maxTaskWorkGroupSizeX_NV = */ 32,
-    /* .maxTaskWorkGroupSizeY_NV = */ 1,
-    /* .maxTaskWorkGroupSizeZ_NV = */ 1,
-    /* .maxMeshViewCountNV = */ 4,
-    /* .maxDualSourceDrawBuffersEXT = */ 1,
-
-    /* .limits = */ {
-        /* .nonInductiveForLoops = */ 1,
-        /* .whileLoops = */ 1,
-        /* .doWhileLoops = */ 1,
-        /* .generalUniformIndexing = */ 1,
-        /* .generalAttributeMatrixVectorIndexing = */ 1,
-        /* .generalVaryingIndexing = */ 1,
-        /* .generalSamplerIndexing = */ 1,
-        /* .generalVariableIndexing = */ 1,
-        /* .generalConstantMatrixVectorIndexing = */ 1,
-    }
-};
diff --git a/src/glsl/glslang.h b/src/glsl/glslang.h
index e950420f..148232d5 100644
--- a/src/glsl/glslang.h
+++ b/src/glsl/glslang.h
@@ -20,6 +20,10 @@
 #include <stdlib.h>
 #include <stdbool.h>
 
+typedef struct TLimits TLimits;
+typedef struct TBuiltInResource TBuiltInResource;
+#include <glslang/Include/ResourceLimits.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -45,6 +49,8 @@ struct pl_glslang_res *pl_glslang_compile(const struct pl_glsl_version *glsl,
                                           enum glsl_shader_stage stage,
                                           const char *shader);
 
+extern const TBuiltInResource DefaultTBuiltInResource;
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/glsl/glslang_resources.c b/src/glsl/glslang_resources.c
new file mode 100644
index 00000000..a111c15d
--- /dev/null
+++ b/src/glsl/glslang_resources.c
@@ -0,0 +1,132 @@
+/*
+ * This file is part of libplacebo.
+ *
+ * libplacebo is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * libplacebo is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with libplacebo. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "glslang.h"
+
+// Taken from glslang's examples, which apparently generally bases the choices
+// on OpenGL specification limits
+//
+// Note: This lives in a separate file so we can compile this struct using C99
+// designated initializers instead of using C++ struct initializers, because
+// the latter will break on every upstream struct extension.
+const TBuiltInResource DefaultTBuiltInResource = {
+    .maxLights = 32,
+    .maxClipPlanes = 6,
+    .maxTextureUnits = 32,
+    .maxTextureCoords = 32,
+    .maxVertexAttribs = 64,
+    .maxVertexUniformComponents = 4096,
+    .maxVaryingFloats = 64,
+    .maxVertexTextureImageUnits = 32,
+    .maxCombinedTextureImageUnits = 80,
+    .maxTextureImageUnits = 32,
+    .maxFragmentUniformComponents = 4096,
+    .maxDrawBuffers = 32,
+    .maxVertexUniformVectors = 128,
+    .maxVaryingVectors = 8,
+    .maxFragmentUniformVectors = 16,
+    .maxVertexOutputVectors = 16,
+    .maxFragmentInputVectors = 15,
+    .minProgramTexelOffset = -8,
+    .maxProgramTexelOffset = 7,
+    .maxClipDistances = 8,
+    .maxComputeWorkGroupCountX = 65535,
+    .maxComputeWorkGroupCountY = 65535,
+    .maxComputeWorkGroupCountZ = 65535,
+    .maxComputeWorkGroupSizeX = 1024,
+    .maxComputeWorkGroupSizeY = 1024,
+    .maxComputeWorkGroupSizeZ = 64,
+    .maxComputeUniformComponents = 1024,
+    .maxComputeTextureImageUnits = 16,
+    .maxComputeImageUniforms = 8,
+    .maxComputeAtomicCounters = 8,
+    .maxComputeAtomicCounterBuffers = 1,
+    .maxVaryingComponents = 60,
+    .maxVertexOutputComponents = 64,
+    .maxGeometryInputComponents = 64,
+    .maxGeometryOutputComponents = 128,
+    .maxFragmentInputComponents = 128,
+    .maxImageUnits = 8,
+    .maxCombinedImageUnitsAndFragmentOutputs = 8,
+    .maxCombinedShaderOutputResources = 8,
+    .maxImageSamples = 0,
+    .maxVertexImageUniforms = 0,
+    .maxTessControlImageUniforms = 0,
+    .maxTessEvaluationImageUniforms = 0,
+    .maxGeometryImageUniforms = 0,
+    .maxFragmentImageUniforms = 8,
+    .maxCombinedImageUniforms = 8,
+    .maxGeometryTextureImageUnits = 16,
+    .maxGeometryOutputVertices = 256,
+    .maxGeometryTotalOutputComponents = 1024,
+    .maxGeometryUniformComponents = 1024,
+    .maxGeometryVaryingComponents = 64,
+    .maxTessControlInputComponents = 128,
+    .maxTessControlOutputComponents = 128,
+    .maxTessControlTextureImageUnits = 16,
+    .maxTessControlUniformComponents = 1024,
+    .maxTessControlTotalOutputComponents = 4096,
+    .maxTessEvaluationInputComponents = 128,
+    .maxTessEvaluationOutputComponents = 128,
+    .maxTessEvaluationTextureImageUnits = 16,
+    .maxTessEvaluationUniformComponents = 1024,
+    .maxTessPatchComponents = 120,
+    .maxPatchVertices = 32,
+    .maxTessGenLevel = 64,
+    .maxViewports = 16,
+    .maxVertexAtomicCounters = 0,
+    .maxTessControlAtomicCounters = 0,
+    .maxTessEvaluationAtomicCounters = 0,
+    .maxGeometryAtomicCounters = 0,
+    .maxFragmentAtomicCounters = 8,
+    .maxCombinedAtomicCounters = 8,
+    .maxAtomicCounterBindings = 1,
+    .maxVertexAtomicCounterBuffers = 0,
+    .maxTessControlAtomicCounterBuffers = 0,
+    .maxTessEvaluationAtomicCounterBuffers = 0,
+    .maxGeometryAtomicCounterBuffers = 0,
+    .maxFragmentAtomicCounterBuffers = 1,
+    .maxCombinedAtomicCounterBuffers = 1,
+    .maxAtomicCounterBufferSize = 16384,
+    .maxTransformFeedbackBuffers = 4,
+    .maxTransformFeedbackInterleavedComponents = 64,
+    .maxCullDistances = 8,
+    .maxCombinedClipAndCullDistances = 8,
+    .maxSamples = 4,
+    .maxMeshOutputVerticesNV = 256,
+    .maxMeshOutputPrimitivesNV = 512,
+    .maxMeshWorkGroupSizeX_NV = 32,
+    .maxMeshWorkGroupSizeY_NV = 1,
+    .maxMeshWorkGroupSizeZ_NV = 1,
+    .maxTaskWorkGroupSizeX_NV = 32,
+    .maxTaskWorkGroupSizeY_NV = 1,
+    .maxTaskWorkGroupSizeZ_NV = 1,
+    .maxMeshViewCountNV = 4,
+    .maxDualSourceDrawBuffersEXT = 1,
+
+    .limits = {
+        .nonInductiveForLoops = 1,
+        .whileLoops = 1,
+        .doWhileLoops = 1,
+        .generalUniformIndexing = 1,
+        .generalAttributeMatrixVectorIndexing = 1,
+        .generalVaryingIndexing = 1,
+        .generalSamplerIndexing = 1,
+        .generalVariableIndexing = 1,
+        .generalConstantMatrixVectorIndexing = 1,
+    },
+};
diff --git a/src/meson.build b/src/meson.build
index d3eaccfb..7de18086 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -232,6 +232,7 @@ components = [
     'name': 'glslang',
     'deps': glslang,
     'srcs': [ 'glsl/glslang.cc',
+              'glsl/glslang_resources.c',
               'glsl/spirv_glslang.c',
             ],
   }, {
