[Piglit] [PATCH] Test varying structs in GLSL ES 3.00.

Paul Berry stereotype441 at gmail.com
Mon Jan 21 15:01:19 PST 2013


This patch adds the following GLSL ES 3.00 tests:

- varying-struct-basic: a simple test case involving a single varying
  struct.

- varying-struct-arrays: exercise complex interactions between structs
  and arrays in varyings.

- varying-struct-copy-vs: exercise corner cases where a struct
  internal to a vertex shader is copied to a varying struct.

- varying-struct-copy-fs: exercise corner cases where a varying struct
  is copied to a struct internal to a fragment shader.

- varying-struct-interpolation: verify that interpolation qualifiers
  "flat" and "smooth" are inherited by the fields within a varying
  struct.

- varying-struct-centroid: verify that the interpolation qualifier
  "centroid" is inherited by the fields within a varying struct.

Note that "centroid" is tested separately from the other interpolation
qualifiers since MSAA is required to verify that it works correctly,
so it can't be tested with a simple shader_runner test.
---

These are the piglit tests I used to validate my recent Mesa
patch series "glsl: Add support for varying structs."  They're a
little overzealous considering the simplicity of the
implementation, but I wanted to have our bases covered in case we
come back later and replace it with a more complex approach that
involves "flattening" structured varyings.

Once these tests are reviewed I plan to submit a follow-up patch
that ports them to GLSL 1.50.

Due to a piglit framework bug, these tests won't run correctly unless
Tom Gall's patch "shader_runner regression with gles" (which is still
being code reviewed) is also applied.


 tests/all.tests                                    |   2 +-
 tests/spec/CMakeLists.txt                          |   1 +
 tests/spec/glsl-es-3.00/CMakeLists.txt             |   1 +
 .../glsl-es-3.00/execution/CMakeLists.gles3.txt    |   8 +
 tests/spec/glsl-es-3.00/execution/CMakeLists.txt   |   1 +
 .../execution/varying-struct-arrays.shader_test    | 236 +++++++++++++++++++++
 .../execution/varying-struct-basic.shader_test     | 114 ++++++++++
 .../execution/varying-struct-centroid.c            | 199 +++++++++++++++++
 .../execution/varying-struct-copy-fs.shader_test   | 112 ++++++++++
 .../execution/varying-struct-copy-vs.shader_test   | 137 ++++++++++++
 .../varying-struct-interpolation.shader_test       |  86 ++++++++
 11 files changed, 896 insertions(+), 1 deletion(-)
 create mode 100644 tests/spec/glsl-es-3.00/CMakeLists.txt
 create mode 100644 tests/spec/glsl-es-3.00/execution/CMakeLists.gles3.txt
 create mode 100644 tests/spec/glsl-es-3.00/execution/CMakeLists.txt
 create mode 100644 tests/spec/glsl-es-3.00/execution/varying-struct-arrays.shader_test
 create mode 100644 tests/spec/glsl-es-3.00/execution/varying-struct-basic.shader_test
 create mode 100644 tests/spec/glsl-es-3.00/execution/varying-struct-centroid.c
 create mode 100644 tests/spec/glsl-es-3.00/execution/varying-struct-copy-fs.shader_test
 create mode 100644 tests/spec/glsl-es-3.00/execution/varying-struct-copy-vs.shader_test
 create mode 100644 tests/spec/glsl-es-3.00/execution/varying-struct-interpolation.shader_test

