This adds a couple of original compiler tests, and ports the tests for
amd_vertex_shader_layer and amd_vertex_shader_viewport_index to the ARB
extension.

These tests touch the VS, but not the tes eval.

Signed-off-by: Dylan Baker <dylanx.c.ba...@intel.com>
---
 tests/all.py                                       |   8 +
 tests/spec/CMakeLists.txt                          |   1 +
 .../CMakeLists.gl.txt                              |  24 ++
 .../arb_shader_viewport_layer_array/CMakeLists.txt |   1 +
 .../compiler/write-viewportindex.frag              |  15 +
 .../compiler/write-viewportindex.tesc              |  15 +
 .../compiler/write-viewportindex.tese              |  17 ++
 .../compiler/write-viewportindex.vert              |  17 ++
 .../layered-2d-texture-render.c                    | 339 +++++++++++++++++++++
 .../layered-depth-texture-render.c                 | 239 +++++++++++++++
 .../spec/arb_shader_viewport_layer_array/render.c  | 152 +++++++++
 11 files changed, 828 insertions(+)
 create mode 100644 tests/spec/arb_shader_viewport_layer_array/CMakeLists.gl.txt
 create mode 100644 tests/spec/arb_shader_viewport_layer_array/CMakeLists.txt
 create mode 100644 
tests/spec/arb_shader_viewport_layer_array/compiler/write-viewportindex.frag
 create mode 100644 
tests/spec/arb_shader_viewport_layer_array/compiler/write-viewportindex.tesc
 create mode 100644 
tests/spec/arb_shader_viewport_layer_array/compiler/write-viewportindex.tese
 create mode 100644 
tests/spec/arb_shader_viewport_layer_array/compiler/write-viewportindex.vert
 create mode 100644 
tests/spec/arb_shader_viewport_layer_array/layered-2d-texture-render.c
 create mode 100644 
tests/spec/arb_shader_viewport_layer_array/layered-depth-texture-render.c
 create mode 100644 tests/spec/arb_shader_viewport_layer_array/render.c

