From 37b2f07f66f135da51b26114803050e8c54a4761 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Fri, 17 Nov 2017 17:51:01 +0100 Subject: [PATCH] Add a test for tfb with tessellation --- .../spec/arb_transform_feedback2/CMakeLists.gl.txt | 1 + tests/spec/arb_transform_feedback2/tessellation.c | 316 +++++++++++++++++++++ 2 files changed, 317 insertions(+) create mode 100644 tests/spec/arb_transform_feedback2/tessellation.c diff --git a/tests/spec/arb_transform_feedback2/CMakeLists.gl.txt b/tests/spec/arb_transform_feedback2/CMakeLists.gl.txt index 03635c0..e135198 100644 --- a/tests/spec/arb_transform_feedback2/CMakeLists.gl.txt +++ b/tests/spec/arb_transform_feedback2/CMakeLists.gl.txt @@ -15,5 +15,6 @@ piglit_add_executable (arb_transform_feedback2-draw-auto draw-auto.c) piglit_add_executable (arb_transform_feedback2-gen-names-only gen-names-only.c) piglit_add_executable (arb_transform_feedback2-istransformfeedback istransformfeedback.c) piglit_add_executable (arb_transform_feedback2-pause-counting pause-counting.c) +piglit_add_executable (arb_transform_feedback2-tessellation tessellation.c) # vim: ft=cmake: diff --git a/tests/spec/arb_transform_feedback2/tessellation.c b/tests/spec/arb_transform_feedback2/tessellation.c new file mode 100644 index 0000000..5adcfb4 --- /dev/null +++ b/tests/spec/arb_transform_feedback2/tessellation.c @@ -0,0 +1,316 @@ +/* + * Copyright © 2017 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. + */ + +#include "piglit-util-gl.h" + +/** + * @file tessellation.c + * + * Test transform feedback with a lot of vertices generated by tessellation. + */ + +PIGLIT_GL_TEST_CONFIG_BEGIN + + config.supports_gl_core_version = 40; + +PIGLIT_GL_TEST_CONFIG_END + +#define STR(x) #x +#define STRINGIFY(x) STR(x) + +#define MAX_TFB_PRIMS 4096 +#define TFB_SIZE (MAX_TFB_PRIMS * \ + ARRAY_SIZE(feedback_varyings) * \ + sizeof (int)) +#define PATCH_SIZE 32 +#define N_PATCHES 64 +#define N_RUNS 3000 + +static const char +fs_source[] = + "#version 400\n" + "\n" + "layout(location = 0) out vec4 color_out;\n" + "\n" + "void\n" + "main()\n" + "{\n" + " color_out = vec4(0.0, 1.0, 0.0, 1.0);\n" + "}\n"; + +static const char +vs_source[] = + "#version 400\n" + "\n" + "layout(location = 0) in vec4 vertex_pos;\n" + "\n" + "void\n" + "main()\n" + "{\n" + " gl_Position = vertex_pos;\n" + "}\n"; + +static const char +tcs_source[] = + "#version 400\n" + "\n" + "layout(vertices = " STRINGIFY(PATCH_SIZE) ") out;\n" + "\n" + "out TC_OUT\n" + "{\n" + " int tc_invocation_id;\n" + " int tc_patch_vertices_in;\n" + " int tc_primitive_id;\n" + "} out_te[];\n" + "\n" + "void\n" + "main()\n" + "{\n" + " gl_out[gl_InvocationID].gl_Position =\n" + " gl_in[gl_InvocationID].gl_Position;\n" + " out_te[gl_InvocationID].tc_invocation_id =\n" + " gl_InvocationID;\n" + " out_te[gl_InvocationID].tc_patch_vertices_in =\n" + " gl_PatchVerticesIn;\n" + " out_te[gl_InvocationID].tc_primitive_id =\n" + " gl_PrimitiveID;\n" + " gl_TessLevelInner[0] = 4.0;\n" + " gl_TessLevelInner[1] = 4.0;\n" + " gl_TessLevelOuter[0] = 4.0;\n" + " gl_TessLevelOuter[1] = 4.0;\n" + " gl_TessLevelOuter[2] = 4.0;\n" + " gl_TessLevelOuter[3] = 4.0;\n" + "}\n"; + +static const char +tes_source[] = + "#version 400\n" + "\n" + "layout(triangles) in;\n" + "\n" + "in TC_OUT\n" + "{\n" + " int tc_invocation_id;\n" + " int tc_patch_vertices_in;\n" + " int tc_primitive_id;\n" + "} in_tc[];\n" + "\n" + "out int primitive_id;\n" + "out int patch_vertices_in;\n" + "out int three;\n" + "out int four;\n" + "out int five;\n" + "\n" + "void\n" + "main()\n" + "{\n" + " primitive_id = gl_PrimitiveID;\n" + " patch_vertices_in = gl_PatchVerticesIn;\n" + " three = in_tc[gl_PatchVerticesIn - 1].tc_invocation_id;\n" + " four = in_tc[gl_PatchVerticesIn - 1].tc_patch_vertices_in;\n" + " five = in_tc[gl_PatchVerticesIn - 1].tc_primitive_id;\n" + "}"; + +static const char * const +feedback_varyings[] = { + "primitive_id", + "patch_vertices_in", + "three", + "four", + "five", +}; + +static GLuint +make_program(void) +{ + GLuint prog, tcs, tes; + + prog = piglit_build_simple_program_unlinked(vs_source, fs_source); + + tcs = piglit_compile_shader_text(GL_TESS_CONTROL_SHADER, + tcs_source); + glAttachShader(prog, tcs); + glDeleteShader(tcs); + + tes = piglit_compile_shader_text(GL_TESS_EVALUATION_SHADER, + tes_source); + glAttachShader(prog, tes); + glDeleteShader(tes); + + glTransformFeedbackVaryings(prog, + ARRAY_SIZE(feedback_varyings), + feedback_varyings, + GL_INTERLEAVED_ATTRIBS); + + glLinkProgram(prog); + + if (!piglit_link_check_status(prog)) { + glDeleteProgram(prog); + piglit_report_result(PIGLIT_FAIL); + } + + return prog; +} + +static void +print_all_results(GLint prims, const int *data) +{ + const int *p = data; + int i, j; + + for (i = 0; i < prims; i++) { + for (j = 0; j < ARRAY_SIZE(feedback_varyings); j++) { + fprintf(stderr, "%i", *p++); + if (j < ARRAY_SIZE(feedback_varyings) - 1) + fputc(':', stderr); + } + fputc(' ', stderr); + } + fputc('\n', stderr); +} + +static bool +check_result(GLint prims) +{ + const int *data = + glMapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); + const int *p = data; + bool res = true; + int i; + + for (i = 0; i < prims; i++) { + if (p[1] != PATCH_SIZE || + p[3] != PATCH_SIZE) { + fprintf(stderr, + "Unexpected feedback values at index %i\n", + i); + print_all_results(prims, data); + res = false; + break; + } + p += ARRAY_SIZE(feedback_varyings); + } + + glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); + + return res; +} + +static bool +run_test(GLint *n_prims) +{ + GLuint prog = make_program(); + GLuint qo; + GLuint vao; + GLuint tfb; + void *zeros; + bool pass = true; + + glUseProgram(prog); + + zeros = malloc(TFB_SIZE); + memset(zeros, 0, TFB_SIZE); + + glGenBuffers(1, &tfb); + glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tfb); + glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, + TFB_SIZE, + zeros, + GL_DYNAMIC_READ); + + free(zeros); + + glBindBuffersBase(GL_TRANSFORM_FEEDBACK_BUFFER, + 0, /* first */ + 1, /* count */ + &tfb); + + glGenQueries(1, &qo); + if (*n_prims <= 0) { + glBeginQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, + 0, /* index */ + qo); + } + + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + glPatchParameteri(GL_PATCH_VERTICES, PATCH_SIZE); + glBeginTransformFeedback(GL_TRIANGLES); + glDrawArraysInstanced(GL_PATCHES, 0, PATCH_SIZE * N_PATCHES, 4); + glEndTransformFeedback(); + + if (*n_prims <= 0) { + glEndQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, + 0 /* index */); + + glGetQueryObjectiv(qo, GL_QUERY_RESULT, n_prims); + + if (*n_prims <= 0 || *n_prims >= MAX_TFB_PRIMS) { + fprintf(stderr, + "GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN has " + "the unexpected value %i\n", + *n_prims); + pass = false; + } + } + + if (pass && !check_result(*n_prims)) + pass = false; + + glDeleteVertexArrays(1, &vao); + + glDeleteQueries(1, &qo); + + glDeleteBuffers(1, &tfb); + + glDeleteProgram(prog); + + return pass; +} + +enum piglit_result +piglit_display(void) +{ + int i; + int fail_count = 0; + GLint n_prims = 0; + + for (i = 0; i < N_RUNS; i++) { + if (!run_test(&n_prims)) + fail_count++; + } + + printf("Failure rate %i/%i (%i%%)\n", + fail_count, + N_RUNS, + fail_count * 100 / N_RUNS); + + return fail_count > 0 ? PIGLIT_FAIL : PIGLIT_PASS; +} + +void +piglit_init(int argc, char **argv) +{ + piglit_require_gl_version(40); +} -- 2.9.5