From: Ian Romanick <ian.d.roman...@intel.com>

V3: rebased, fix variable copy & paste error, update the
relink_program_created_by_glCreateShaderProgram() test to check
for linking error when in core profile and no error in compat
(Timothy).

v2: Add missing extension check for GL_ARB_transform_feedback2.  Use
configure_transform_feedback_object utility function.  Use
CreateShaderProgram_with_xfb utility function.

Signed-off-by: Ian Romanick <ian.d.roman...@intel.com>
Reviewed-by: Timothy Arceri <timothy.arc...@collabora.com>
---
 tests/all.py                                       |   1 +
 .../arb_separate_shader_objects/CMakeLists.gl.txt  |   1 +
 .../spec/arb_separate_shader_objects/api-errors.c  | 352 +++++++++++++++++++++
 3 files changed, 354 insertions(+)
 create mode 100644 tests/spec/arb_separate_shader_objects/api-errors.c

diff --git a/tests/all.py b/tests/all.py
index 33b49f2..2c16c69 100644
--- a/tests/all.py
+++ b/tests/all.py
@@ -2193,6 +2193,7 @@ with profile.group_manager(
       'mix-and-match-tcs-tes'),
     g(['arb_separate_shader_object-mixed_explicit_and_non_explicit_locations'],
       'Mixed explicit and non-explicit locations')