diff --git a/tests/all.py b/tests/all.py
index 3961656..edec9d0 100644
--- a/tests/all.py
+++ b/tests/all.py
@@ -4749,6 +4749,14 @@ with profile.group_manager(
     g(['arb_shader_draw_parameters-drawid-indirect', 'baseinstance'], 
'drawid-indirect-baseinstance')
     g(['arb_shader_draw_parameters-drawid-indirect', 'vertexid'], 
'drawid-indirect-vertexid')
 
+with profile.group_manager(
+        PiglitGLTest,
+        grouptools.join('spec', 'ARB_shader_viewport_layer_array')) as g:
+    for test in ['layered-depth-texture-render',
+                 'layered-depth-texture-render',
+                 'render-vs']:
+        g(['arb_shader_viewport_layer_array-{}'.format(test)], test)
+
 # Group ARB_indirect_parameters
 with profile.group_manager(
         PiglitGLTest,
diff --git a/tests/spec/CMakeLists.txt b/tests/spec/CMakeLists.txt
index 9b0f73e..d56c501 100644
--- a/tests/spec/CMakeLists.txt
+++ b/tests/spec/CMakeLists.txt
@@ -54,6 +54,7 @@ add_subdirectory (arb_shader_atomic_counters)
 add_subdirectory (arb_shader_objects)
 add_subdirectory (arb_shader_image_load_store)
 add_subdirectory (arb_shader_image_size)
+add_subdirectory (arb_shader_viewport_layer_array)
 add_subdirectory (arb_shading_language_420pack/execution)
 add_subdirectory (arb_stencil_texturing)
 add_subdirectory (arb_sync)
diff --git a/tests/spec/arb_shader_viewport_layer_array/CMakeLists.gl.txt 
b/tests/spec/arb_shader_viewport_layer_array/CMakeLists.gl.txt
new file mode 100644
index 0000000..ebbca99
--- /dev/null
+++ b/tests/spec/arb_shader_viewport_layer_array/CMakeLists.gl.txt
@@ -0,0 +1,24 @@
+include_directories(
+       ${GLEXT_INCLUDE_DIR}
+       ${OPENGL_INCLUDE_PATH}
+)
+
+link_libraries (
+       piglitutil_${piglit_target_api}
+       ${OPENGL_gl_LIBRARY}
+)
+
+piglit_add_executable(
+       arb_shader_viewport_layer_array-layered-2d-texture-render
+       layered-2d-texture-render.c
+)
+piglit_add_executable(
+       arb_shader_viewport_layer_array-layered-depth-texture-render
+       layered-depth-texture-render.c
+)
+piglit_add_executable(
+       arb_shader_viewport_layer_array-render-vs
+       render.c
+)
+
+# vim: ft=cmake
diff --git a/tests/spec/arb_shader_viewport_layer_array/CMakeLists.txt 
b/tests/spec/arb_shader_viewport_layer_array/CMakeLists.txt
new file mode 100644
index 0000000..144a306
--- /dev/null
+++ b/tests/spec/arb_shader_viewport_layer_array/CMakeLists.txt
@@ -0,0 +1 @@
+piglit_include_target_api()
diff --git 
a/tests/spec/arb_shader_viewport_layer_array/compiler/write-viewportindex.frag 
b/tests/spec/arb_shader_viewport_layer_array/compiler/write-viewportindex.frag
new file mode 100644
index 0000000..5acf23c
--- /dev/null
+++ 
b/tests/spec/arb_shader_viewport_layer_array/compiler/write-viewportindex.frag
@@ -0,0 +1,15 @@
+/* gl_ViewportIndex should be undefined in a Fragment Shader.
+ *
+ * [config]
+ * expect_result: fail
+ * glsl_version: 4.10
+ * require_extensions: GL_ARB_shader_viewport_layer_array
+ * [end config]
+ */
+
+#version 410
+
+void main()
+{
+    gl_ViewportIndex = 1;
+}
diff --git 
a/tests/spec/arb_shader_viewport_layer_array/compiler/write-viewportindex.tesc 
b/tests/spec/arb_shader_viewport_layer_array/compiler/write-viewportindex.tesc
new file mode 100644
index 0000000..e1d308d
--- /dev/null
+++ 
b/tests/spec/arb_shader_viewport_layer_array/compiler/write-viewportindex.tesc
@@ -0,0 +1,15 @@
+/* gl_ViewportIndex should be undefined in a Teselation Control Shader.
+ *
+ * [config]
+ * expect_result: fail
+ * glsl_version: 4.10
+ * require_extensions: GL_ARB_shader_viewport_layer_array
+ * [end config]
+ */
+
+#version 410
+
+void main()
+{
+    gl_ViewportIndex = 1;
+}
diff --git 
a/tests/spec/arb_shader_viewport_layer_array/compiler/write-viewportindex.tese 
b/tests/spec/arb_shader_viewport_layer_array/compiler/write-viewportindex.tese
new file mode 100644
index 0000000..5087a30
--- /dev/null
+++ 
b/tests/spec/arb_shader_viewport_layer_array/compiler/write-viewportindex.tese
@@ -0,0 +1,17 @@
+/* Tests that the OpenGL special variable gl_ViewportIndex can be set in a
+ * Teselation Evaulation Shader.
+ *
+ * [config]
+ * expect_result: pass
+ * glsl_version: 4.10
+ * require_extensions: GL_ARB_shader_viewport_layer_array
+ * [end config]
+ */
+
+#version 410
+#extension GL_ARB_shader_viewport_layer_array : require
+
+void main()
+{
+    gl_ViewportIndex = 1;
+}
diff --git 
a/tests/spec/arb_shader_viewport_layer_array/compiler/write-viewportindex.vert 
b/tests/spec/arb_shader_viewport_layer_array/compiler/write-viewportindex.vert
new file mode 100644
index 0000000..b98580a
--- /dev/null
+++ 
b/tests/spec/arb_shader_viewport_layer_array/compiler/write-viewportindex.vert
@@ -0,0 +1,17 @@
+/* Tests that the OpenGL special variable gl_ViewportIndex can be set in a
+ * vertex shader
+ *
+ * [config]
+ * expect_result: pass
+ * glsl_version: 4.10
+ * require_extensions: GL_ARB_shader_viewport_layer_array
+ * [end config]
+ */
+
+#version 410
+#extension GL_ARB_shader_viewport_layer_array : require
+
+void main()
+{
+    gl_ViewportIndex = 1;
+}
diff --git 
a/tests/spec/arb_shader_viewport_layer_array/layered-2d-texture-render.c 
b/tests/spec/arb_shader_viewport_layer_array/layered-2d-texture-render.c
new file mode 100644
index 0000000..e5ad56c
--- /dev/null
+++ b/tests/spec/arb_shader_viewport_layer_array/layered-2d-texture-render.c
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 2013, 2016 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.
+ *
+ */
+
+/*
+ * Test 2D array texture rendering with gl_Layer
+ * (ARB_shader_viewport_layer_array)
+ *
+ * This test uses layered rendering (gl_Layer) within the vertex shader.
+ * Support for gl_Layer in VS is added by the ARB_shader_viewport_layer_array
+ * extension.
+ *
+ * This test first draws to a color array texture which is attached to
+ * a framebuffer. The texture has 5 layers and 7 LODs.
+ *
+ * Once colors have been rendered to each array slice & LOD, the test
+ * then uses the texture to draw on the system framebuffer and verifies
+ * that the expected colors appear.
+ */
+
+#include "piglit-util-gl.h"
+
+#define PAD            5
+#define SIZE           64
+#define LAYERS         5
+#define LOD            7
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+       config.supports_gl_core_version = 41;
+       config.supports_gl_compat_version = 41;
+
+       config.window_width = (((SIZE+PAD)*LAYERS)+PAD);
+       config.window_height = (((SIZE+PAD)*2)+PAD);
+       config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGB;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+static GLuint rectangle_vertices_bo;
+
+/* VS and FS to fill the 2D array texture */
+static const char *fill_tex_vs = 
+ "#version 410\n"
+ "#extension GL_ARB_shader_viewport_layer_array: enable\n"
+ "uniform int color_bias;\n"
+ "in vec2 vertex;\n"
+ "out vec3 color;\n"
+ "vec3 get_color(int num)\n"
+ "{\n"
+ " vec3 result = vec3(0.0);\n"
+ " if ((num & 4) != 0) result.r = 1.0;"
+ " if ((num & 2) != 0) result.g = 1.0;"
+ " if ((num & 1) != 0) result.b = 1.0;"
+ " return result;\n"
+ "}\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = vec4(vertex, vec2(0.0, 1.0));\n"
+ " gl_Layer = gl_InstanceID;\n"
+ " color = get_color(color_bias + gl_InstanceID);\n"
+ "}\n";
+
+static const char *fill_tex_fs = 
+ "#version 410\n"
+ "in vec3 color;\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = vec4(color, 1.0);\n"
+ "}\n";
+
+/* VS and FS to use and test the 2D array texture */
+static const char *use_tex_vs = 
+ "#version 410\n"
+ "in vec2 vertex;\n"
+ "out vec2 coord;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = vec4(vertex, vec2(0.0, 1.0));\n"
+ " coord = (vertex * 0.5) + 0.5;\n"
+ "}\n";
+
+static const char *use_tex_fs =
+ "#version 410\n"
+ "uniform sampler2DArray tex; \n"
+ "uniform int layer;\n"
+ "uniform int lod;\n"
+ "in vec2 coord;\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = textureLod(tex, vec3(coord, float(layer)), lod);\n"
+ "}\n";
+
+static GLuint fill_tex_program;
+static GLuint use_tex_program;
+
+static int get_x(int layer)
+{
+       return ((SIZE + PAD) * layer) + PAD;
+}
+
+static int get_y(int layer, int lod)
+{
+       int size = SIZE >> lod;
+       return PAD + (((1 << lod) - 1) * 2 * size);
+}
+
+static const GLfloat *get_color(int num)
+{
+       int color_index;
+
+       static const GLfloat colors[][3] = {
+               {0.0, 0.0, 0.0},
+               {0.0, 0.0, 1.0},
+               {0.0, 1.0, 0.0},
+               {0.0, 1.0, 1.0},
+               {1.0, 0.0, 0.0},
+               {1.0, 0.0, 1.0},
+               {1.0, 1.0, 0.0},
+               {1.0, 1.0, 1.0},
+       };
+
+       color_index = num % ARRAY_SIZE(colors);
+       return colors[color_index];
+}
+
+static bool
+render_tex_layers(GLuint tex)
+{
+       int lod;
+       GLint color_bias_loc;
+       GLint vertex_loc;
+       GLenum status;
+       int color_index = 0;
+       int size;
+
+       glUseProgram(fill_tex_program);
+
+       color_bias_loc = glGetUniformLocation(fill_tex_program, "color_bias");
+
+       glBindBuffer(GL_ARRAY_BUFFER, rectangle_vertices_bo);
+       vertex_loc = glGetAttribLocation(fill_tex_program, "vertex");
+       glVertexAttribPointer(vertex_loc, 2, GL_FLOAT, 0, 0, 0);
+       glEnableVertexAttribArray(vertex_loc);
+       for (lod = 0; lod < LOD; lod++) {
+               size = SIZE >> lod;
+               glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 
lod);
+               status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+               if (status != GL_FRAMEBUFFER_COMPLETE) {
+                       fprintf(stderr, "fbo incomplete (status = %s)\n",
+                               piglit_get_gl_enum_name(status));
+                       return false;
+               }
+               glDrawBuffer(GL_COLOR_ATTACHMENT0);
+               glViewport(0, 0, size, size);
+               glUniform1i(color_bias_loc, color_index);
+               glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, LAYERS);
+               color_index += LAYERS;
+       }
+       glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0);
+       glBindFramebuffer(GL_FRAMEBUFFER, piglit_winsys_fbo);
+       glDisableVertexAttribArray(vertex_loc);
+
+       return true;
+}
+
+static GLuint
+build_texture(void)
+{
+       GLuint tex;
+       int lod;
+       int size;
+
+       glGenTextures(1, &tex);
+       glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
+       for (lod = 0; lod < LOD; lod++) {
+               size = SIZE >> lod;
+               glTexImage3D(GL_TEXTURE_2D_ARRAY, lod, GL_RGBA,
+                            size, size, LAYERS, 0, GL_RGBA, GL_FLOAT, NULL);
+       }
+
+       render_tex_layers(tex);
+
+       return tex;
+}
+
+static void
+draw_box(GLuint tex, int layer, int lod)
+{
+       GLint layer_loc, lod_loc, vertex_loc;
+       int x = get_x(layer);
+       int y = get_y(layer, lod);
+       int size = SIZE >> lod;
+
+       layer_loc = glGetUniformLocation(use_tex_program, "layer");
+       lod_loc = glGetUniformLocation(use_tex_program, "lod");
+
+       glBindBuffer(GL_ARRAY_BUFFER, rectangle_vertices_bo);
+
+       vertex_loc = glGetAttribLocation(use_tex_program, "vertex");
+       glVertexAttribPointer(vertex_loc, 2, GL_FLOAT, 0, 0, 0);
+       glEnableVertexAttribArray(vertex_loc);
+
+       glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
+
+       glViewport(x, y, size, size);
+       glUniform1i(layer_loc, layer);
+       glUniform1i(lod_loc, lod);
+       glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+       glDisableVertexAttribArray(vertex_loc);
+}
+
+static GLboolean
+test_results(int layer, int lod)
+{
+       int x = get_x(layer);
+       int y = get_y(layer, lod);
+       const GLfloat *expected_color3f = get_color((lod * LAYERS) + layer);
+       GLboolean pass;
+       int size = SIZE >> lod;
+
+       pass = piglit_probe_rect_rgb(x, y, size, size, expected_color3f);
+
+       if (!pass) {
+               printf("2D array failed at size %d, layer %d\n",
+                      size, layer);
+       }
+
+       return pass;
+}
+
+static GLboolean
+test_texture(GLuint tex)
+{
+       int layer, lod;
+       GLint tex_loc;
+       GLboolean pass = GL_TRUE;
+       glUseProgram(use_tex_program);
+       glActiveTexture(GL_TEXTURE0);
+       tex_loc = glGetUniformLocation(use_tex_program, "tex");
+       glUniform1i(tex_loc, 0);
+
+       glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER,
+                       GL_NEAREST_MIPMAP_NEAREST);
+       glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER,
+                       GL_NEAREST);
+
+       for (lod = 0; lod < LOD; lod++) {
+               for (layer = 0; layer < LAYERS; layer++) {
+                       draw_box(tex, layer, lod);
+               }
+       }
+
+       for (lod = 0; lod < LOD; lod++) {
+               for (layer = 0; layer < LAYERS; layer++) {
+                       pass = test_results(layer, lod) && pass;
+               }
+       }
+
+       glUseProgram(0);
+       return pass;
+}
+
+enum piglit_result
+piglit_display(void)
+{
+       GLboolean pass;
+       GLuint vao, fbo;
+       GLuint tex;
+       static const GLfloat verts[4][2] = {
+               { 1.0, -1.0},
+               {-1.0, -1.0},
+               { 1.0,  1.0},
+               {-1.0,  1.0},
+       };
+
+       /* Clear background to gray */
+       glClearColor(0.5, 0.5, 0.5, 1.0);
+       glClear(GL_COLOR_BUFFER_BIT);
+
+       glGenFramebuffers(1, &fbo);
+       glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+       glGenVertexArrays(1, &vao);
+       glBindVertexArray(vao);
+       glGenBuffers(1, &rectangle_vertices_bo);
+       glBindBuffer(GL_ARRAY_BUFFER, rectangle_vertices_bo);
+       glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
+
+       tex = build_texture();
+       pass = test_texture(tex);
+       glDeleteTextures(1, &tex);
+
+       piglit_present_results();
+
+       glDeleteBuffers(1, &rectangle_vertices_bo);
+       glDeleteFramebuffers(1, &fbo);
+       glDeleteVertexArrays(1, &vao);
+
+       return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+       /* For glFramebufferTexture we need either GL 3.2 or
+        * GL_ARB_geometry_shader4.
+        */
+       if (piglit_get_gl_version() < 32) {
+               piglit_require_extension("GL_ARB_geometry_shader4");
+       }
+
+       piglit_require_extension("GL_AMD_vertex_shader_layer");
+
+       fill_tex_program = piglit_build_simple_program(fill_tex_vs, 
fill_tex_fs);
+       piglit_check_gl_error(GL_NO_ERROR);
+
+       use_tex_program = piglit_build_simple_program(use_tex_vs, use_tex_fs);
+       piglit_check_gl_error(GL_NO_ERROR);
+}
diff --git 
a/tests/spec/arb_shader_viewport_layer_array/layered-depth-texture-render.c 
b/tests/spec/arb_shader_viewport_layer_array/layered-depth-texture-render.c
new file mode 100644
index 0000000..fbac6f1
--- /dev/null
+++ b/tests/spec/arb_shader_viewport_layer_array/layered-depth-texture-render.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2013, 2016 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.
+ *
+ */
+
+/*
+ * Test 2D depth array texture rendering with gl_Layer
+ * (ARB_shader_viewport_layer_array)
+ *
+ * This test uses layered rendering (gl_Layer) within the vertex shader.
+ * Support for gl_Layer in VS is added by the ARB_shader_viewport_layer_array
+ * extension.
+ *
+ * This test first renders to a depth array texture which is attached to
+ * a framebuffer. The texture has 5 layers and 7 LODs.
+ *
+ * Once depths have been rendered to each array slice & LOD, the test
+ * then verifies the depth value in each array slice & LOD.
+ */
+
+#include "piglit-util-gl.h"
+
+#define PAD            5
+#define SIZE           64
+#define LAYERS         5
+#define LOD            7
+#define DRAW_COUNT     LAYERS * LOD
+#define STRINGIFY(x)    #x
+#define EXP_STRINGIFY(x) STRINGIFY(x)
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+       config.supports_gl_core_version = 41;
+       config.supports_gl_compat_version = 41;
+
+       config.window_width = (((SIZE+PAD)*LAYERS)+PAD);
+       config.window_height = (((SIZE+PAD)*2)+PAD);
+       config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGB;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+static GLuint rectangle_vertices_bo;
+
+/* VS and FS to fill the 2D array texture */
+static const char *fill_tex_vs = 
+ "#version 410\n"
+ "#extension GL_ARB_shader_viewport_layer_array: enable\n"
+ "uniform int drawing_level;\n"
+ "in vec2 vertex;\n"
+ "out vec3 color;\n"
+ "int num_layers = " EXP_STRINGIFY(LAYERS) ";\n"
+ "int draw_count = " EXP_STRINGIFY(DRAW_COUNT) ";\n"
+ "float get_z()\n"
+ "{\n"
+ " return float((drawing_level * num_layers) + gl_InstanceID) / draw_count;\n"
+  "}\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = vec4(vertex, get_z(), 1.0);\n"
+ " gl_Layer = gl_InstanceID;\n"
+ "}\n";
+
+static GLuint fill_tex_program;
+
+static bool
+render_tex_layers(GLuint tex)
+{
+       int lod;
+       GLint drawing_level_loc, vertex_loc;
+       GLenum status;
+       int color_index = 0;
+       int size;
+
+       glUseProgram(fill_tex_program);
+
+       drawing_level_loc = glGetUniformLocation(fill_tex_program, 
"drawing_level");
+
+       glBindBuffer(GL_ARRAY_BUFFER, rectangle_vertices_bo);
+       vertex_loc = glGetAttribLocation(fill_tex_program, "vertex");
+       glVertexAttribPointer(vertex_loc, 2, GL_FLOAT, 0, 0, 0);
+       glEnableVertexAttribArray(vertex_loc);
+       for (lod = 0; lod < LOD; lod++) {
+               size = SIZE >> lod;
+               glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, tex, 
lod);
+               status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+               if (status != GL_FRAMEBUFFER_COMPLETE) {
+                       fprintf(stderr, "fbo incomplete (status = %s)\n",
+                               piglit_get_gl_enum_name(status));
+                       return false;
+               }
+
+               /* Clear background to gray */
+               glClearDepth(1.0);
+               glClear(GL_DEPTH_BUFFER_BIT);
+
+               glViewport(0, 0, size, size);
+               glUniform1i(drawing_level_loc, lod);
+               glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, LAYERS);
+               color_index += LAYERS;
+       }
+       glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 0, 0);
+       glDisableVertexAttribArray(vertex_loc);
+
+       return true;
+}
+
+static GLuint
+build_texture(void)
+{
+       GLuint tex;
+       int lod;
+       int size;
+
+       glGenTextures(1, &tex);
+       glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
+       for (lod = 0; lod < LOD; lod++) {
+               size = SIZE >> lod;
+               glTexImage3D(GL_TEXTURE_2D_ARRAY, lod, GL_DEPTH_COMPONENT,
+                            size, size, LAYERS, 0, GL_DEPTH_COMPONENT, 
GL_FLOAT, NULL);
+       }
+
+       render_tex_layers(tex);
+
+       return tex;
+}
+
+/* Attach the texture layer/lod to the read framebuffer
+ */
+static void
+set_up_read_framebuffer(GLuint tex, int level, int layer)
+{
+       GLenum status;
+
+       glFramebufferTextureLayer(GL_READ_FRAMEBUFFER,
+                                 GL_DEPTH_ATTACHMENT,
+                                 tex, level, layer);
+
+       status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+       if (status == GL_FRAMEBUFFER_UNSUPPORTED && level == 0) {
+               printf("This buffer combination is unsupported\n");
+               piglit_report_result(PIGLIT_SKIP);
+       } else if (status != GL_FRAMEBUFFER_COMPLETE) {
+               printf("FBO incomplete at miplevel %d\n", level);
+               piglit_report_result(PIGLIT_FAIL);
+       }
+}
+
+static GLboolean
+test_texture(GLuint tex)
+{
+       int layer, lod;
+       GLboolean retval = GL_TRUE;
+       float expected;
+       float draw_count = LAYERS * LOD;
+       int dim = SIZE;
+
+       for (lod = 0; lod < LOD; lod++) {
+               for (layer = 0; layer < LAYERS; layer++) {
+                       GLboolean pass;
+                       set_up_read_framebuffer(tex, lod, layer);
+                       expected = ((float)(lod * LAYERS) + layer) / draw_count;
+                       expected = (expected / 2.0) + 0.5;
+                       pass = piglit_probe_rect_depth(0, 0, dim, dim, 
expected);
+                       retval = retval && pass;
+               }
+               dim >>= 1;
+       }
+
+       return retval;
+}
+
+enum piglit_result
+piglit_display(void)
+{
+       GLboolean pass;
+       GLuint vao, fbo;
+       GLuint tex;
+       static const GLfloat verts[4][2] = {
+               { 1.0, -1.0},
+               {-1.0, -1.0},
+               { 1.0,  1.0},
+               {-1.0,  1.0},
+       };
+
+       glEnable(GL_DEPTH_TEST);
+
+       glGenFramebuffers(1, &fbo);
+       glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+       glGenVertexArrays(1, &vao);
+       glBindVertexArray(vao);
+       glGenBuffers(1, &rectangle_vertices_bo);
+       glBindBuffer(GL_ARRAY_BUFFER, rectangle_vertices_bo);
+       glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
+
+       tex = build_texture();
+       pass = test_texture(tex);
+       glDeleteTextures(1, &tex);
+
+       glDeleteBuffers(1, &rectangle_vertices_bo);
+       glDeleteFramebuffers(1, &fbo);
+       glDeleteVertexArrays(1, &vao);
+
+       return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+       /* For glFramebufferTexture we need either GL 3.2 or
+        * GL_ARB_geometry_shader4.
+        */
+       if (piglit_get_gl_version() < 32) {
+               piglit_require_extension("GL_ARB_geometry_shader4");
+       }
+
+       piglit_require_extension("GL_AMD_vertex_shader_layer");
+
+       fill_tex_program = piglit_build_simple_program(fill_tex_vs, NULL);
+       piglit_check_gl_error(GL_NO_ERROR);
+}
diff --git a/tests/spec/arb_shader_viewport_layer_array/render.c 
b/tests/spec/arb_shader_viewport_layer_array/render.c
new file mode 100644
index 0000000..9b48498
--- /dev/null
+++ b/tests/spec/arb_shader_viewport_layer_array/render.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright ?? 2013 LunarG, Inc.
+ * Copyright ?? 2016 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.
+ *
+ * Author: Jon Ashburn <j...@lunarg.com>
+ * Adapted for vertex shader: Ilia Mirkin <imir...@alum.mit.edu>
+ */
+
+/**
+ * Tests rendering into a single framebuffer surface with multiple viewports
+ * via a vertex shader.  Confirm that each area of the surface delineated by
+ * a viewport renders the correct color.
+ * From the extension registry for ARB_viewport_array:
+ *    "This extension enhances OpenGL by providing a mechanism to expose
+ *    multiple viewports. Each viewport is specified as a rectangle. The
+ *    destination viewport may be selected per-primitive by the geometry
+ *    shader. This allows the Geometry Shader to produce different versions
+ *    of primitives destined for separate viewport rectangles on the same
+ *    surface.
+ * This extension allows specifying the viewport from the vertex shader.
+ */
+#include "piglit-util-gl.h"
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+       config.supports_gl_core_version = 31;
+
+       config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+const char *vsSource = {
+       "#version 410\n"
+        "#extension GL_ARB_shader_viewport_layer_array : require\n"
+       "in vec4 piglit_vertex;\n"
+       "uniform int idx;\n"
+       "void main() {\n"
+       "       gl_ViewportIndex = idx;\n"
+       "       gl_Position = piglit_vertex;\n"
+       "}\n"
+};
+
+const char *fsSource = {
+       "#version 140\n"
+       "uniform vec3 color;\n"
+       "void main() {\n"
+       "       gl_FragColor = vec4(color.xyz, 1.0);\n"
+       "}\n"
+};
+
+static GLint colorLoc;
+static GLint vpIndexLoc;
+
+/**
+ * Draws a single quad into multiple viewport  each with a different
+ * color.  Reads back the expected color  to test if the drawing was correct.
+ * @param  changeVPloc;   if true then the vertex shader viewport location
+ *         is changed with each loop, otherwise viewport location is fixed.
+ */
+static bool
+draw_multi_viewport(const bool changeVPLoc)
+{
+       bool pass = true;
+       int i, j;
+       const int divX=2, divY=4;
+       GLfloat w = (GLfloat) piglit_width / (GLfloat) divX;
+       GLfloat h = (GLfloat) piglit_height / (GLfloat) divY;
+       const GLfloat colors[][3] = {{0.0, 0.0, 1.0},
+                                 {0.0, 1.0, 0.0},
+                                 {1.0, 0.0, 0.0},
+                                 {1.0, 1.0, 0.0},
+                                 {0.0, 1.0, 1.0},
+                                 {1.0, 0.0, 1.0},
+                                 {1.0, 1.0, 1.0},
+                                 {0.0, 0.0, 0.5},
+                                 {0.0, 0.0, 0.0}};
+
+       assert(ARRAY_SIZE(colors) == divX*divY + 1);
+
+       glViewport(0, 0, piglit_width, piglit_height); /* for glClear() */
+       glClear(GL_COLOR_BUFFER_BIT);
+       glUniform1i(vpIndexLoc, divX * divY);
+       glViewportIndexedf(divX * divY, -10.0, -30.0, piglit_width, 20.0);
+       for (i = 0; i < divX; i++) {
+               for (j = 0; j < divY; j++) {
+                       int p;
+                       GLfloat *expected;
+                       glUniform3fv(colorLoc, 1, &colors[j + i*divY][0]);
+                       if (changeVPLoc) {
+                               glUniform1i(vpIndexLoc, j + i*divY);
+                               expected = (GLfloat *) &colors[j + i*divY][0];
+                       } else  {
+                               expected = (GLfloat *) &colors[divX * divY][0];
+                       }
+                       glViewportIndexedf(j + i*divY, i * w, j * h, w, h);
+                       piglit_draw_rect(-1, -1, 2, 2);
+                       pass = piglit_check_gl_error(GL_NO_ERROR) && pass;
+                       p = piglit_probe_pixel_rgb(i * w + w/2, j * h + h/2,
+                                                  expected);
+                       piglit_present_results();
+                       if (!p) {
+                               printf("Wrong color for viewport i,j %d %d 
changeVP=%d\n",
+                                      i, j, changeVPLoc);
+                               pass = false;
+                       }
+               }
+       }
+       return pass;
+}
+
+enum piglit_result
+piglit_display(void)
+{
+       bool pass = true;
+
+       pass = draw_multi_viewport(true);
+       pass = draw_multi_viewport(false) && pass;
+       pass = piglit_check_gl_error(GL_NO_ERROR) && pass;
+       return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+       GLuint program;
+
+       piglit_require_extension("GL_ARB_shader_viewport_layer_array");
+
+       program = piglit_build_simple_program(vsSource, fsSource);
+       glUseProgram(program);
+       colorLoc = glGetUniformLocation(program, "color");
+       vpIndexLoc = glGetUniformLocation(program, "idx");
+}
-- 
2.9.3

_______________________________________________
Piglit mailing list
Piglit@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/piglit

Reply via email to