diff --git a/tests/all.tests b/tests/all.tests
index 0e3eb37..f6eacc6 100644
--- a/tests/all.tests
+++ b/tests/all.tests
@@ -836,7 +836,7 @@ import_glsl_parser_tests(spec['glsl-es-3.00'],
 add_shader_test_dir(spec['glsl-es-3.00'],
 		    os.path.join(testsDir, 'spec', 'glsl-es-3.00'),
 		    recursive=True)
-
+add_concurrent_test(spec['glsl-es-3.00']['execution'], 'varying-struct-centroid_gles3')
 
 
 # Group AMD_conservative_depth
diff --git a/tests/spec/CMakeLists.txt b/tests/spec/CMakeLists.txt
index a4342b7..df87181 100644
--- a/tests/spec/CMakeLists.txt
+++ b/tests/spec/CMakeLists.txt
@@ -48,6 +48,7 @@ add_subdirectory (glsl-1.10)
 add_subdirectory (glsl-1.20)
 add_subdirectory (glsl-1.30)
 add_subdirectory (glsl-1.40)
+add_subdirectory (glsl-es-3.00)
 add_subdirectory (gl-1.0)
 add_subdirectory (gl-2.0)
 add_subdirectory (gl-2.1)
diff --git a/tests/spec/glsl-es-3.00/CMakeLists.txt b/tests/spec/glsl-es-3.00/CMakeLists.txt
new file mode 100644
index 0000000..bb76f08
--- /dev/null
+++ b/tests/spec/glsl-es-3.00/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory (execution)
diff --git a/tests/spec/glsl-es-3.00/execution/CMakeLists.gles3.txt b/tests/spec/glsl-es-3.00/execution/CMakeLists.gles3.txt
new file mode 100644
index 0000000..42f6f11
--- /dev/null
+++ b/tests/spec/glsl-es-3.00/execution/CMakeLists.gles3.txt
@@ -0,0 +1,8 @@
+link_libraries(
+	piglitutil_${piglit_target_api}
+	${OPENGL_gles2_LIBRARY}
+	)
+
+piglit_add_executable (varying-struct-centroid_${piglit_target_api} varying-struct-centroid.c)
+
+# vim: ft=cmake:
diff --git a/tests/spec/glsl-es-3.00/execution/CMakeLists.txt b/tests/spec/glsl-es-3.00/execution/CMakeLists.txt
new file mode 100644
index 0000000..144a306
--- /dev/null
+++ b/tests/spec/glsl-es-3.00/execution/CMakeLists.txt
@@ -0,0 +1 @@
+piglit_include_target_api()
diff --git a/tests/spec/glsl-es-3.00/execution/varying-struct-arrays.shader_test b/tests/spec/glsl-es-3.00/execution/varying-struct-arrays.shader_test
new file mode 100644
index 0000000..5248fb8
--- /dev/null
+++ b/tests/spec/glsl-es-3.00/execution/varying-struct-arrays.shader_test
@@ -0,0 +1,236 @@
+# Test that varying structs work properly in conjunction with arrays.
+#
+# From the GLSL ES 3.00 specification, section 4.3.4 ("Input Variables"):
+#
+#     Fragment inputs can only be signed and unsigned integers and
+#     integer vectors, float, floating-point vectors, matrices, or
+#     arrays or structures of these.
+#
+# And from section 4.3.6 ("Output Variables"):
+#
+#     Vertex output variables ... can only be float, floating-point
+#     vectors, matrices, signed or unsigned integers or integer
+#     vectors, or arrays or structures of any these.
+#
+# This test verifies the proper functioning of varyings whose types
+# are a struct containing an array, an array of structs, and various
+# complex combinations of arrays and structs.
+#
+# Note: chapter 11 of the GLSL ES 3.00 spec ("Counting of Inputs and
+# Outputs") specifies a packing algorithm which constitutes a minimum
+# requirement for when a set of varyings must be supported by a
+# conformant implementation.  Although that chapter has not yet been
+# updated to reflect varying structs, Khronos's internal bugzilla
+# indicates that structs should be flattened before applying the
+# packing algorithm
+# (https://cvs.khronos.org/bugzilla/show_bug.cgi?id=9828).  The
+# varyings in this test flatten as follows:
+#
+# float     s1.f;             // A
+# float[3]  s1.af[];          // B
+# float[3]  as1[].f;          // C
+# float[9]  as1[].af[];       // D
+# float     s2.s1.f;          // E
+# float[3]  s2.s1.af[];       // F
+# float[2]  s2.as1[].f;       // G
+# float[6]  s2.as1[].af[];    // H
+# float[2]  as2[].s1.f;       // I
+# float[6]  as2[].s1.af[];    // J
+# float[4]  as2[].as1[].f;    // K
+# float[12] as2[].as1[].af[]; // L
+#
+# And the flattened varyings would in turn be packed like so:
+#    x y z w
+#  0 L D J G
+#  1 L D J G
+#  2 L D J I
+#  3 L D J I
+#  4 L D J
+#  5 L D J
+#  6 L D B
+#  7 L D B
+#  8 L D B
+#  9 L H C
+# 10 L H C
+# 11 L H C
+# 12 K H F
+# 13 K H F
+# 14 K H F
+# 15 K A E
+
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+
+[vertex shader]
+#version 300 es
+
+uniform float ref;
+
+in vec4 vertex;
+struct S1
+{
+	float f;
+	float af[3];
+};
+struct S2
+{
+	S1 s1;
+	S1 as1[2];
+};
+out S1 s1;
+out S1 as1[3];
+out S2 s2;
+out S2 as2[2];
+
+void main()
+{
+	gl_Position = vertex;
+	float f = ref;
+	s1.f = f++;
+	s1.af[0] = f++;
+	s1.af[1] = f++;
+	s1.af[2] = f++;
+	as1[0].f = f++;
+	as1[0].af[0] = f++;
+	as1[0].af[1] = f++;
+	as1[0].af[2] = f++;
+	as1[1].f = f++;
+	as1[1].af[0] = f++;
+	as1[1].af[1] = f++;
+	as1[1].af[2] = f++;
+	as1[2].f = f++;
+	as1[2].af[0] = f++;
+	as1[2].af[1] = f++;
+	as1[2].af[2] = f++;
+	s2.s1.f = f++;
+	s2.s1.af[0] = f++;
+	s2.s1.af[1] = f++;
+	s2.s1.af[2] = f++;
+	s2.as1[0].f = f++;
+	s2.as1[0].af[0] = f++;
+	s2.as1[0].af[1] = f++;
+	s2.as1[0].af[2] = f++;
+	s2.as1[1].f = f++;
+	s2.as1[1].af[0] = f++;
+	s2.as1[1].af[1] = f++;
+	s2.as1[1].af[2] = f++;
+	as2[0].s1.f = f++;
+	as2[0].s1.af[0] = f++;
+	as2[0].s1.af[1] = f++;
+	as2[0].s1.af[2] = f++;
+	as2[0].as1[0].f = f++;
+	as2[0].as1[0].af[0] = f++;
+	as2[0].as1[0].af[1] = f++;
+	as2[0].as1[0].af[2] = f++;
+	as2[0].as1[1].f = f++;
+	as2[0].as1[1].af[0] = f++;
+	as2[0].as1[1].af[1] = f++;
+	as2[0].as1[1].af[2] = f++;
+	as2[1].s1.f = f++;
+	as2[1].s1.af[0] = f++;
+	as2[1].s1.af[1] = f++;
+	as2[1].s1.af[2] = f++;
+	as2[1].as1[0].f = f++;
+	as2[1].as1[0].af[0] = f++;
+	as2[1].as1[0].af[1] = f++;
+	as2[1].as1[0].af[2] = f++;
+	as2[1].as1[1].f = f++;
+	as2[1].as1[1].af[0] = f++;
+	as2[1].as1[1].af[1] = f++;
+	as2[1].as1[1].af[2] = f++;
+}
+
+[fragment shader]
+#version 300 es
+
+uniform float ref;
+
+struct S1
+{
+	float f;
+	float af[3];
+};
+struct S2
+{
+	S1 s1;
+	S1 as1[2];
+};
+in S1 s1;
+in S1 as1[3];
+in S2 s2;
+in S2 as2[2];
+out vec4 color;
+
+#define CHECK(value, expected) \
+	if (distance(value, expected) > 0.00001) \
+		failed = true
+
+void main()
+{
+	bool failed = false;
+	float f = ref;
+
+	CHECK(s1.f, f++);
+	CHECK(s1.af[0], f++);
+	CHECK(s1.af[1], f++);
+	CHECK(s1.af[2], f++);
+	CHECK(as1[0].f, f++);
+	CHECK(as1[0].af[0], f++);
+	CHECK(as1[0].af[1], f++);
+	CHECK(as1[0].af[2], f++);
+	CHECK(as1[1].f, f++);
+	CHECK(as1[1].af[0], f++);
+	CHECK(as1[1].af[1], f++);
+	CHECK(as1[1].af[2], f++);
+	CHECK(as1[2].f, f++);
+	CHECK(as1[2].af[0], f++);
+	CHECK(as1[2].af[1], f++);
+	CHECK(as1[2].af[2], f++);
+	CHECK(s2.s1.f, f++);
+	CHECK(s2.s1.af[0], f++);
+	CHECK(s2.s1.af[1], f++);
+	CHECK(s2.s1.af[2], f++);
+	CHECK(s2.as1[0].f, f++);
+	CHECK(s2.as1[0].af[0], f++);
+	CHECK(s2.as1[0].af[1], f++);
+	CHECK(s2.as1[0].af[2], f++);
+	CHECK(s2.as1[1].f, f++);
+	CHECK(s2.as1[1].af[0], f++);
+	CHECK(s2.as1[1].af[1], f++);
+	CHECK(s2.as1[1].af[2], f++);
+	CHECK(as2[0].s1.f, f++);
+	CHECK(as2[0].s1.af[0], f++);
+	CHECK(as2[0].s1.af[1], f++);
+	CHECK(as2[0].s1.af[2], f++);
+	CHECK(as2[0].as1[0].f, f++);
+	CHECK(as2[0].as1[0].af[0], f++);
+	CHECK(as2[0].as1[0].af[1], f++);
+	CHECK(as2[0].as1[0].af[2], f++);
+	CHECK(as2[0].as1[1].f, f++);
+	CHECK(as2[0].as1[1].af[0], f++);
+	CHECK(as2[0].as1[1].af[1], f++);
+	CHECK(as2[0].as1[1].af[2], f++);
+	CHECK(as2[1].s1.f, f++);
+	CHECK(as2[1].s1.af[0], f++);
+	CHECK(as2[1].s1.af[1], f++);
+	CHECK(as2[1].s1.af[2], f++);
+	CHECK(as2[1].as1[0].f, f++);
+	CHECK(as2[1].as1[0].af[0], f++);
+	CHECK(as2[1].as1[0].af[1], f++);
+	CHECK(as2[1].as1[0].af[2], f++);
+	CHECK(as2[1].as1[1].f, f++);
+	CHECK(as2[1].as1[1].af[0], f++);
+	CHECK(as2[1].as1[1].af[1], f++);
+	CHECK(as2[1].as1[1].af[2], f++);
+
+	if (failed)
+		color = vec4(1.0, 0.0, 0.0, 1.0);
+	else
+		color = vec4(0.0, 1.0, 0.0, 1.0);
+}
+
+[test]
+uniform float ref 137.035999074
+draw rect -1 -1 2 2
+probe all rgba 0.0 1.0 0.0 1.0
diff --git a/tests/spec/glsl-es-3.00/execution/varying-struct-basic.shader_test b/tests/spec/glsl-es-3.00/execution/varying-struct-basic.shader_test
new file mode 100644
index 0000000..4ecfdf6
--- /dev/null
+++ b/tests/spec/glsl-es-3.00/execution/varying-struct-basic.shader_test
@@ -0,0 +1,114 @@
+# Test that varying structs work properly.
+#
+# From the GLSL ES 3.00 specification, section 4.3.4 ("Input Variables"):
+#
+#     Fragment inputs can only be signed and unsigned integers and
+#     integer vectors, float, floating-point vectors, matrices, or
+#     arrays or structures of these.
+#
+# And from section 4.3.6 ("Output Variables"):
+#
+#     Vertex output variables ... can only be float, floating-point
+#     vectors, matrices, signed or unsigned integers or integer
+#     vectors, or arrays or structures of any these.
+#
+# This test verifies basic functionality of varying structs using a
+# varying struct containing a variety of types.
+
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+
+[vertex shader]
+#version 300 es
+
+uniform float ref;
+
+in vec4 vertex;
+struct Foo
+{
+	mat4 a;
+	mat3 b;
+	mat2 c;
+	vec4 d;
+	vec3 e;
+	vec2 f;
+	float g;
+};
+out Foo foo;
+
+void main()
+{
+	gl_Position = vertex;
+
+	foo.a = mat4(ref,        ref +  1.0, ref +  2.0, ref +  3.0,
+		     ref +  4.0, ref +  5.0, ref +  6.0, ref +  7.0,
+		     ref +  8.0, ref +  9.0, ref + 10.0, ref + 11.0,
+		     ref + 12.0, ref + 13.0, ref + 14.0, ref + 15.0);
+
+	foo.b = mat3(ref + 16.0, ref + 17.0, ref + 18.0,
+		     ref + 19.0, ref + 20.0, ref + 21.0,
+		     ref + 22.0, ref + 23.0, ref + 24.0);
+
+	foo.c = mat2(ref + 25.0, ref + 26.0,
+		     ref + 27.0, ref + 28.0);
+
+	foo.d = vec4(ref + 29.0, ref + 30.0, ref + 31.0, ref + 32.0);
+	foo.e = vec3(ref + 33.0, ref + 34.0, ref + 35.0);
+	foo.f = vec2(ref + 36.0, ref + 37.0);
+	foo.g = ref + 38.0;
+}
+
+[fragment shader]
+#version 300 es
+
+uniform float ref;
+
+struct Foo
+{
+	mat4 a;
+	mat3 b;
+	mat2 c;
+	vec4 d;
+	vec3 e;
+	vec2 f;
+	float g;
+};
+in Foo foo;
+out vec4 color;
+
+#define CHECK(value, expected) \
+	if (distance(value, expected) > 0.00001) \
+		failed = true
+
+void main()
+{
+	bool failed = false;
+
+	CHECK(foo.a[0], vec4(ref,        ref +  1.0, ref +  2.0, ref +  3.0));
+	CHECK(foo.a[1], vec4(ref +  4.0, ref +  5.0, ref +  6.0, ref +  7.0));
+	CHECK(foo.a[2], vec4(ref +  8.0, ref +  9.0, ref + 10.0, ref + 11.0));
+	CHECK(foo.a[3], vec4(ref + 12.0, ref + 13.0, ref + 14.0, ref + 15.0));
+
+	CHECK(foo.b[0], vec3(ref + 16.0, ref + 17.0, ref + 18.0));
+	CHECK(foo.b[1], vec3(ref + 19.0, ref + 20.0, ref + 21.0));
+	CHECK(foo.b[2], vec3(ref + 22.0, ref + 23.0, ref + 24.0));
+
+	CHECK(foo.c[0], vec2(ref + 25.0, ref + 26.0));
+	CHECK(foo.c[1], vec2(ref + 27.0, ref + 28.0));
+
+	CHECK(foo.d, vec4(ref + 29.0, ref + 30.0, ref + 31.0, ref + 32.0));
+	CHECK(foo.e, vec3(ref + 33.0, ref + 34.0, ref + 35.0));
+	CHECK(foo.f, vec2(ref + 36.0, ref + 37.0));
+	CHECK(foo.g, ref + 38.0);
+
+	if (failed)
+		color = vec4(1.0, 0.0, 0.0, 1.0);
+	else
+		color = vec4(0.0, 1.0, 0.0, 1.0);
+}
+
+[test]
+uniform float ref 137.035999074
+draw rect -1 -1 2 2
+probe all rgba 0.0 1.0 0.0 1.0
diff --git a/tests/spec/glsl-es-3.00/execution/varying-struct-centroid.c b/tests/spec/glsl-es-3.00/execution/varying-struct-centroid.c
new file mode 100644
index 0000000..301a19c
--- /dev/null
+++ b/tests/spec/glsl-es-3.00/execution/varying-struct-centroid.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file varying-struct-centroid.c
+ *
+ * Test that varying structs work properly.
+ *
+ * From the GLSL ES 3.00 specification, section 4.3.4 ("Input Variables"):
+ *
+ *     Fragment inputs can only be signed and unsigned integers and
+ *     integer vectors, float, floating-point vectors, matrices, or
+ *     arrays or structures of these.
+ *
+ * And from section 4.3.6 ("Output Variables"):
+ *
+ *     Vertex output variables ... can only be float, floating-point
+ *     vectors, matrices, signed or unsigned integers or integer
+ *     vectors, or arrays or structures of any these.
+ *
+ * This tests that the elements of varying structs properly respect the
+ * "centroid" keyword.
+ *
+ * The test functions as follows:
+ *
+ * - Create a vertex and fragment shader whose varyings are (1) a vec4
+ *   using normal interpolation, (2) a vec4 using centroid
+ *   interpolation, (3) a struct using normal interpolation, and (4) a
+ *   struct using centroid interpolation.  Both structs contain a
+ *   single vec4.  The fragment shader compares the vec4's inside the
+ *   structs with the corresponding non-structured vec4's, and outputs
+ *   red or green depending whether they match.
+ *
+ * - Create a multisampled renderbuffer.
+ *
+ * - Draw a rectangle that covers the entire renderbuffer.
+ *
+ * - Draw a triangle over the top of this rectangle, where the
+ *   coordinates have been chosen to ensure that at least some pixels
+ *   are less than 50% covered (these pixels will have their
+ *   centroid-interpolated varyings differ from their
+ *   non-centroid-interpolated varyings since the center of the pixel
+ *   is not covered).
+ *
+ * - Use a blit to downsample the image to the screen.
+ *
+ * - Check that all pixels are green.
+ */
+
+#include "piglit-util-gl-common.h"
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+	config.supports_gl_es_version = 30;
+	config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_ALPHA | PIGLIT_GL_VISUAL_DOUBLE;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+static const char vs_text[] =
+	"#version 300 es\n"
+	"in vec4 vertex;\n"
+	"struct Foo {\n"
+	"  vec4 v;\n"
+	"};\n"
+	"out Foo foo;\n"
+	"centroid out Foo foo_centroid;\n"
+	"out vec4 ref;\n"
+	"centroid out vec4 ref_centroid;\n"
+	"void main()\n"
+	"{\n"
+	"  gl_Position = vertex;\n"
+	"  foo.v = vertex;\n"
+	"  foo_centroid.v = vertex;\n"
+	"  ref = vertex;\n"
+	"  ref_centroid = vertex;\n"
+	"}\n";
+
+static const char fs_text[] =
+	"#version 300 es\n"
+	"struct Foo {\n"
+	"  vec4 v;\n"
+	"};\n"
+	"in Foo foo;\n"
+	"centroid in Foo foo_centroid;\n"
+	"in vec4 ref;\n"
+	"centroid in vec4 ref_centroid;\n"
+	"out vec4 color;\n"
+	"void main()\n"
+	"{\n"
+	"  if (distance(foo.v, ref) > 0.00001\n"
+	"      || distance(foo_centroid.v, ref_centroid) > 0.00001) {\n"
+	"    color = vec4(1.0, 0.0, 0.0, 1.0);\n"
+	"  } else {\n"
+	"    color = vec4(0.0, 1.0, 0.0, 1.0);\n"
+	"  }\n"
+	"}\n";
+
+
+static GLuint prog;
+static GLuint fbo;
+static GLuint rb;
+
+
+void
+piglit_init(int argc, char **argv)
+{
+	/* Create the shaders */
+	prog = glCreateProgram();
+	glAttachShader(prog, piglit_compile_shader_text(GL_VERTEX_SHADER,
+							vs_text));
+	glAttachShader(prog, piglit_compile_shader_text(GL_FRAGMENT_SHADER,
+							fs_text));
+	glBindAttribLocation(prog, PIGLIT_ATTRIB_POS, "vertex");
+	glLinkProgram(prog);
+	if (!piglit_link_check_status(prog))
+		piglit_report_result(PIGLIT_FAIL);
+
+	/* Create the multisampled framebuffer */
+	glGenFramebuffers(1, &fbo);
+	glGenRenderbuffers(1, &rb);
+	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
+	glBindRenderbuffer(GL_RENDERBUFFER, rb);
+	glRenderbufferStorageMultisample(GL_RENDERBUFFER,
+					 4 /* samples */,
+					 GL_RGBA8 /* internalformat */,
+					 piglit_width, piglit_height);
+	glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+				  GL_RENDERBUFFER, rb);
+	if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER)
+	    != GL_FRAMEBUFFER_COMPLETE) {
+		printf("Framebuffer incomplete\n");
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		piglit_report_result(PIGLIT_FAIL);
+}
+
+
+enum piglit_result
+piglit_display(void)
+{
+	const float verts[3][4] = {
+		{ -1.0, -1.0, 0.0, 1.0 },
+		{ -0.9,  1.0, 0.0, 1.0 },
+		{  1.0,  0.8, 0.0, 1.0 }
+	};
+	const float green[4] = { 0.0, 1.0, 0.0, 1.0 };
+	bool pass = true;
+
+	/* Set up to draw into the multisampled renderbuffer */
+	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
+	glClear(GL_COLOR_BUFFER_BIT);
+	glUseProgram(prog);
+
+	/* Draw a rectangle covering the entire buffer */
+	piglit_draw_rect(-1, -1, 2, 2);
+
+	/* Draw a triangle where some samples are <50% covered */
+	glVertexAttribPointer(PIGLIT_ATTRIB_POS, 4, GL_FLOAT, GL_FALSE, 0,
+			      verts);
+	glEnableVertexAttribArray(PIGLIT_ATTRIB_POS);
+	glDrawArrays(GL_TRIANGLES, 0, 3);
+
+	/* Blit to the main window to downsample the image */
+	glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
+	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, piglit_winsys_fbo);
+	glBlitFramebuffer(0, 0, piglit_width, piglit_height,
+			  0, 0, piglit_width, piglit_height,
+			  GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+	/* Check that the image is all green */
+	glBindFramebuffer(GL_READ_FRAMEBUFFER, piglit_winsys_fbo);
+	pass = piglit_probe_rect_rgba(0, 0, piglit_width, piglit_height,
+				      green) && pass;
+
+	piglit_present_results();
+	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
diff --git a/tests/spec/glsl-es-3.00/execution/varying-struct-copy-fs.shader_test b/tests/spec/glsl-es-3.00/execution/varying-struct-copy-fs.shader_test
new file mode 100644
index 0000000..44fa96c
--- /dev/null
+++ b/tests/spec/glsl-es-3.00/execution/varying-struct-copy-fs.shader_test
@@ -0,0 +1,112 @@
+# Test that varying structs work properly.
+#
+# From the GLSL ES 3.00 specification, section 4.3.4 ("Input Variables"):
+#
+#     Fragment inputs can only be signed and unsigned integers and
+#     integer vectors, float, floating-point vectors, matrices, or
+#     arrays or structures of these.
+#
+# And from section 4.3.6 ("Output Variables"):
+#
+#     Vertex output variables ... can only be float, floating-point
+#     vectors, matrices, signed or unsigned integers or integer
+#     vectors, or arrays or structures of any these.
+#
+# This tests that varying structs work when copied to other structs
+# within the fragment shader, including:
+#
+# - A struct delivered to a function via an "in" parameter, or
+# - A local struct within the shader.
+#
+# These cases are important because in implementations that flatten
+# varying structs to their individual components, these uses of
+# varying structs are likely to take different code paths than uses of
+# varying structs that access the structure elements one at a time.
+
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+
+[vertex shader]
+#version 300 es
+
+in vec4 vertex;
+struct Foo
+{
+	float a;
+	vec2 b;
+	vec3 c;
+	vec4 d;
+};
+out Foo foo;
+uniform int subtest;
+
+void main()
+{
+	gl_Position = vertex;
+
+	float ref = 100.0 * float(subtest);
+
+	foo.a = ref + 1.0;
+	foo.b = vec2(ref + 2.0, ref + 3.0);
+	foo.c = vec3(ref + 4.0, ref + 5.0, ref + 6.0);
+	foo.d = vec4(ref + 7.0, ref + 8.0, ref + 9.0, ref + 10.0);
+}
+
+[fragment shader]
+#version 300 es
+
+uniform int subtest;
+
+struct Foo
+{
+	float a;
+	vec2 b;
+	vec3 c;
+	vec4 d;
+};
+in Foo foo;
+out vec4 color;
+
+#define CHECK(value, expected) \
+	if (distance(value, expected) > 0.00001) \
+		failed = true
+
+void check_fn(in Foo p, inout bool failed)
+{
+	CHECK(p.a, 101.0);
+	CHECK(p.b, vec2(102.0, 103.0));
+	CHECK(p.c, vec3(104.0, 105.0, 106.0));
+	CHECK(p.d, vec4(107.0, 108.0, 109.0, 110.0));
+}
+
+void main()
+{
+	bool failed = false;
+	Foo local_foo;
+
+	switch (subtest) {
+	case 0:
+		local_foo = foo;
+		CHECK(local_foo.a, 1.0);
+		CHECK(local_foo.b, vec2(2.0, 3.0));
+		CHECK(local_foo.c, vec3(4.0, 5.0, 6.0));
+		CHECK(local_foo.d, vec4(7.0, 8.0, 9.0, 10.0));
+		break;
+	case 1:
+		check_fn(foo, failed);
+		break;
+	}
+
+	if (failed)
+		color = vec4(1.0, 0.0, 0.0, 1.0);
+	else
+		color = vec4(0.0, 1.0, 0.0, 1.0);
+}
+
+[test]
+uniform int subtest 0
+draw rect -1 -1 2 1
+uniform int subtest 1
+draw rect -1 0 2 1
+probe all rgba 0.0 1.0 0.0 1.0
diff --git a/tests/spec/glsl-es-3.00/execution/varying-struct-copy-vs.shader_test b/tests/spec/glsl-es-3.00/execution/varying-struct-copy-vs.shader_test
new file mode 100644
index 0000000..0924a0e
--- /dev/null
+++ b/tests/spec/glsl-es-3.00/execution/varying-struct-copy-vs.shader_test
@@ -0,0 +1,137 @@
+# Test that varying structs work properly.
+#
+# From the GLSL ES 3.00 specification, section 4.3.4 ("Input Variables"):
+#
+#     Fragment inputs can only be signed and unsigned integers and
+#     integer vectors, float, floating-point vectors, matrices, or
+#     arrays or structures of these.
+#
+# And from section 4.3.6 ("Output Variables"):
+#
+#     Vertex output variables ... can only be float, floating-point
+#     vectors, matrices, signed or unsigned integers or integer
+#     vectors, or arrays or structures of any these.
+#
+# This tests that varying structs work when copied from other structs
+# within the vertex shader, including:
+#
+# - A struct returned from a function
+# - An "out" parameter of a function
+# - A local struct within the shader, or
+# - A uniform struct.
+#
+# These cases are important because in implementations that flatten
+# varying structs to their individual components, these uses of
+# varying structs are likely to take different code paths than uses of
+# varying structs that access the structure elements one at a time.
+
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+
+[vertex shader]
+#version 300 es
+
+in vec4 vertex;
+struct Foo
+{
+	float a;
+	vec2 b;
+	vec3 c;
+	vec4 d;
+};
+out Foo foo;
+uniform Foo uniform_foo;
+uniform int subtest;
+
+Foo return_foo(float ref)
+{
+	return Foo(ref + 1.0,
+		   vec2(ref + 2.0, ref + 3.0),
+		   vec3(ref + 4.0, ref + 5.0, ref + 6.0),
+		   vec4(ref + 7.0, ref + 8.0, ref + 9.0, ref + 10.0));
+}
+
+void out_param_foo(float ref, out Foo p)
+{
+	p.a = ref + 1.0;
+	p.b = vec2(ref + 2.0, ref + 3.0);
+	p.c = vec3(ref + 4.0, ref + 5.0, ref + 6.0);
+	p.d = vec4(ref + 7.0, ref + 8.0, ref + 9.0, ref + 10.0);
+}
+
+void main()
+{
+	gl_Position = vertex;
+	Foo local_foo;
+	local_foo.a = 1.0;
+	local_foo.b = vec2(2.0, 3.0);
+	local_foo.c = vec3(4.0, 5.0, 6.0);
+	local_foo.d = vec4(7.0, 8.0, 9.0, 10.0);
+
+	switch (subtest) {
+	case 0:
+		foo = local_foo;
+		break;
+	case 1:
+		foo = return_foo(100.0);
+		break;
+	case 2:
+		out_param_foo(200.0, foo);
+		break;
+	case 3:
+		foo = uniform_foo;
+		break;
+	}
+}
+
+[fragment shader]
+#version 300 es
+
+uniform int subtest;
+
+struct Foo
+{
+	float a;
+	vec2 b;
+	vec3 c;
+	vec4 d;
+};
+in Foo foo;
+out vec4 color;
+
+#define CHECK(value, expected) \
+	if (distance(value, expected) > 0.00001) \
+		failed = true
+
+void main()
+{
+	bool failed = false;
+
+	float ref = 100.0 * float(subtest);
+
+	CHECK(foo.a, ref + 1.0);
+	CHECK(foo.b, vec2(ref + 2.0, ref + 3.0));
+	CHECK(foo.c, vec3(ref + 4.0, ref + 5.0, ref + 6.0));
+	CHECK(foo.d, vec4(ref + 7.0, ref + 8.0, ref + 9.0, ref + 10.0));
+
+	if (failed)
+		color = vec4(1.0, 0.0, 0.0, 1.0);
+	else
+		color = vec4(0.0, 1.0, 0.0, 1.0);
+}
+
+[test]
+uniform int subtest 0
+draw rect -1 -1 1 1
+uniform int subtest 1
+draw rect 0 -1 1 1
+uniform int subtest 2
+draw rect -1 0 1 1
+uniform int subtest 3
+uniform float uniform_foo.a 301.0
+uniform vec2 uniform_foo.b 302.0 303.0
+uniform vec3 uniform_foo.c 304.0 305.0 306.0
+uniform vec4 uniform_foo.d 307.0 308.0 309.0 310.0
+draw rect 0 0 1 1
+probe all rgba 0.0 1.0 0.0 1.0
diff --git a/tests/spec/glsl-es-3.00/execution/varying-struct-interpolation.shader_test b/tests/spec/glsl-es-3.00/execution/varying-struct-interpolation.shader_test
new file mode 100644
index 0000000..4930dc1
--- /dev/null
+++ b/tests/spec/glsl-es-3.00/execution/varying-struct-interpolation.shader_test
@@ -0,0 +1,86 @@
+# Test that varying structs work properly.
+#
+# From the GLSL ES 3.00 specification, section 4.3.4 ("Input Variables"):
+#
+#     Fragment inputs can only be signed and unsigned integers and
+#     integer vectors, float, floating-point vectors, matrices, or
+#     arrays or structures of these.
+#
+# And from section 4.3.6 ("Output Variables"):
+#
+#     Vertex output variables ... can only be float, floating-point
+#     vectors, matrices, signed or unsigned integers or integer
+#     vectors, or arrays or structures of any these.
+#
+# This tests that the elements of varying structs properly respect the
+# keywords "flat" and "smooth".
+#
+# Note: the keyword "noperspective" is not tested because it does not
+# exist in GLSL ES 3.00.
+
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+
+[vertex shader]
+#version 300 es
+
+in vec4 vertex;
+struct Foo
+{
+	vec4 a;
+};
+out Foo foo;
+flat out Foo foo_flat;
+smooth out Foo foo_smooth;
+out vec4 ref;
+flat out vec4 ref_flat;
+smooth out vec4 ref_smooth;
+
+void main()
+{
+	gl_Position = vertex;
+	foo.a = vertex;
+	foo_flat.a = vertex;
+	foo_smooth.a = vertex;
+	ref = vertex;
+	ref_flat = vertex;
+	ref_smooth = vertex;
+}
+
+[fragment shader]
+#version 300 es
+
+struct Foo
+{
+	vec4 a;
+};
+in Foo foo;
+flat in Foo foo_flat;
+smooth in Foo foo_smooth;
+in vec4 ref;
+flat in vec4 ref_flat;
+smooth in vec4 ref_smooth;
+out vec4 color;
+
+#define CHECK(value, expected) \
+	if (distance(value, expected) > 0.00001) \
+		failed = true
+
+void main()
+{
+	bool failed = false;
+
+	CHECK(foo.a, ref);
+	CHECK(foo_flat.a, ref_flat);
+	CHECK(foo_smooth.a, ref_smooth);
+
+	if (failed)
+		color = vec4(1.0, 0.0, 0.0, 1.0);
+	else
+		color = vec4(0.0, 1.0, 0.0, 1.0);
+}
+
+[test]
+draw rect -1 -1 2 2
+probe all rgba 0.0 1.0 0.0 1.0
-- 
1.8.1.1



More information about the Piglit mailing list