/* * Copyright (c) 2009 Nicolai Hähnle * * 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. * * Authors: * Nicolai Hähnle * */ /** * \file * Test certain type of very long fragment programs. */ #include #include #include #include "piglit-util-gl.h" PIGLIT_GL_TEST_CONFIG_BEGIN config.supports_gl_compat_version = 10; config.window_visual = PIGLIT_GL_VISUAL_RGBA; PIGLIT_GL_TEST_CONFIG_END int max_alu_instructions; static const char program_Head[] = "!!ARBfp1.0\n" "TEMP r;\n" "MOV r, 0;\n" ; static const char program_Step[] = "ADD %s, r.wxyz, { %f, %f, %f, %f };\n"; static const char program_Tail[] = "END\n"; static const char program_Output[] = "result.color"; static void step_add(unsigned int i, float * add) { unsigned int rotate = i % 4; add[(0 + rotate) % 4] = ((i+1) % 16) ? 0.0625 : -1.0+0.0625; add[(1 + rotate) % 4] = ((i+1) % 16) ? 0.0 : (((i+1) % 256) ? 0.0625 : -1.0+0.0625); add[(2 + rotate) % 4] = ((i+1) % 256) ? 0.0 : (((i+1) % 4096) ? 0.0625 : -1.0+0.0625); add[(3 + rotate) % 4] = ((i+1) % 4096) ? 0.0 : 0.0625; } static enum piglit_result test(unsigned int alu_depth) { char * program_text = malloc(sizeof(program_Head) + 2*alu_depth*sizeof(program_Step) + sizeof(program_Tail) + sizeof(program_Output)); char * buildp; char buf[128]; GLuint program_object; unsigned int i; float expected[4] = { 0.0, 0.0, 0.0, 0.0 }; /* Note: This test makes sense up to alu_depth of 65536, * but current drivers are not exactly efficient with such * long programs, and if 16k works, then 64k will probably * work, too ;-) */ if (!alu_depth || alu_depth > 16384 || alu_depth + 1 > max_alu_instructions) { free(program_text); return PIGLIT_SKIP; } printf("Testing: alu_depth = %u\n", alu_depth); memcpy(program_text, program_Head, sizeof(program_Head)-1); buildp = program_text + sizeof(program_Head)-1; for(i = 0; i < alu_depth; ++i) { float add[4]; int length; step_add(i, add); length = snprintf(buf, sizeof(buf), program_Step, i == (alu_depth-1) ? program_Output : "r", add[0], add[1], add[2], add[3]); memcpy(buildp, buf, length); buildp += length; } memcpy(buildp, program_Tail, sizeof(program_Tail)); // printf(program_text); program_object = piglit_compile_program(GL_FRAGMENT_PROGRAM_ARB, program_text); free(program_text); program_text = NULL; glEnable(GL_FRAGMENT_PROGRAM_ARB); glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, program_object); piglit_draw_rect(0, 0, 32, 32); glDisable(GL_FRAGMENT_PROGRAM_ARB); glDeleteProgramsARB(1, &program_object); expected[0] = (alu_depth % 16) * 0.0625; expected[1] = ((alu_depth/16) % 16) * 0.0625; expected[2] = ((alu_depth/256) % 16) * 0.0625; expected[3] = (alu_depth/4096) * 0.0625; for(i = 0; i < ((alu_depth+3) % 4); ++i) { float tmp = expected[3]; expected[3] = expected[2]; expected[2] = expected[1]; expected[1] = expected[0]; expected[0] = tmp; } if (expected[0] > 1.0) expected[0] = 1.0; if (expected[1] > 1.0) expected[1] = 1.0; if (expected[2] > 1.0) expected[2] = 1.0; if (expected[3] > 1.0) expected[3] = 1.0; if (!piglit_probe_pixel_rgba(16, 16, expected)) { fprintf(stderr, "Failure in alu_depth = %i\n", alu_depth); return PIGLIT_FAIL; } return PIGLIT_PASS; } enum piglit_result piglit_display(void) { enum piglit_result result; unsigned int alu_depth; piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE); glClear(GL_COLOR_BUFFER_BIT); alu_depth = 1; for(;;) { result = test(alu_depth); if (result == PIGLIT_SKIP) break; if (result != PIGLIT_PASS) return result; if (alu_depth < 8) { alu_depth++; } else { /* Not quite powers of two to avoid aliasing */ alu_depth = (alu_depth * 2) - 5; } } return PIGLIT_PASS; } void piglit_init(int argc, char ** argv) { piglit_require_fragment_program(); glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, &max_alu_instructions); printf("Max (native) ALU instructions: %i\n", max_alu_instructions); }