+    g(['arb_separate_shader_object-api-errors'], 'misc. API error checks')
     g(['arb_separate_shader_object-rendezvous_by_location', '-fbo'],
       'Rendezvous by location', run_concurrent=False)
     g(['arb_separate_shader_object-rendezvous_by_location-5-stages'],
diff --git a/tests/spec/arb_separate_shader_objects/CMakeLists.gl.txt 
b/tests/spec/arb_separate_shader_objects/CMakeLists.gl.txt
index 572157e..f5512bd 100644
--- a/tests/spec/arb_separate_shader_objects/CMakeLists.gl.txt
+++ b/tests/spec/arb_separate_shader_objects/CMakeLists.gl.txt
@@ -11,6 +11,7 @@ link_libraries (
 piglit_add_executable (arb_separate_shader_object-400-combinations 
400-combinations.c sso-common.c)
 piglit_add_executable (arb_separate_shader_object-active-sampler-conflict 
active-sampler-conflict.c)
 piglit_add_executable 
(arb_separate_shader_object-ActiveShaderProgram-invalid-program 
ActiveShaderProgram-invalid-program.c sso-common.c)
+piglit_add_executable (arb_separate_shader_object-api-errors api-errors.c 
sso-common.c)
 piglit_add_executable (arb_separate_shader_object-compat-builtins 
compat-builtins.c)
 piglit_add_executable (arb_separate_shader_object-dlist dlist.c sso-common.c)
 piglit_add_executable 
(arb_separate_shader_object-explicit_locations_and_transform_feedback 
explicit_locations_and_transform_feedback.c)
diff --git a/tests/spec/arb_separate_shader_objects/api-errors.c 
b/tests/spec/arb_separate_shader_objects/api-errors.c
new file mode 100644
index 0000000..1d6069e
--- /dev/null
+++ b/tests/spec/arb_separate_shader_objects/api-errors.c
@@ -0,0 +1,352 @@
+/*
+ * Copyright © 2014 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 api-errors.c
+ * Verify miscelaneous API error conditions from the specification.
+ */
+#include "piglit-util-gl.h"
+#include "sso-common.h"
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+       config.supports_gl_compat_version = 10;
+       config.supports_gl_core_version = 31;
+
+       config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGB;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+static bool
+relink_program_created_by_glCreateShaderProgram(void)
+{
+       static const char *code = "void main() { gl_Position = vec4(0); }";
+       GLuint prog = 0;
+       GLuint vs = 0;
+       bool pass = true;
+
+       prog = glCreateShaderProgramv(GL_VERTEX_SHADER, 1,
+                                     (const GLchar * const*) &code);
+       if (!piglit_link_check_status(prog)) {
+               pass = false;
+               goto done;
+       }
+
+       if (!piglit_check_gl_error(0)) {
+               pass = false;
+               goto done;
+       }
+
+       /* Issue #14 of the GL_ARB_separate_shader_objects spec says:
+        *
+        *     "14. Should glLinkProgram work to re-link a shader created with
+        *          glCreateShaderProgram?
+        *
+        *          RESOLVED: NO because the shader created by
+        *          glCreateShaderProgram is detached and deleted as part of
+        *          the glCreateShaderProgram sequence.  This means if you
+        *          call glLinkProgram on a program returned from
+        *          glCreateShaderProgram, you'll find the re-link fails
+        *          because no shader object is attached.
+        *
+        *          An application is free to attach one or more new shader
+        *          objects to the program and then relink would work.
+        *
+        *          This is fine because re-linking isn't necessary/expected."
+        */
+       glLinkProgram(prog);
+
+       if (piglit_is_core_profile) {
+               if (piglit_link_check_status(prog)) {
+                       printf("Relinking program without any shaders "
+                              "attached succeeded, but it should have "
+                              "failed.\n");
+                       pass = false;
+               }
+       } else if (!piglit_link_check_status(prog)) {
+               printf("Relinking program without any shaders attached "
+                      "failed, but it should have succeeded.\n");
+               pass = false;
+       }
+
+       pass = piglit_check_gl_error(0) && pass;
+
+       vs = piglit_compile_shader_text(GL_VERTEX_SHADER, code);
+       if (vs == 0) {
+               pass = false;
+               goto done;
+       }
+
+       glAttachShader(prog, vs);
+
+       glLinkProgram(prog);
+
+       if (!piglit_link_check_status(prog)) {
+               printf("Relinking program after reattaching a vertex shader "
+                      "failed, but it should have succeeded.\n");
+               pass = false;
+       }
+
+       pass = piglit_check_gl_error(0) && pass;
+
+ done:
+       glDeleteProgram(prog);
+       glDeleteShader(vs);
+
+       piglit_report_subtest_result(pass ? PIGLIT_PASS : PIGLIT_FAIL,
+                                    "relink a program created by "
+                                    "glCreateShaderProgramv");
+       return pass;
+}
+
+static bool
+glUseProgramStages_for_a_missing_stage(void)
+{
+       static const char *vs_code = "void main() { gl_Position = vec4(0); }";
+       static const char *fs_code = "void main() { }";
+
+       GLuint vs_prog = 0;
+       GLuint fs_prog = 0;
+       GLuint prog;
+       GLuint pipe = 0;
+       bool pass = true;
+
+       vs_prog = glCreateShaderProgramv(GL_VERTEX_SHADER, 1,
+                                        (const GLchar * const*) &vs_code);
+       fs_prog = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1,
+                                        (const GLchar * const*) &fs_code);
+
+       glGenProgramPipelines(1, &pipe);
+       glBindProgramPipeline(pipe);
+       glUseProgramStages(pipe, GL_VERTEX_SHADER_BIT, vs_prog);
+       glUseProgramStages(pipe, GL_FRAGMENT_SHADER_BIT, fs_prog);
+
+       /* Sanity check.
+        */
+       glGetProgramPipelineiv(pipe, GL_FRAGMENT_SHADER, (GLint *) &prog);
+       if (prog != fs_prog) {
+               printf("Sanity check failed - fragment shader program "
+                      "mismatch.\n");
+               pass = false;
+       }
+
+       glGetProgramPipelineiv(pipe, GL_VERTEX_SHADER, (GLint *) &prog);
+       if (prog != vs_prog) {
+               printf("Sanity check failed - vertex shader program "
+                      "mismatch.\n");
+               pass = false;
+       }
+
+       pass = piglit_check_gl_error(0) && pass;
+
+       /* Issue #7 of the GL_ARB_separate_shader_objects spec says:
+        *
+        *     "7.  What happens if you have a program object current for a
+        *          shader stage, but the program object doesn't contain an
+        *          executable for that stage?
+        *
+        *          RESOLVED: This is not an error; instead it is as though
+        *          there were no program bound to that stage.  We have two
+        *          different notions for programs bound to shader stages.  A
+        *          program is "current" for a stage if it bound to that stage
+        *          in the active program pipeline object.  A program is
+        *          "active" for a stage if it is current and it has an
+        *          executable for this stage.  In this case, the program
+        *          would be current but not active.
+        *
+        *          When no program is active for a stage, the stage will be
+        *          replaced with fixed functionality logic (compatibility
+        *          profile vertex and fragment), disabled (tessellation
+        *          control and evaluation, geometry), or have undefined
+        *          results (core profile vertex and fragment).
+        *
+        *          Support for programs that are current but not active is
+        *          intentional behavior.  Consider an example where an
+        *          application wants to use two different types of separate
+        *          program object -- one for all types of vertex processing
+        *          and a second for fragment processing.  Some of the vertex
+        *          pipe programs might include tessellation or geometry
+        *          shaders; others might only include a vertex shader.  With
+        *          this configuration, the application can use code like the
+        *          following:
+        *
+        *            #define GL_ALL_VERTEX_PIPE_SHADER_BITS    \
+        *                (GL_VERTEX_SHADER_BIT             |   \
+        *                 GL_TESS_CONTROL_SHADER_BIT       |   \
+        *                 GL_TESS_EVALUATION_SHADER_BIT    |   \
+        *                 GL_GEOMETRY_SHADER_BIT)
+        *
+        *            glUseProgramStages(pipeline,
+        *                               GL_ALL_VERTEX_PIPE_SHADER_BITS,
+        *                               vertex_pipe_program);
+        *            glUseProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT,
+        *                               fragment_pipe_program);
+        *
+        *        Such code wouldn't have to determine if
+        *        <vertex_pipe_program> has tessellation or geometry shaders.
+        *        Instead, it simply sets all possible bits, which removes the
+        *        old program from all non-fragment stages.  For stages not
+        *        present in the new program, the program will be current but
+        *        not active, and it will be as though no program were bound
+        *        to such stages."
+        *
+        * Further, the body of the spec says:
+        *
+        *     "If UseProgramStages is called with <program> set to zero or
+        *     with a program object that contains no executable code for a
+        *     given stages, it is as if the pipeline object has no
+        *     programmable stage configured for the indicated shader stages."
+        *
+        * This indicated to me that the "program == 0" and "program doesn't
+        * have the specified stage" cases should both cause
+        * glGetProgramPipelineiv to return zero for the GL_*_SHADER query.
+        */
+       glUseProgramStages(pipe, GL_FRAGMENT_SHADER_BIT, vs_prog);
+
+       glGetProgramPipelineiv(pipe, GL_FRAGMENT_SHADER, (GLint *) &prog);
+       if (prog != 0) {
+               printf("Using a program that lacks a particular stage for that "
+                      "stage did not cause the stage to use program 0.\n");
+               pass = false;
+       }
+
+       pass = piglit_check_gl_error(0) && pass;
+
+       piglit_report_subtest_result(pass ? PIGLIT_PASS : PIGLIT_FAIL,
+                                    "glUseProgramStages of a program that "
+                                    "lacks a specified stage");
+
+       return pass;
+}
+
+static bool
+glActiveShaderProgram_while_transform_feedback_is_active(void)
+{
+       static const char *vs_code = "void main() { gl_Position = vec4(0); }";
+       static const char *fs_code = "void main() { }";
+
+       GLuint vs_prog = 0;
+       GLuint fs_prog = 0;
+       GLuint pipe = 0;
+       GLuint xfb = 0;
+       GLuint buf = 0;
+       bool pass = true;
+       static const char *varyings[] = {"gl_Position"};
+
+       if (!CreateShaderProgram_with_xfb(vs_code, varyings, 1, &vs_prog)) {
+               pass = false;
+               goto done;
+       }
+
+       fs_prog = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1,
+                                        (const GLchar * const*) &fs_code);
+
+       glGenProgramPipelines(1, &pipe);
+       glBindProgramPipeline(pipe);
+       glUseProgramStages(pipe, GL_VERTEX_SHADER_BIT, vs_prog);
+       glUseProgramStages(pipe, GL_FRAGMENT_SHADER_BIT, fs_prog);
+
+       configure_transform_feedback_object(&xfb, &buf);
+
+       pass = piglit_check_gl_error(0) && pass;
+
+       glBeginTransformFeedback(GL_TRIANGLES);
+
+       pass = piglit_check_gl_error(0) && pass;
+
+       /* Issue #6b of the GL_ARB_separate_shader_objects spec says:
+        *
+        *     "6b. Should the active program be allowed to changed within
+        *          transform feedback mode?
+        *
+        *          RESOLVED:  Yes.
+        *
+        *          The active program simply allows uniforms to be changed
+        *          but doesn't actually change how the graphics pipeline
+        *          itself is configured or what programs are used for vertex,
+        *          geometry, and fragment processing."
+        */
+       glActiveShaderProgram(pipe, vs_prog);
+       glActiveShaderProgram(pipe, fs_prog);
+
+       pass = piglit_check_gl_error(0) && pass;
+
+       glEndTransformFeedback();
+
+       pass = piglit_check_gl_error(0) && pass;
+
+ done:
+       glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
+       glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
+
+       glDeleteTransformFeedbacks(1, &xfb);
+       glDeleteBuffers(1, &buf);
+       glDeleteProgram(vs_prog);
+       glDeleteProgram(fs_prog);
+
+       pass = piglit_check_gl_error(0) && pass;
+
+       piglit_report_subtest_result(pass ? PIGLIT_PASS : PIGLIT_FAIL,
+                                    "glActiveShaderProgram while transform "
+                                    "feedback is active");
+
+       return pass;
+}
+
+static bool
+glBindProgramPipeline_while_transform_feedback_is_active(void)
+{
+       /* This is already covered by the "bind_pipeline" mode of the
+        * ext_transform_feedback-api-errors test.
+        */
+       return true;
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+       bool pass = true;
+
+       piglit_require_vertex_shader();
+       piglit_require_fragment_shader();
+       piglit_require_extension("GL_ARB_separate_shader_objects");
+
+       pass = relink_program_created_by_glCreateShaderProgram() && pass;
+       pass = glUseProgramStages_for_a_missing_stage() && pass;
+
+       if (piglit_is_extension_supported("GL_ARB_transform_feedback2")) {
+               pass = 
glActiveShaderProgram_while_transform_feedback_is_active()
+                       && pass;
+               pass = 
glBindProgramPipeline_while_transform_feedback_is_active()
+                       && pass;
+       }
+
+       piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);
+}
+
+enum piglit_result
+piglit_display(void)
+{
+       return PIGLIT_FAIL;
+}
-- 
2.5.0

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

Reply via email to