2 * Copyright (c) 2018 Advanced Micro Devices
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
25 * \file tes-gs-max-output.cpp
27 * Stress the limits of what tessellation + geometry shaders can output using
28 * generic shaders with points as input and output primitives, allowing
30 * - number of input instances (instanced draws)
31 * - number of input patches per instance
32 * - (integer) tessellation factors
33 * - number of invocations (GS instances)
34 * - number of output vertices per invocation
35 * - number of output components per vertex
37 * Verification works by rendering points and writing to an SSBO from the
41 #include "piglit-util-gl.h"
48 #define WINDOW_SIZE 256
50 PIGLIT_GL_TEST_CONFIG_BEGIN
52 config
.supports_gl_compat_version
= 32;
53 config
.supports_gl_core_version
= 32;
54 config
.window_width
= WINDOW_SIZE
;
55 config
.window_height
= WINDOW_SIZE
;
56 config
.window_visual
= PIGLIT_GL_VISUAL_DOUBLE
| PIGLIT_GL_VISUAL_RGBA
;
57 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
59 PIGLIT_GL_TEST_CONFIG_END
62 #define STR(x) PASTE(x)
65 unsigned num_instances
; /* draw instances */
66 unsigned num_patches
; /* draw size / count */
67 unsigned tessfactor_u
;
68 unsigned tessfactor_v
;
69 unsigned num_invocations
; /* GS invocations / instances */
70 unsigned num_outputs
; /* # vertex ouput per GS invocation */
71 unsigned num_extra_components
; /* # extra components per GS output vertex */
73 bool operator<(const testcase
&o
) const {
74 if (num_instances
< o
.num_instances
)
76 if (num_instances
> o
.num_instances
)
79 if (num_patches
< o
.num_patches
)
81 if (num_patches
> o
.num_patches
)
84 if (tessfactor_u
< o
.tessfactor_u
)
86 if (tessfactor_u
> o
.tessfactor_u
)
89 if (tessfactor_v
< o
.tessfactor_v
)
91 if (tessfactor_v
> o
.tessfactor_v
)
94 if (num_invocations
< o
.num_invocations
)
96 if (num_invocations
> o
.num_invocations
)
99 if (num_outputs
< o
.num_outputs
)
101 if (num_outputs
> o
.num_outputs
)
104 return num_extra_components
< o
.num_extra_components
;
108 struct fragmentshaderkey
{
109 unsigned num_extra_components
;
111 bool operator<(const fragmentshaderkey
&o
) const {
112 return num_extra_components
< o
.num_extra_components
;
116 struct geometryshaderkey
{
117 unsigned num_invocations
;
118 unsigned num_outputs
;
119 unsigned num_extra_components
;
121 bool operator<(const geometryshaderkey
&o
) const {
122 if (num_invocations
< o
.num_invocations
)
124 if (num_invocations
> o
.num_invocations
)
126 if (num_outputs
< o
.num_outputs
)
128 if (num_outputs
> o
.num_outputs
)
130 return num_extra_components
< o
.num_extra_components
;
134 static std::map
<fragmentshaderkey
, GLuint
> fragmentshaders
;
135 static std::map
<geometryshaderkey
, GLuint
> testprograms
;
137 static const struct testcase default_testcase
= {
142 .num_invocations
= 1,
144 .num_extra_components
= 0,
147 static int32_t *buffer_copy
;
149 static const unsigned max_final_points
= 2 * 1024 * 1024; /* requires 16 MiB buffer */
150 static bool small
= false;
151 static GLuint vs_shader
;
152 static GLuint tcs_shader
;
153 static GLuint tes_shader
;
156 static std::vector
<testcase
> testcases
;
157 static std::set
<testcase
> testcases_set
;
158 static GLuint max_tessfactor
;
159 static GLuint max_gs_invocations
;
160 static GLuint max_gs_out_vertices
;
161 static GLuint max_gs_total_out_components
;
162 static GLuint max_gs_out_components
;
163 static unsigned max_gs_out_vertices_real
;
165 static const char vs_text
[] =
168 "uniform int u_verts_per_instance;\n"
170 "out int vs_tcs_id;\n"
173 " vs_tcs_id = gl_InstanceID * u_verts_per_instance + gl_VertexID;\n"
176 static const char tcs_text
[] =
178 "#extension GL_ARB_tessellation_shader : require\n"
179 "layout(vertices = 1) out;\n"
181 "in int vs_tcs_id[];\n"
183 "out int tcs_tes_id[];\n"
185 "uniform int u_tessfactor_u;\n"
186 "uniform int u_tessfactor_v;\n"
189 " tcs_tes_id[gl_InvocationID] = vs_tcs_id[gl_InvocationID];\n"
190 " gl_TessLevelOuter[0] = u_tessfactor_v;\n"
191 " gl_TessLevelOuter[1] = u_tessfactor_u;\n"
194 static const char tes_text
[] =
196 "#extension GL_ARB_tessellation_shader : require\n"
197 "layout(isolines, equal_spacing) in;\n"
199 "in int tcs_tes_id[];\n"
201 "out int tes_gs_id;\n"
204 " tes_gs_id = tcs_tes_id[0];\n"
205 " gl_Position.x = gl_TessCoord[0];\n"
206 " gl_Position.y = gl_TessCoord[1];\n"
209 /* Those numbers really don't matter much for what we're trying to do here. */
210 #define GEN_SEQUENCE \
211 "int seq_next(int x) {\n" \
212 " x = (x + 1) * 709900053;\n" \
213 " x = x ^ (x >> 17);\n" \
217 static const char gs_text
[] =
219 "#extension GL_ARB_gpu_shader5 : require\n"
221 "#define NUM_INVOCATIONS %d\n"
222 "#define NUM_OUT_VERTICES %d\n"
223 "#define NUM_EXTRA_COMPONENTS %d\n"
225 "layout(lines, invocations = NUM_INVOCATIONS) in;\n"
226 "layout(points, max_vertices = NUM_OUT_VERTICES) out;\n"
228 "uniform int u_tessfactor_u;\n"
229 "uniform int u_tessfactor_v;\n"
231 "in int tes_gs_id[];\n"
233 "flat out int gs_ps_data[1 + NUM_EXTRA_COMPONENTS];\n"
238 " int in_id = tes_gs_id[0] * u_tessfactor_u * u_tessfactor_v;\n"
239 " float v = gl_in[0].gl_Position.y;\n"
240 " in_id += u_tessfactor_u * int(v * u_tessfactor_v + 0.5);\n"
241 " float u = min(gl_in[0].gl_Position.x, gl_in[1].gl_Position.x);\n"
242 " in_id += int(u * u_tessfactor_u + 0.5);\n"
244 " for (int i = 0; i < NUM_OUT_VERTICES; ++i) {\n"
245 " uint id = (in_id * NUM_INVOCATIONS + gl_InvocationID) * NUM_OUT_VERTICES + i;\n"
246 " uint x = id %% " STR(WINDOW_SIZE
) "u;\n"
247 " uint y = (id / " STR(WINDOW_SIZE
) "u) %% " STR(WINDOW_SIZE
) "u;\n"
248 " gl_Position.x = (float(x) + 0.5) / " STR(WINDOW_SIZE
) " * 2.0 - 1.0;\n"
249 " gl_Position.y = (float(y) + 0.5) / " STR(WINDOW_SIZE
) " * 2.0 - 1.0;\n"
250 " gl_Position.z = 0.0;\n"
251 " gl_Position.w = 1.0;\n"
253 " int val = int(id);\n"
254 " for (int j = 0; j <= NUM_EXTRA_COMPONENTS; ++j) {\n"
255 " gs_ps_data[j] = val;\n"
256 " val = seq_next(val);\n"
263 static const char fs_text
[] =
265 "#extension GL_ARB_shader_storage_buffer_object : require\n"
267 "#define NUM_EXTRA_COMPONENTS %d\n"
269 "flat in int gs_ps_data[1 + NUM_EXTRA_COMPONENTS];\n"
270 "out vec4 out_color;\n"
272 "layout(std430, binding = 0) buffer SSBO {\n"
279 " int id = gs_ps_data[0];\n"
280 " int screen_id = int(gl_FragCoord.y) * " STR(WINDOW_SIZE
) " + int(gl_FragCoord.x);\n"
281 " if (screen_id != id %% (" STR(WINDOW_SIZE
* WINDOW_SIZE
) ")) {\n"
282 " ssbo.data[id].x = 1000;\n"
283 " ssbo.data[id].y = screen_id;\n"
284 " out_color = vec4(0.1, 0, 0, 1);\n"
289 " for (int j = 0; j <= NUM_EXTRA_COMPONENTS; ++j) {\n"
290 " if (val != gs_ps_data[j]) {\n"
291 " ssbo.data[id].x = 2000 + j;\n"
292 " ssbo.data[id].y = gs_ps_data[j];\n"
293 " out_color = vec4(0, 0.1, 0, 1);\n"
296 " val = seq_next(val);\n"
299 " ssbo.data[id].x = 1;\n"
300 " out_color = vec4(0, 0, 0, 1);\n"
304 print_testcase(const struct testcase
*tc
)
306 printf("Case: instances = %u patches = %u tessfactor = %u,%u invocations = %u "
307 "outputs = %u extra_components = %u\n",
308 tc
->num_instances
, tc
->num_patches
, tc
->tessfactor_u
, tc
->tessfactor_v
,
309 tc
->num_invocations
, tc
->num_outputs
, tc
->num_extra_components
);
313 add_testcase(const struct testcase
*tc
)
315 if (!testcases_set
.insert(*tc
).second
)
318 if (tc
->num_instances
> 64 * 1024 ||
319 tc
->num_patches
> 64 * 1024 ||
320 tc
->tessfactor_u
> 64 * 1024 ||
321 tc
->tessfactor_v
> 64 * 1024 ||
322 tc
->num_invocations
> 64 * 1024 ||
323 tc
->num_outputs
> 64 * 1024 ||
324 tc
->num_extra_components
> 64 * 1024) {
325 fprintf(stderr
, "Excessive test case size. Are you sure?\n");
330 /* Multiple separate multiplies to avoid integer wraparound */
331 if ((uint64_t)tc
->num_instances
* tc
->num_patches
* tc
->tessfactor_u
> max_final_points
||
332 (uint64_t)tc
->tessfactor_v
* tc
->num_invocations
* tc
->num_outputs
> max_final_points
||
333 (uint64_t)tc
->num_instances
* tc
->num_patches
* tc
->tessfactor_u
*
334 tc
->tessfactor_v
* tc
->num_invocations
* tc
->num_outputs
> max_final_points
) {
335 fprintf(stderr
, "Test case has more than %u final points.\n", max_final_points
);
340 /* Check against implementation-defined limits. */
341 if (tc
->tessfactor_u
> max_tessfactor
|| tc
->tessfactor_v
> max_tessfactor
) {
342 fprintf(stderr
, "Tessellation factor too high (max: %u)\n",
347 if (tc
->num_outputs
> max_gs_out_vertices
) {
348 fprintf(stderr
, "Too many output vertices (max: %d)\n",
349 max_gs_out_vertices
);
353 if (tc
->num_outputs
* (5 + tc
->num_extra_components
) > max_gs_total_out_components
) {
354 fprintf(stderr
, "Too many output components (max: %d)\n",
355 max_gs_total_out_components
);
359 if (tc
->num_invocations
> max_gs_invocations
) {
360 fprintf(stderr
, "Too many GS invocations (max: %d)\n",
366 /* Compile GS shader and link program */
367 geometryshaderkey gskey
;
368 gskey
.num_invocations
= tc
->num_invocations
;
369 gskey
.num_outputs
= tc
->num_outputs
;
370 gskey
.num_extra_components
= tc
->num_extra_components
;
371 if (testprograms
.find(gskey
) == testprograms
.end()) {
374 fragmentshaderkey fskey
;
375 fskey
.num_extra_components
= tc
->num_extra_components
;
376 std::map
<fragmentshaderkey
, GLuint
>::const_iterator fsit
=
377 fragmentshaders
.find(fskey
);
378 if (fsit
== fragmentshaders
.end()) {
379 if (asprintf(&text
, fs_text
, tc
->num_extra_components
) < 0)
382 piglit_compile_shader_text(GL_FRAGMENT_SHADER
, text
);
385 fsit
= fragmentshaders
.insert(std::make_pair(fskey
, fs_shader
)).first
;
388 if (asprintf(&text
, gs_text
, tc
->num_invocations
, tc
->num_outputs
,
389 tc
->num_extra_components
) < 0)
392 piglit_compile_shader_text(GL_GEOMETRY_SHADER
, text
);
395 GLuint prog
= glCreateProgram();
396 glAttachShader(prog
, vs_shader
);
397 glAttachShader(prog
, tcs_shader
);
398 glAttachShader(prog
, tes_shader
);
399 glAttachShader(prog
, gs_shader
);
400 glAttachShader(prog
, fsit
->second
);
402 if (!piglit_link_check_status(prog
))
403 piglit_report_result(PIGLIT_FAIL
);
405 glDeleteShader(gs_shader
);
407 testprograms
.insert(std::make_pair(gskey
, prog
));
410 testcases
.push_back(*tc
);
414 run_testcase(const struct testcase
*tc
)
416 unsigned final_points
= tc
->num_instances
* tc
->num_patches
* tc
->tessfactor_u
*
417 tc
->tessfactor_v
* tc
->num_invocations
* tc
->num_outputs
;
418 unsigned bufsize
= 2 * sizeof(int32_t) * final_points
;
422 glClearColor(0, 0, 0, 1);
423 glClear(GL_COLOR_BUFFER_BIT
);
425 geometryshaderkey gskey
;
426 gskey
.num_invocations
= tc
->num_invocations
;
427 gskey
.num_outputs
= tc
->num_outputs
;
428 gskey
.num_extra_components
= tc
->num_extra_components
;
429 std::map
<geometryshaderkey
, GLuint
>::const_iterator progit
=
430 testprograms
.find(gskey
);
431 assert(progit
!= testprograms
.end());
433 glUseProgram(progit
->second
);
434 glPatchParameteri(GL_PATCH_VERTICES
, 1);
435 glUniform1i(glGetUniformLocation(progit
->second
, "u_tessfactor_u"),
437 glUniform1i(glGetUniformLocation(progit
->second
, "u_tessfactor_v"),
439 glUniform1i(glGetUniformLocation(progit
->second
, "u_verts_per_instance"),
442 glBindBufferBase(GL_SHADER_STORAGE_BUFFER
, 0, ssbo
);
444 memset(buffer_copy
, 0, bufsize
);
445 glBufferSubData(GL_SHADER_STORAGE_BUFFER
, 0, bufsize
, buffer_copy
);
448 glBlendFunc(GL_ONE
, GL_ONE
);
450 glDrawArraysInstanced(GL_PATCHES
, 0, tc
->num_patches
, tc
->num_instances
);
454 if (!piglit_check_gl_error(GL_NO_ERROR
))
457 static const float expected
[] = { 0, 0, 0, 1 };
460 if (!piglit_probe_rect_rgba(0, 0, WINDOW_SIZE
, WINDOW_SIZE
, expected
))
463 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER
, 0, bufsize
, buffer_copy
);
465 for (unsigned i
= 0; i
< final_points
; ++i
) {
466 if (buffer_copy
[2 * i
] != 1) {
467 printf("Error @ %d: %d %d\n", i
,
468 buffer_copy
[2 * i
], buffer_copy
[2 * i
+ 1]);
478 generate_testcases_max2(const testcase
&tc
, bool explicit_instances
, bool explicit_patches
)
480 unsigned amplify
= tc
.tessfactor_u
* tc
.tessfactor_v
* tc
.num_invocations
* tc
.num_outputs
;
481 unsigned target_in
= max_final_points
/ amplify
;
484 target_in
= MIN2(4, target_in
);
486 if (!explicit_instances
) {
488 tc1
.num_instances
= MAX2(1, target_in
/ tc1
.num_patches
);
492 if (!explicit_patches
) {
494 tc1
.num_patches
= MAX2(1, target_in
/ tc1
.num_instances
);
498 if (!explicit_instances
&& !explicit_patches
) {
500 tc1
.num_instances
= MAX2(1, (unsigned)sqrt(target_in
));
501 tc1
.num_patches
= MAX2(1, target_in
/ tc1
.num_instances
);
505 if (explicit_instances
&& explicit_patches
)
510 generate_testcases_max1(const testcase
&tc
, bool explicit_instances
, bool explicit_patches
,
511 bool explicit_tessfactor_u
, bool explicit_tessfactor_v
,
512 unsigned tess_out_max
)
514 if (!explicit_tessfactor_u
) {
516 tc1
.tessfactor_u
= MIN2(MAX2(1, tess_out_max
/ tc1
.tessfactor_v
),
518 generate_testcases_max2(tc1
, explicit_instances
, explicit_patches
);
521 if (!explicit_tessfactor_v
) {
523 tc1
.tessfactor_v
= MIN2(MAX2(1, tess_out_max
/ tc1
.tessfactor_u
),
525 generate_testcases_max2(tc1
, explicit_instances
, explicit_patches
);
528 if (!explicit_tessfactor_u
&& !explicit_tessfactor_v
) {
530 tc1
.tessfactor_u
= MIN2(MAX2(1, (unsigned)sqrt(tess_out_max
)),
532 tc1
.tessfactor_v
= MIN2(MAX2(1, tess_out_max
/ tc1
.tessfactor_u
),
534 generate_testcases_max2(tc1
, explicit_instances
, explicit_patches
);
537 if (explicit_tessfactor_u
&& explicit_tessfactor_v
)
538 generate_testcases_max2(tc
, explicit_instances
, explicit_patches
);
542 generate_testcases_max(const testcase
&tc
, bool explicit_instances
, bool explicit_patches
,
543 bool explicit_tessfactor_u
, bool explicit_tessfactor_v
)
545 unsigned amplify
= tc
.num_invocations
* tc
.num_outputs
;
546 unsigned tess_out_max
= max_final_points
/ amplify
;
549 generate_testcases_max1(tc
, explicit_instances
, explicit_patches
,
550 explicit_tessfactor_u
, explicit_tessfactor_v
,
551 MIN2(4, tess_out_max
));
553 generate_testcases_max1(tc
, explicit_instances
, explicit_patches
,
554 explicit_tessfactor_u
, explicit_tessfactor_v
,
556 while (tess_out_max
> 4) {
557 tess_out_max
= sqrt(tess_out_max
);
558 generate_testcases_max1(tc
, explicit_instances
, explicit_patches
,
559 explicit_tessfactor_u
, explicit_tessfactor_v
,
566 rand_subdivide(int partitions
)
570 for (int i
= 1; i
< partitions
; ++i
)
571 x
= std::min(x
, (double)rand() / ((double)RAND_MAX
+ 1));
577 piglit_init(int argc
, char **argv
)
579 bool explicit_instances
= false;
580 bool explicit_patches
= false;
581 bool explicit_tessfactor_u
= false;
582 bool explicit_tessfactor_v
= false;
583 bool explicit_invocations
= false;
584 bool explicit_outputs
= false;
585 bool explicit_components
= false;
586 bool scan_mode
= false;
587 unsigned scan_seed
= 0;
588 unsigned scan_count
= 0;
589 struct testcase explicit_testcase
;
591 piglit_require_extension("GL_ARB_tessellation_shader");
592 piglit_require_extension("GL_ARB_shader_storage_buffer_object");
594 memcpy(&explicit_testcase
, &default_testcase
, sizeof(explicit_testcase
));
597 for (i
= 1; i
< argc
; ++i
) {
598 if (!strcmp(argv
[i
], "-small")) {
604 if (!strcmp(argv
[i
], "-instances")) {
605 explicit_testcase
.num_instances
= atoi(argv
[i
+ 1]);
606 explicit_instances
= true;
608 } else if (!strcmp(argv
[i
], "-patches")) {
609 explicit_testcase
.num_patches
= atoi(argv
[i
+ 1]);
610 explicit_patches
= true;
612 } else if (!strcmp(argv
[i
], "-tessfactor_u")) {
613 explicit_testcase
.tessfactor_u
= atoi(argv
[i
+ 1]);
614 explicit_tessfactor_u
= true;
616 } else if (!strcmp(argv
[i
], "-tessfactor_v")) {
617 explicit_testcase
.tessfactor_v
= atoi(argv
[i
+ 1]);
618 explicit_tessfactor_v
= true;
620 } else if (!strcmp(argv
[i
], "-invocations")) {
621 explicit_testcase
.num_invocations
= atoi(argv
[i
+ 1]);
622 explicit_invocations
= true;
624 } else if (!strcmp(argv
[i
], "-outputs")) {
625 explicit_testcase
.num_outputs
= atoi(argv
[i
+ 1]);
626 explicit_outputs
= true;
628 } else if (!strcmp(argv
[i
], "-components")) {
629 explicit_testcase
.num_extra_components
= atoi(argv
[i
+ 1]);
630 explicit_components
= true;
636 if (!strcmp(argv
[i
], "-scan")) {
637 scan_seed
= atoi(argv
[i
+ 1]);
638 scan_count
= atoi(argv
[i
+ 2]);
647 fprintf(stderr
, "Unknown argument or too few params: %s\n", argv
[i
]);
651 /* Various GL objects needed by the test */
652 vs_shader
= piglit_compile_shader_text(GL_VERTEX_SHADER
, vs_text
);
653 if (!piglit_check_gl_error(GL_NO_ERROR
))
654 piglit_report_result(PIGLIT_FAIL
);
656 tcs_shader
= piglit_compile_shader_text(GL_TESS_CONTROL_SHADER
, tcs_text
);
657 if (!piglit_check_gl_error(GL_NO_ERROR
))
658 piglit_report_result(PIGLIT_FAIL
);
660 tes_shader
= piglit_compile_shader_text(GL_TESS_EVALUATION_SHADER
, tes_text
);
661 if (!piglit_check_gl_error(GL_NO_ERROR
))
662 piglit_report_result(PIGLIT_FAIL
);
664 glGenVertexArrays(1, &vao
);
665 glBindVertexArray(vao
);
667 glGenBuffers(1, &ssbo
);
668 glBindBuffer(GL_SHADER_STORAGE_BUFFER
, ssbo
);
669 glBufferData(GL_SHADER_STORAGE_BUFFER
, max_final_points
* 8, NULL
, GL_DYNAMIC_READ
);
671 buffer_copy
= (int32_t *)calloc(2 * sizeof(int32_t), max_final_points
);
673 glGetIntegerv(GL_MAX_TESS_GEN_LEVEL
, (GLint
*)&max_tessfactor
);
674 glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES
, (GLint
*)&max_gs_out_vertices
);
675 glGetIntegerv(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS
,
676 (GLint
*)&max_gs_total_out_components
);
677 glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS
,
678 (GLint
*)&max_gs_out_components
);
679 glGetIntegerv(GL_MAX_GEOMETRY_SHADER_INVOCATIONS
, (GLint
*)&max_gs_invocations
);
680 if (!piglit_check_gl_error(GL_NO_ERROR
))
681 piglit_report_result(PIGLIT_FAIL
);
683 max_gs_out_vertices_real
= MIN2(max_gs_out_vertices
,
684 max_gs_total_out_components
/ 5);
689 /* First, generate test cases that max out each of the dimensions */
690 testcase tc0
= explicit_testcase
;
691 if (!explicit_invocations
)
692 tc0
.num_invocations
= max_gs_invocations
;
694 if (!explicit_outputs
) {
697 if (!explicit_components
) {
698 tc1
.num_outputs
= max_gs_out_vertices_real
;
699 tc1
.num_extra_components
=
700 MIN2(max_gs_total_out_components
/ tc1
.num_outputs
,
701 max_gs_out_components
) - 5;
704 MIN2(max_gs_total_out_components
/
705 (5 + tc1
.num_extra_components
),
706 max_gs_out_vertices_real
);
709 generate_testcases_max(tc1
, explicit_instances
, explicit_patches
,
710 explicit_tessfactor_u
, explicit_tessfactor_v
);
713 if (!explicit_components
) {
716 if (!explicit_outputs
) {
717 tc1
.num_extra_components
= max_gs_out_components
- 5;
719 MIN2(max_gs_total_out_components
/
720 (5 + tc1
.num_extra_components
),
721 max_gs_out_vertices_real
);
723 tc1
.num_extra_components
=
724 MIN2(max_gs_total_out_components
/ tc1
.num_outputs
,
725 max_gs_out_components
) - 4;
728 generate_testcases_max(tc1
, explicit_instances
, explicit_patches
,
729 explicit_tessfactor_u
, explicit_tessfactor_v
);
732 if (explicit_outputs
&& explicit_components
)
733 generate_testcases_max(tc0
, explicit_instances
, explicit_patches
,
734 explicit_tessfactor_u
, explicit_tessfactor_v
);
736 /* Generate additional tests randomly.
738 * Attempt to generate a random distribution that isn't too
739 * lop-sided, but admittedly this is all just hand-wavey
742 while (testcases
.size() < scan_count
) {
743 testcase tc
= explicit_testcase
;
745 if (!explicit_outputs
|| !explicit_components
) {
746 if (explicit_outputs
|| rand() & 1) {
747 unsigned max_components
=
748 MIN2(max_gs_total_out_components
/ tc
.num_outputs
,
749 max_gs_out_components
) - 5;
750 tc
.num_extra_components
= rand() % (max_components
+ 1);
752 if (!explicit_outputs
) {
753 unsigned max_outputs
=
754 MIN2(max_gs_total_out_components
/
755 (5 + tc
.num_extra_components
),
756 max_gs_out_vertices_real
);
757 tc
.num_outputs
= 1 + rand() % max_outputs
;
760 unsigned max_outputs
=
761 MIN2(max_gs_total_out_components
/
762 (5 + tc
.num_extra_components
),
763 max_gs_out_vertices_real
);
764 tc
.num_outputs
= 1 + rand() % max_outputs
;
766 if (!explicit_components
) {
767 unsigned max_components
=
768 MIN2(max_gs_total_out_components
/ tc
.num_outputs
,
769 max_gs_out_components
) - 5;
770 tc
.num_extra_components
= rand() % (max_components
+ 1);
775 unsigned amplify
= tc
.num_outputs
;
777 if (explicit_invocations
)
778 amplify
*= tc
.num_invocations
;
779 if (explicit_tessfactor_u
)
780 amplify
*= tc
.tessfactor_u
;
781 if (explicit_tessfactor_v
)
782 amplify
*= tc
.tessfactor_v
;
783 if (explicit_patches
)
784 amplify
*= tc
.num_patches
;
785 if (explicit_instances
)
786 amplify
*= tc
.num_instances
;
788 unsigned target
= max_final_points
/ amplify
;
791 target
= MIN2(32, target
);
793 if (!explicit_tessfactor_u
) {
794 float tf_log_weight
= logf(target
) * rand_subdivide(6);
795 tc
.tessfactor_u
= MIN2(expf(tf_log_weight
), max_tessfactor
);
796 target
/= tc
.tessfactor_u
;
798 if (!explicit_tessfactor_v
) {
799 float tf_log_weight
= logf(target
) * rand_subdivide(6);
800 tc
.tessfactor_v
= MIN2(expf(tf_log_weight
), max_tessfactor
);
801 target
/= tc
.tessfactor_v
;
803 if (!explicit_invocations
) {
804 float log_weight
= logf(target
);
805 if (!explicit_instances
|| !explicit_patches
)
806 log_weight
*= rand_subdivide(2);
807 tc
.num_invocations
= MIN2(expf(log_weight
), max_gs_invocations
);
808 target
/= tc
.num_invocations
;
810 if (!explicit_instances
) {
811 float log_weight
= logf(target
);
812 if (!explicit_patches
)
813 log_weight
*= rand_subdivide(2);
814 tc
.num_instances
= expf(log_weight
);
815 target
/= tc
.num_instances
;
817 if (!explicit_patches
)
818 tc
.num_patches
= 1 + rand() % target
;
823 add_testcase(&explicit_testcase
);
832 for (unsigned i
= 0; i
< testcases
.size(); ++i
) {
833 if (!run_testcase(&testcases
[i
]))
837 if (!piglit_check_gl_error(GL_NO_ERROR
))
840 piglit_present_results();
842 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;