1 /*
2 * Copyright 2014 VMware, Inc.
3 *
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:
10 *
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
13 * Software.
14 *
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.
22 */
23
24 /**
25 * Test resource limits given the maximum supported by the implementation.
26 *
27 * Each component of the fragment output is derived using the following
28 * expression (indexed at the scalar level):
29 *
30 * result[i] = texture[i] * texture[i] * ... * attrib[i + l * numOutputs]
31 *
32 * Depending on the limits for vertex/fragment image units, the texture
33 * contribution will vary. See the generation of g_expected at the end of
34 * piglit_init.
35 *
36 * Since the scalar inputs are primes, multiplication will yield a unique
37 * result. Results can be diagnosed by evaluating for their missing factor(s).
38 *
39 * Matthew McClure
40 * 7 July 2014
41 */
42
43 #include "piglit-util-gl.h"
44
45 PIGLIT_GL_TEST_CONFIG_BEGIN
46
47 config.supports_gl_compat_version = 30;
48 config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGBA;
49 config.khr_no_error_support = PIGLIT_NO_ERRORS;
50
51 PIGLIT_GL_TEST_CONFIG_END
52
53
54 /*
55 * Definitions for the runtime behavior.
56 */
57 #define GLSL_VERSION "#version 130"
58 #define BUFFER_WIDTH 32
59 #define BUFFER_HEIGHT 32
60 #define MAX_SHADER_LINE_CHARS 256
61 #define MAX_SHADER_TEXT_CHARS 16*1024
62 #define MAX_COMPONENTS 4
63 #define MAX_EXPRESSION_OUTPUTS 1
64 #define MAX_EXPRESSION_ARGUMENTS 2
65 #define MAX_EXPRESSION_TEMPS 1
66 #define TEMP_TEXT_SIZE (MAX_EXPRESSION_OUTPUTS + \
67 MAX_EXPRESSION_ARGUMENTS + \
68 MAX_EXPRESSION_ARGUMENTS)
69
70 #define NUM_PRIMES 512
71 #define NUM_VERTICES 3
72
73 #define DEBUG_INPUT 0x01
74 #define DEBUG_READBACK 0x02
75 #define DEBUG_SHADERS 0x04
76 #define DEBUG_DRAW 0x08
77 #define DEBUG_DONT_CLAMP_MAX_VARYINGS 0x10
78
79 /*
80 * Type definitions for our working set.
81 */
82 enum {
83 DRAW_ARRAYS_VBO = 0,
84 DRAW_ELEMENTS_VBO = 1,
85 DRAW_IMMEDIATE = 2,
86 };
87
88 typedef struct MyVector4 {
89 float x, y, z, w;
90 } MyVector4;
91
92 typedef struct PackedTypeDesc {
93 char *typeName;
94 unsigned numComponents;
95 char *componentNames[MAX_COMPONENTS];
96 char *defaultValue;
97 } PackedTypeDesc;
98
99 typedef struct PackedDesc {
100 char *semanticName;
101 char *variableName;
102 bool isArray;
103 unsigned count;
104 const PackedTypeDesc *typeDesc;
105 } PackedDesc;
106
107
108 /*
109 * Global variables for the test's state.
110 */
111 static GLint g_maxVaryingFloats = 0;
112 static GLint g_maxVertexAttribs = 0;
113 static GLint g_maxVertexTextureImageUnits = 0;
114 static GLint g_maxTextureImageUnits = 0;
115 static GLint g_maxCombinedTextureImageUnits = 0;
116
117 static GLint g_maxAuxBuffers = 0;
118 static GLint g_maxDrawBuffers = 0;
119 static GLint g_maxColorAttachments = 0;
120
121 static GLint g_debugMask = 0x0;
122 static GLint g_drawMode = DRAW_IMMEDIATE;
123
124 static char *g_fragColor = "gl_FragColor";
125 static char *g_fragData = "gl_FragData";
126
127 static const GLfloat g_primes[NUM_PRIMES] = {
128 2.0, 3.0, 5.0, 7.0, 11.0, 13.0, 17.0, 19.0,
129 23.0, 29.0, 31.0, 37.0, 41.0, 43.0, 47.0, 53.0,
130 59.0, 61.0, 67.0, 71.0, 73.0, 79.0, 83.0, 89.0,
131 97.0, 101.0, 103.0, 107.0, 109.0, 113.0, 127.0, 131.0,
132 137.0, 139.0, 149.0, 151.0, 157.0, 163.0, 167.0, 173.0,
133 179.0, 181.0, 191.0, 193.0, 197.0, 199.0, 211.0, 223.0,
134 227.0, 229.0, 233.0, 239.0, 241.0, 251.0, 257.0, 263.0,
135 269.0, 271.0, 277.0, 281.0, 283.0, 293.0, 307.0, 311.0,
136 313.0, 317.0, 331.0, 337.0, 347.0, 349.0, 353.0, 359.0,
137 367.0, 373.0, 379.0, 383.0, 389.0, 397.0, 401.0, 409.0,
138 419.0, 421.0, 431.0, 433.0, 439.0, 443.0, 449.0, 457.0,
139 461.0, 463.0, 467.0, 479.0, 487.0, 491.0, 499.0, 503.0,
140 509.0, 521.0, 523.0, 541.0, 547.0, 557.0, 563.0, 569.0,
141 571.0, 577.0, 587.0, 593.0, 599.0, 601.0, 607.0, 613.0,
142 617.0, 619.0, 631.0, 641.0, 643.0, 647.0, 653.0, 659.0,
143 661.0, 673.0, 677.0, 683.0, 691.0, 701.0, 709.0, 719.0,
144 727.0, 733.0, 739.0, 743.0, 751.0, 757.0, 761.0, 769.0,
145 773.0, 787.0, 797.0, 809.0, 811.0, 821.0, 823.0, 827.0,
146 829.0, 839.0, 853.0, 857.0, 859.0, 863.0, 877.0, 881.0,
147 883.0, 887.0, 907.0, 911.0, 919.0, 929.0, 937.0, 941.0,
148 947.0, 953.0, 967.0, 971.0, 977.0, 983.0, 991.0, 997.0,
149 1009.0, 1013.0, 1019.0, 1021.0, 1031.0, 1033.0, 1039.0, 1049.0,
150 1051.0, 1061.0, 1063.0, 1069.0, 1087.0, 1091.0, 1093.0, 1097.0,
151 1103.0, 1109.0, 1117.0, 1123.0, 1129.0, 1151.0, 1153.0, 1163.0,
152 1171.0, 1181.0, 1187.0, 1193.0, 1201.0, 1213.0, 1217.0, 1223.0,
153 1229.0, 1231.0, 1237.0, 1249.0, 1259.0, 1277.0, 1279.0, 1283.0,
154 1289.0, 1291.0, 1297.0, 1301.0, 1303.0, 1307.0, 1319.0, 1321.0,
155 1327.0, 1361.0, 1367.0, 1373.0, 1381.0, 1399.0, 1409.0, 1423.0,
156 1427.0, 1429.0, 1433.0, 1439.0, 1447.0, 1451.0, 1453.0, 1459.0,
157 1471.0, 1481.0, 1483.0, 1487.0, 1489.0, 1493.0, 1499.0, 1511.0,
158 1523.0, 1531.0, 1543.0, 1549.0, 1553.0, 1559.0, 1567.0, 1571.0,
159 1579.0, 1583.0, 1597.0, 1601.0, 1607.0, 1609.0, 1613.0, 1619.0,
160 1621.0, 1627.0, 1637.0, 1657.0, 1663.0, 1667.0, 1669.0, 1693.0,
161 1697.0, 1699.0, 1709.0, 1721.0, 1723.0, 1733.0, 1741.0, 1747.0,
162 1753.0, 1759.0, 1777.0, 1783.0, 1787.0, 1789.0, 1801.0, 1811.0,
163 1823.0, 1831.0, 1847.0, 1861.0, 1867.0, 1871.0, 1873.0, 1877.0,
164 1879.0, 1889.0, 1901.0, 1907.0, 1913.0, 1931.0, 1933.0, 1949.0,
165 1951.0, 1973.0, 1979.0, 1987.0, 1993.0, 1997.0, 1999.0, 2003.0,
166 2011.0, 2017.0, 2027.0, 2029.0, 2039.0, 2053.0, 2063.0, 2069.0,
167 2081.0, 2083.0, 2087.0, 2089.0, 2099.0, 2111.0, 2113.0, 2129.0,
168 2131.0, 2137.0, 2141.0, 2143.0, 2153.0, 2161.0, 2179.0, 2203.0,
169 2207.0, 2213.0, 2221.0, 2237.0, 2239.0, 2243.0, 2251.0, 2267.0,
170 2269.0, 2273.0, 2281.0, 2287.0, 2293.0, 2297.0, 2309.0, 2311.0,
171 2333.0, 2339.0, 2341.0, 2347.0, 2351.0, 2357.0, 2371.0, 2377.0,
172 2381.0, 2383.0, 2389.0, 2393.0, 2399.0, 2411.0, 2417.0, 2423.0,
173 2437.0, 2441.0, 2447.0, 2459.0, 2467.0, 2473.0, 2477.0, 2503.0,
174 2521.0, 2531.0, 2539.0, 2543.0, 2549.0, 2551.0, 2557.0, 2579.0,
175 2591.0, 2593.0, 2609.0, 2617.0, 2621.0, 2633.0, 2647.0, 2657.0,
176 2659.0, 2663.0, 2671.0, 2677.0, 2683.0, 2687.0, 2689.0, 2693.0,
177 2699.0, 2707.0, 2711.0, 2713.0, 2719.0, 2729.0, 2731.0, 2741.0,
178 2749.0, 2753.0, 2767.0, 2777.0, 2789.0, 2791.0, 2797.0, 2801.0,
179 2803.0, 2819.0, 2833.0, 2837.0, 2843.0, 2851.0, 2857.0, 2861.0,
180 2879.0, 2887.0, 2897.0, 2903.0, 2909.0, 2917.0, 2927.0, 2939.0,
181 2953.0, 2957.0, 2963.0, 2969.0, 2971.0, 2999.0, 3001.0, 3011.0,
182 3019.0, 3023.0, 3037.0, 3041.0, 3049.0, 3061.0, 3067.0, 3079.0,
183 3083.0, 3089.0, 3109.0, 3119.0, 3121.0, 3137.0, 3163.0, 3167.0,
184 3169.0, 3181.0, 3187.0, 3191.0, 3203.0, 3209.0, 3217.0, 3221.0,
185 3229.0, 3251.0, 3253.0, 3257.0, 3259.0, 3271.0, 3299.0, 3301.0,
186 3307.0, 3313.0, 3319.0, 3323.0, 3329.0, 3331.0, 3343.0, 3347.0,
187 3359.0, 3361.0, 3371.0, 3373.0, 3389.0, 3391.0, 3407.0, 3413.0,
188 3433.0, 3449.0, 3457.0, 3461.0, 3463.0, 3467.0, 3469.0, 3491.0,
189 3499.0, 3511.0, 3517.0, 3527.0, 3529.0, 3533.0, 3539.0, 3541.0,
190 3547.0, 3557.0, 3559.0, 3571.0, 3581.0, 3583.0, 3593.0, 3607.0,
191 3613.0, 3617.0, 3623.0, 3631.0, 3637.0, 3643.0, 3659.0, 3671.0,
192 };
193
194 static const PackedTypeDesc g_rgbaDesc = {
195 "vec4", 4, { ".r", ".g", ".b", ".a" },
196 "vec4(1.0, 1.0, 1.0, 1.0)"
197 };
198
199 static const PackedTypeDesc g_vec4Desc = {
200 "vec4", 4, { ".x", ".y", ".z", ".w" },
201 "vec4(1.0, 1.0, 1.0, 1.0)"
202 };
203
204 static const PackedTypeDesc g_floatDesc = {
205 "float", 1, { "" },
206 "1.0"
207 };
208
209 static const PackedTypeDesc g_sampler2DDesc = {
210 "sampler2D", 4, { "" },
211 "vec4(1.0, 1.0, 1.0, 1.0)"
212 };
213
214 static const char *g_vectorComponents[MAX_COMPONENTS] = {
215 ".x", ".y", ".z", ".w"
216 };
217
218 //static const MyVector4 one = { 1.0f, 1.0f, 1.0f, 1.0f };
219 //static const MyVector4 zero = { 0.0f, 0.0f, 0.0f, 0.0f };
220
221 static const MyVector4 g_positionBuffer[NUM_VERTICES] = {
222 { -1.0, -1.0, 0.0, 0.0 },
223 { -1.0, 1.0, 0.0, 0.0 },
224 { 1.0, 1.0, 0.0, 0.0 }
225 };
226
227 static GLuint g_elementVBO;
228 static const GLushort g_elementBuffer[NUM_VERTICES] = { 0, 1, 2 };
229 static const char *g_vertexShaderText =
230 "#version 110 \n"
231 " \n"
232 "void main() \n"
233 "{ \n"
234 " gl_Position = gl_Vertex; \n"
235 "} \n";
236
237 //static char *g_geometryShaderText = NULL;
238
239 static const char *g_fragmentShaderText =
240 "#version 110 \n"
241 " \n"
242 "void main()\n"
243 "{ \n"
244 " gl_FragData[0] = vec4(1.0, 2.0, 3.0, 4.0);\n"
245 " gl_FragData[1] = vec4(5.0, 6.0, 7.0, 8.0);\n"
246 "} \n";
247
248 static GLuint g_program = 0;
249 static GLfloat *g_expected;
250
251
252 /**
253 * Format a string which contains the requested declaration for the variable.
254 * The desc structure will describe the variable, i.e. type, if it is an array,
255 * and how large the array is.
256 *
257 * \param desc Descriptor of the variable referenced. See PackedDesc.
258 * \param tmpStrSize Temporary string size for safe string formatting.
259 * \param tmpStr Temporary staging string.
260 * \param strSize Size of the formatted string.
261 * \param str An allocated temporary string for this function to populate with
262 * the reference expression.
263 * \return Pointer to str.
264 */
265
266 static char *
get_packed_decl(const PackedDesc * desc,const unsigned tmpStrSize,char * tmpStr,const unsigned strSize,char * str)267 get_packed_decl(const PackedDesc *desc,
268 const unsigned tmpStrSize,
269 char *tmpStr,
270 const unsigned strSize,
271 char *str)
272 {
273 int i = 0;
274
275 if (NULL == str) {
276 return "";
277 }
278
279 if (desc->isArray) {
280 snprintf(tmpStr, tmpStrSize,
281 "%s %s %s%s%u%s;\n",
282 desc->semanticName,
283 desc->typeDesc->typeName,
284 desc->variableName,
285 desc->isArray ? "[" : "",
286 desc->count,
287 desc->isArray ? "]" : "");
288 strncat(str, tmpStr, strSize - strlen(str));
289 } else if (desc->count > 1) {
290 for (i = 0; i < desc->count; i++) {
291 snprintf(tmpStr, tmpStrSize,
292 "%s %s %s%u;\n",
293 desc->semanticName,
294 desc->typeDesc->typeName,
295 desc->variableName, i);
296 strncat(str, tmpStr, strSize - strlen(str));
297 }
298 } else {
299 snprintf(tmpStr, tmpStrSize,
300 "%s %s %s;\n",
301 desc->semanticName,
302 desc->typeDesc->typeName,
303 desc->variableName);
304 strncat(str, tmpStr, strSize - strlen(str));
305 }
306
307 return str;
308 }
309
310
311 /**
312 * Format a string which contains the requested referenced value. The desc
313 * structure will describe the variable which is sub-indexed by arrayIndex.
314 * To address individual components, a componentIndex translated to (x,y,z,w)
315 * is applied to the textual representation.
316 *
317 * \param desc Descriptor of the variable referenced. See PackedDesc.
318 * \param arrayIndex Sub-index into the variable described by desc.
319 * \param componentIndex Component of the variable, depends on the desc
320 * configuration for the variable.
321 * \param str An allocated temporary string for this function to populate with
322 * the reference expression.
323 * \return Pointer to str.
324 */
325
326 static char *
get_packed_reference(const PackedDesc * desc,const unsigned arrayIndex,const unsigned componentIndex,const unsigned strSize,char * str)327 get_packed_reference(const PackedDesc *desc,
328 const unsigned arrayIndex,
329 const unsigned componentIndex,
330 const unsigned strSize,
331 char *str)
332 {
333 if (g_debugMask & DEBUG_INPUT) {
334 printf("desc=%p componentIndex=%u\n", desc, componentIndex);
335 printf("desc->typeDesc=%p\n", desc->typeDesc);
336 printf("desc->typeDesc->componentNames=%p\n",
337 desc->typeDesc->componentNames);
338 }
339
340 if (componentIndex > desc->typeDesc->numComponents) {
341 snprintf(str, strSize, "%s", g_floatDesc.defaultValue);
342 return str;
343 }
344
345 if (arrayIndex > desc->count) {
346 snprintf(str, strSize, "%s%s",
347 desc->typeDesc->defaultValue,
348 desc->typeDesc->componentNames[componentIndex]);
349 return str;
350 }
351
352 if (desc->count > 1) {
353 snprintf(str, strSize, "%s%s%u%s%s",
354 desc->variableName,
355 desc->isArray ? "[" : "",
356 arrayIndex,
357 desc->isArray ? "]" : "",
358 desc->typeDesc->componentNames[componentIndex]);
359 } else {
360 snprintf(str, strSize, "%s%s",
361 desc->variableName,
362 desc->typeDesc->componentNames[componentIndex]);
363 }
364
365 return str;
366 }
367
368
369 /**
370 * Set up an FBO for the test.
371 *
372 * \param colorTarget Color attachment index relative to GL_COLOR_ATTACHMENT0
373 * \param internalFormat Internal GL format for the pixel data.
374 * \param format GL format for the pixel data.
375 * \param formatType Data type for the pixel data.
376 * \param width Width of the requested FBO backing store.
377 * \param height Height of the requested FBO backing store.
378 * \param fbo FBO object allocated to bind with this texture.
379 * \param pTexture A pointer to the GLuint identifier storage for the allocated
380 * texture.
381 * \return true if the setup succeeded without error
382 * false otherwise.
383 */
384
385 static bool
setup_fbo_2d(const GLuint colorTarget,const GLenum internalFormat,const GLenum format,const GLenum formatType,const GLuint width,const GLuint height,const GLuint fbo,GLuint * pTexture)386 setup_fbo_2d(const GLuint colorTarget,
387 const GLenum internalFormat,
388 const GLenum format,
389 const GLenum formatType,
390 const GLuint width,
391 const GLuint height,
392 const GLuint fbo,
393 GLuint *pTexture)
394 {
395 GLenum status;
396
397 glGenTextures(1, pTexture);
398 glBindTexture(GL_TEXTURE_2D, *pTexture);
399 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
400 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
401 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0,
402 format, formatType, NULL);
403
404 /*
405 * Framebuffer object is implied to be bound.
406 */
407 glFramebufferTexture2D(GL_FRAMEBUFFER,
408 GL_COLOR_ATTACHMENT0 + colorTarget,
409 GL_TEXTURE_2D, *pTexture, 0);
410
411 if (!piglit_check_gl_error(GL_NO_ERROR)) {
412 fprintf(stderr, "Failed to create FBO %u.\n", colorTarget);
413 piglit_report_result(PIGLIT_FAIL);
414 return false;
415 }
416
417 status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
418 if (status != GL_FRAMEBUFFER_COMPLETE) {
419 fprintf(stderr, "Incomplete fbo for format %s.%s (status %s)\n",
420 piglit_get_gl_enum_name(internalFormat),
421 piglit_get_gl_enum_name(format),
422 piglit_get_gl_enum_name(status));
423 piglit_report_result(PIGLIT_FAIL);
424 return false;
425 }
426
427 return true;
428 }
429
430
431 /**
432 * Set up the vertex buffer objects and element buffer objects for the
433 * test. To ensure constant values across the primitive, populate the same
434 * prime attribute value in each vertex.
435 *
436 * \return true if the setup succeeded without error
437 * false otherwise.
438 */
439
440 static bool
setup_vertex_element_buffers(void)441 setup_vertex_element_buffers(void)
442 {
443 MyVector4 attrib[NUM_VERTICES];
444 GLuint buf;
445 GLuint attribLoc;
446 int i;
447
448 /*
449 * Setup the gl_Position attribute buffer.
450 */
451 glGenBuffers(1, &buf);
452 glBindBuffer(GL_ARRAY_BUFFER, buf);
453 glBufferData(GL_ARRAY_BUFFER, NUM_VERTICES*sizeof(MyVector4),
454 g_positionBuffer, GL_STATIC_DRAW);
455
456 attribLoc = glGetAttribLocation(g_program, "InPosition");
457 glEnableVertexAttribArray(attribLoc);
458 glVertexAttribPointer(attribLoc, 4, GL_FLOAT, GL_FALSE, 0, 0);
459 glBindBuffer(GL_ARRAY_BUFFER, 0);
460
461 /*
462 * Setup the vertex buffer objects.
463 */
464 for (i = 0; i < g_maxVertexAttribs - 1; i++) {
465 char strTemp[16];
466
467 if ((i + 1) * MAX_COMPONENTS < NUM_PRIMES) {
468 attrib[0].x = attrib[1].x =
469 attrib[2].x = g_primes[i*MAX_COMPONENTS + 0];
470 attrib[0].y = attrib[1].y =
471 attrib[2].y = g_primes[i*MAX_COMPONENTS + 1];
472 attrib[0].z = attrib[1].z =
473 attrib[2].z = g_primes[i*MAX_COMPONENTS + 2];
474 attrib[0].w = attrib[1].w =
475 attrib[2].w = g_primes[i*MAX_COMPONENTS + 3];
476 } else {
477 attrib[0].x = attrib[1].x = attrib[2].x = 1.0;
478 attrib[0].y = attrib[1].y = attrib[2].y = 1.0;
479 attrib[0].z = attrib[1].z = attrib[2].z = 1.0;
480 attrib[0].w = attrib[1].w = attrib[2].w = 1.0;
481 }
482
483 glGenBuffers(1, &buf);
484 glBindBuffer(GL_ARRAY_BUFFER, buf);
485 glBufferData(GL_ARRAY_BUFFER, sizeof(MyVector4)*NUM_VERTICES,
486 attrib, GL_STATIC_DRAW);
487
488 snprintf(strTemp, sizeof(strTemp), "InValue%u", i);
489 attribLoc = glGetAttribLocation(g_program, strTemp);
490 glEnableVertexAttribArray(attribLoc);
491 glVertexAttribPointer(attribLoc, 4, GL_FLOAT, GL_FALSE, 0, 0);
492 glBindBuffer(GL_ARRAY_BUFFER, 0);
493
494 if (!piglit_check_gl_error(GL_NO_ERROR)) {
495 fprintf(stderr, "Failed to create VBO %u.\n", i);
496 piglit_report_result(PIGLIT_FAIL);
497 return false;
498 }
499 }
500
501 /*
502 * Setup the element buffers.
503 */
504 glGenBuffers(1, &g_elementVBO);
505 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_elementVBO);
506 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(g_elementBuffer),
507 g_elementBuffer, GL_STATIC_DRAW);
508 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
509
510 if (!piglit_check_gl_error(GL_NO_ERROR)) {
511 fprintf(stderr, "Failed to create IBO.\n");
512 piglit_report_result(PIGLIT_FAIL);
513 return false;
514 }
515
516 return true;
517 }
518
519
520 /**
521 * Build a GLSL shader for the given packedInput, packedUniform, packedOutput
522 * descriptors. Each GLSL shader will have inputs, uniforms, and outputs. To
523 * ensure all bound resources are made resident, this shader must use all the
524 * inputs, uniforms, and outputs requested by the describing PackedDesc
525 * structures. If the number of outputs are smaller than the number of inputs,
526 * the inputs will map as follows:
527 *
528 * outputs[0] = uniforms[0] inputs[0] * ... * inputs[(i % numOutputs == 0)]
529 *
530 * where i >= numOutputs and represents a subsequent pass of inputs up
531 * until i == numInputs.
532 *
533 * If the number of outputs is larger than the number of inputs, the inputs
534 * and uniforms are referenced until exhausted. Once exhausted, an input
535 * or uniform will default to 1.0 to provide a multiplicative identity.
536 *
537 * \param packedInput A descriptor of the type and number of inputs to this
538 * shader.
539 * \param packedUniform A descriptor of the type and number of uniforms bound
540 * to the shader.
541 * \param packedOutput A descriptor of the type and number of outputs for this
542 * shader.
543 * \param outputDefaultSystemValue A required output for the GLSL shader.
544 * i.e. gl_Position for a vertex shader.
545 * \param defaultSystemValueDecl Pre-defined output declaration.
546 * \param defaultSystemValue Pre-defined output value.
547 * \param pShaderText Output pointer for the allocated and generated shader
548 * text.
549 * \return true if the setup succeeded without error
550 * false otherwise.
551 */
552
553 static bool
build_reduce_glsl_shader(const PackedDesc * packedInput,const PackedDesc * packedUniform,const PackedDesc * packedOutput,const char * outputDefaultSystemValue,const char * defaultSystemValueDecl,const char * defaultSystemValue,char ** pShaderText)554 build_reduce_glsl_shader(const PackedDesc *packedInput,
555 const PackedDesc *packedUniform,
556 const PackedDesc *packedOutput,
557 const char *outputDefaultSystemValue,
558 const char *defaultSystemValueDecl,
559 const char *defaultSystemValue,
560 char **pShaderText)
561 {
562 char *shaderTempText[TEMP_TEXT_SIZE];
563 char *shaderText = NULL;
564 unsigned shaderTextFree = 0;
565 unsigned numScalarInputs =
566 packedInput->count * packedInput->typeDesc->numComponents;
567 unsigned numScalarUniforms =
568 packedUniform->count * packedUniform->typeDesc->numComponents;
569 unsigned numScalarOutputs =
570 packedOutput->count * packedOutput->typeDesc->numComponents;
571
572 /* Prepare for reduction of input contributions to the output slots */
573 unsigned di_do = numScalarInputs / numScalarOutputs;
574 unsigned r = numScalarInputs % numScalarOutputs;
575 int i, j, k, l;
576
577 if (g_debugMask & DEBUG_INPUT) {
578 printf("di_do=%u r=%u\n", di_do, r);
579 }
580
581 for (i = 0; i < sizeof(shaderTempText) / sizeof(char *); i++) {
582 shaderTempText[i] = calloc(MAX_SHADER_LINE_CHARS, sizeof(char));
583
584 if (NULL == shaderTempText[i]) {
585 fprintf(stderr,
586 "Failed to allocate shader temporary text area\n");
587 piglit_report_result(PIGLIT_FAIL);
588 return false;
589 }
590 }
591
592 shaderText = calloc(MAX_SHADER_TEXT_CHARS, sizeof(char));
593 if (NULL == shaderText) {
594 fprintf(stderr, "Failed to allocate space for shader text\n");
595 piglit_report_result(PIGLIT_FAIL);
596 return false;
597 }
598
599 shaderTextFree = MAX_SHADER_TEXT_CHARS - 1;
600
601 snprintf(shaderTempText[0], MAX_SHADER_LINE_CHARS,
602 "%s\n", GLSL_VERSION);
603 strncat(shaderText, shaderTempText[0], shaderTextFree);
604 shaderTextFree -= strlen(shaderTempText[0]);
605
606 /*
607 * Declare the default system value input.
608 */
609 if (outputDefaultSystemValue) {
610 snprintf(shaderTempText[0], MAX_SHADER_LINE_CHARS,
611 "%s\n", defaultSystemValueDecl);
612 strncat(shaderText, shaderTempText[0], shaderTextFree);
613 shaderTextFree -= strlen(defaultSystemValueDecl);
614 }
615
616 /*
617 * Declare the input attributes.
618 */
619 get_packed_decl(packedInput,
620 MAX_SHADER_LINE_CHARS, shaderTempText[0],
621 MAX_SHADER_TEXT_CHARS, shaderText);
622
623 /*
624 * Declare the uniform samplers using the vertex texture functionality.
625 */
626 get_packed_decl(packedUniform,
627 MAX_SHADER_LINE_CHARS, shaderTempText[0],
628 MAX_SHADER_TEXT_CHARS, shaderText);
629
630 /*
631 * Declare the outputs.
632 */
633 if (packedOutput->semanticName) {
634 get_packed_decl(packedOutput,
635 MAX_SHADER_LINE_CHARS, shaderTempText[0],
636 MAX_SHADER_TEXT_CHARS, shaderText);
637 }
638
639 shaderTextFree = MAX_SHADER_TEXT_CHARS - strlen(shaderText);
640
641 /*
642 * Begin main program block.
643 */
644 snprintf(shaderTempText[0], MAX_SHADER_LINE_CHARS,
645 "void main()\n{\n");
646 strncat(shaderText, shaderTempText[0], shaderTextFree);
647 shaderTextFree -= strlen(shaderTempText[0]);
648
649 snprintf(shaderTempText[0], MAX_SHADER_LINE_CHARS,
650 " vec4 texel;\n");
651 strncat(shaderText, shaderTempText[0], shaderTextFree);
652 shaderTextFree -= strlen(shaderTempText[0]);
653
654 /*
655 * Passthru the attributes to the outputs.
656 */
657 i = j = k = l = 0;
658
659 while (i < numScalarOutputs) {
660 char *resultStr = " ", *srcStr = " ";
661
662 if ((i < packedUniform->count*packedUniform->typeDesc->numComponents) &&
663 (j % packedUniform->typeDesc->numComponents) == 0) {
664 snprintf(shaderTempText[0], MAX_SHADER_LINE_CHARS,
665 " texel = texture2D(Texture[%u], vec2(0.0, 0.0));\n",
666 i / packedUniform->typeDesc->numComponents);
667 strncat(shaderText, shaderTempText[0], shaderTextFree);
668 shaderTextFree -= strlen(shaderTempText[0]);
669 }
670
671 /*
672 * Iterate through the contents of the texel
673 */
674 resultStr = get_packed_reference(packedOutput,
675 (i / packedOutput->typeDesc->numComponents),
676 (i % packedOutput->typeDesc->numComponents),
677 MAX_SHADER_LINE_CHARS,
678 shaderTempText[1]);
679
680 /* Reset the temp string to avoid cumulative contributions. */
681 memset(shaderTempText[2], 0, MAX_SHADER_LINE_CHARS);
682
683 if (k < numScalarInputs) {
684 /* Reduce the scalar multiple of the input contributions. */
685 for (l = 0; l < di_do; l++) {
686 srcStr = get_packed_reference(packedInput,
687 (i + (l * numScalarOutputs)) /
688 packedInput->typeDesc->numComponents,
689 (i + (l * numScalarOutputs)) %
690 packedInput->typeDesc->numComponents,
691 MAX_SHADER_LINE_CHARS,
692 shaderTempText[3]);
693
694 if (l > 0) {
695 strncat(shaderTempText[2], " * ",
696 MAX_SHADER_LINE_CHARS - strlen(shaderTempText[2]));
697 }
698 strncat(shaderTempText[2], srcStr,
699 MAX_SHADER_LINE_CHARS - strlen(shaderTempText[2]));
700
701 k++;
702 }
703
704 /* Reduce the remaining scalar contributions until exhausted */
705 if (r) {
706 srcStr = get_packed_reference(packedInput,
707 (i + (l * numScalarOutputs)) /
708 packedInput->typeDesc->numComponents,
709 (i + (l * numScalarOutputs)) %
710 packedInput->typeDesc->numComponents,
711 MAX_SHADER_LINE_CHARS,
712 shaderTempText[3]);
713 if (l > 0) {
714 strncat(shaderTempText[2], " * ",
715 MAX_SHADER_LINE_CHARS - strlen(shaderTempText[2]));
716 }
717 strncat(shaderTempText[2], srcStr,
718 MAX_SHADER_LINE_CHARS - strlen(shaderTempText[2]));
719 k++;
720 r--;
721 }
722 srcStr = shaderTempText[2];
723 } else {
724 snprintf(shaderTempText[2], MAX_SHADER_LINE_CHARS,
725 "%s", g_floatDesc.defaultValue);
726 srcStr = shaderTempText[2];
727 }
728
729 if (j < numScalarUniforms) {
730 if ((g_debugMask & DEBUG_INPUT) && outputDefaultSystemValue) {
731 snprintf(shaderTempText[0], MAX_SHADER_LINE_CHARS,
732 " %s = texel%s;\n", resultStr,
733 g_vectorComponents[j %
734 packedUniform->typeDesc->numComponents]);
735 } else {
736 snprintf(shaderTempText[0], MAX_SHADER_LINE_CHARS,
737 " %s = texel%s * %s;\n", resultStr,
738 g_vectorComponents[j %
739 packedUniform->typeDesc->numComponents],
740 srcStr);
741 }
742 strncat(shaderText, shaderTempText[0], shaderTextFree);
743 shaderTextFree -= strlen(shaderTempText[0]);
744 j++;
745 } else {
746 snprintf(shaderTempText[0], MAX_SHADER_LINE_CHARS,
747 " %s = %s%s * %s;\n", resultStr,
748 packedUniform->typeDesc->defaultValue,
749 g_vectorComponents[0],
750 srcStr);
751 strncat(shaderText, shaderTempText[0], shaderTextFree);
752 shaderTextFree -= strlen(shaderTempText[0]);
753 }
754
755 /* Increment to the next output. */
756 i++;
757 }
758
759 /*
760 * End the main program block.
761 */
762 if (outputDefaultSystemValue) {
763 snprintf(shaderTempText[0], MAX_SHADER_LINE_CHARS,
764 " %s = %s;\n",
765 outputDefaultSystemValue, defaultSystemValue);
766 strncat(shaderText, shaderTempText[0], shaderTextFree);
767 shaderTextFree -= strlen(shaderTempText[0]);
768 }
769
770 snprintf(shaderTempText[0], MAX_SHADER_LINE_CHARS, "}\n");
771 strncat(shaderText, shaderTempText[0], shaderTextFree);
772 shaderTextFree -= strlen(shaderTempText[0]);
773
774 for (i = 0; i < sizeof(shaderTempText) / sizeof(char *); i++) {
775 if (shaderTempText[i]) {
776 free(shaderTempText[i]);
777 }
778 }
779
780 *pShaderText = shaderText;
781 return true;
782 }
783
784
785 /**
786 * Core piglit_display callback. This function will bind the FBOs, Textures,
787 * VBOs, IBOs, and draw a primitive using the GLSL shader generated by
788 * build_reduce_glsl_shader.
789 *
790 * Once rendered, a pixel from each of the color attachments is read back and
791 * compared to the final expression value stored in g_expected given the
792 * associated color attachment index.
793 *
794 * \return PIGLIT_PASS if the setup succeeded without error
795 * PIGLIT_FAIL otherwise.
796 */
797
798 enum piglit_result
piglit_display(void)799 piglit_display(void)
800 {
801 GLuint vao = 0;
802 GLuint fbo = 0;
803 GLuint *fboTextures = NULL;
804 GLenum *colorBuffers = NULL;
805 GLuint attribLoc;
806 GLfloat result[4];
807 int i = 0;
808
809 /*
810 * Reserve memory for the FBO texture objects.
811 */
812 fboTextures = calloc(g_maxColorAttachments, sizeof(GLuint));
813
814 if (NULL == fboTextures) {
815 fprintf(stderr, "Failed to create FBO texture object container.\n");
816 goto fail;
817 }
818
819 /*
820 * Build the color attachments
821 */
822 colorBuffers = calloc(g_maxColorAttachments, sizeof(GLenum));
823
824 if (NULL == colorBuffers) {
825 fprintf(stderr, "Failed to create draw buffers descriptor.\n");
826 goto fail;
827 }
828
829 /*
830 * Generate an FBO container to hold the color attachment hierarchy.
831 */
832 glGenFramebuffers(1, &fbo);
833 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
834
835 for (i = 0; i < g_maxColorAttachments; i++) {
836 setup_fbo_2d(i, GL_RGBA32F, GL_RGBA, GL_FLOAT,
837 BUFFER_WIDTH, BUFFER_HEIGHT,
838 fbo, &fboTextures[i]);
839 colorBuffers[i] = GL_COLOR_ATTACHMENT0 + i;
840 }
841
842 /*
843 * Build the textures sampled by the shaders
844 */
845 for (i = 0; i < g_maxCombinedTextureImageUnits; i++) {
846 GLuint tex;
847 GLuint uniformLoc;
848 char strTemp[16];
849
850 glGenTextures(1, &tex);
851 glActiveTexture(GL_TEXTURE0 + i);
852 glBindTexture(GL_TEXTURE_2D, tex);
853 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
854 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
855
856 if (((i+1) * MAX_COMPONENTS) > sizeof(g_primes)) {
857 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0,
858 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
859 } else {
860 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0,
861 GL_RGBA, GL_FLOAT,
862 &g_primes[i * MAX_COMPONENTS]);
863 }
864
865 if (!piglit_check_gl_error(GL_NO_ERROR)) {
866 fprintf(stderr, "Failed to create texture %u.\n", i);
867 goto fail;
868 }
869
870 snprintf(strTemp, sizeof(strTemp), "Texture[%u]", i);
871 uniformLoc = glGetUniformLocation(g_program, strTemp);
872 glUniform1i(uniformLoc, i);
873
874 if (!piglit_check_gl_error(GL_NO_ERROR)) {
875 fprintf(stderr, "Unable to assign texture %u uniform.\n", i);
876 goto fail;
877 }
878 }
879
880 /*
881 * Setup the vertex and element buffers for drawing our points.
882 */
883 if (g_drawMode != DRAW_IMMEDIATE) {
884 glGenVertexArrays(1, &vao);
885 glBindVertexArray(vao);
886
887 if (!piglit_check_gl_error(GL_NO_ERROR)) {
888 fprintf(stderr, "Unable to create VAO.\n");
889 goto fail;
890 }
891
892 setup_vertex_element_buffers();
893 }
894
895 /*
896 * Setup the raster state.
897 */
898 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
899 glDrawBuffers(g_maxColorAttachments, colorBuffers);
900
901 if (!piglit_check_gl_error(GL_NO_ERROR)) {
902 fprintf(stderr, "Unable to assign draw buffers.\n");
903 goto fail;
904 }
905
906 glClearColor(0.0, 1.0, 0.0, 0.0);
907 glClear(GL_COLOR_BUFFER_BIT);
908
909 /*
910 * Bind the vertex array and enable each attribute.
911 */
912 if (g_drawMode != DRAW_IMMEDIATE) {
913 glBindVertexArray(vao);
914 attribLoc = glGetAttribLocation(g_program, "InPosition");
915 glEnableVertexAttribArray(attribLoc);
916
917 if (!piglit_check_gl_error(GL_NO_ERROR)) {
918 fprintf(stderr,
919 "Unable to enable vertex array attribute %u.\n",
920 attribLoc);
921 goto fail;
922 }
923
924 /*
925 * Enable the rest of the attributes.
926 */
927 for (i = 0; i < g_maxVertexAttribs - 1; i++) {
928 char strTemp[16];
929
930 snprintf(strTemp, sizeof(strTemp), "InValue%u", i);
931 attribLoc = glGetAttribLocation(g_program, strTemp);
932 glEnableVertexAttribArray(attribLoc);
933
934 if (!piglit_check_gl_error(GL_NO_ERROR)) {
935 fprintf(stderr,
936 "Unable to enable vertex array attribute %u.\n",
937 attribLoc);
938 goto fail;
939 }
940 }
941
942 if (g_drawMode == DRAW_ARRAYS_VBO) {
943 if (g_debugMask & DEBUG_DRAW) {
944 fprintf(stderr, "Draw mode DRAW_ARRAYS_VBO\n");
945 }
946 glDrawArrays(GL_TRIANGLES, 0, NUM_VERTICES);
947 }
948
949 if (g_drawMode == DRAW_ELEMENTS_VBO) {
950 if (g_debugMask & DEBUG_DRAW) {
951 fprintf(stderr,
952 "Draw mode DRAW_ELEMENTS_VBO\n");
953 }
954 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_elementVBO);
955 glDrawElements(GL_TRIANGLES, NUM_VERTICES,
956 GL_UNSIGNED_SHORT, 0);
957 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
958 }
959
960 /*
961 * Blindly reset all the attributes.
962 */
963 for (i = 0; i < g_maxVertexAttribs; i++) {
964 glDisableVertexAttribArray(i);
965 }
966 } else {
967 glBegin(GL_TRIANGLES);
968 glVertex3f(-1.0, -1.0, 0.0);
969 glVertex3f(-1.0, 1.0, 0.0);
970 glVertex3f(1.0, 1.0, 0.0);
971 glEnd();
972 }
973
974 if (!piglit_check_gl_error(GL_NO_ERROR))
975 goto fail;
976
977 /*
978 * Read back the FBO contents.
979 */
980
981 /*
982 * Disable color clamping so we don't encounter result
983 * collisions attempting to use a normalized color space.
984 *
985 * Requires OpenGL 3.0
986 */
987 glClampColor(GL_CLAMP_READ_COLOR, GL_FALSE);
988
989 for (i = 0; i < g_maxColorAttachments; i++) {
990 if (g_debugMask & DEBUG_READBACK) {
991 printf("GL_READ_FRAMEBUFFER <- fbo=%u\n", fbo);
992 }
993
994 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
995
996 if (!piglit_check_gl_error(GL_NO_ERROR))
997 goto fail;
998
999 glFramebufferTexture2D(GL_READ_FRAMEBUFFER,
1000 GL_COLOR_ATTACHMENT0,
1001 GL_TEXTURE_2D,
1002 fboTextures[i],
1003 0);
1004
1005 if (!piglit_check_gl_error(GL_NO_ERROR))
1006 goto fail;
1007
1008 glPixelStorei(GL_PACK_ALIGNMENT, 1);
1009 glReadBuffer(GL_COLOR_ATTACHMENT0);
1010
1011 if (!piglit_check_gl_error(GL_NO_ERROR))
1012 goto fail;
1013
1014 glReadPixels(0, BUFFER_HEIGHT - 1,
1015 1, 1, GL_RGBA, GL_FLOAT, result);
1016
1017 if ((g_expected[(i * MAX_COMPONENTS) + 0] != result[0]) ||
1018 (g_expected[(i * MAX_COMPONENTS) + 1] != result[1]) ||
1019 (g_expected[(i * MAX_COMPONENTS) + 2] != result[2]) ||
1020 (g_expected[(i * MAX_COMPONENTS) + 3] != result[3])) {
1021 fprintf(stderr, "GL_COLOR_ATTACHMENT%u: expected "
1022 "(%f, %f, %f, %f) != (%f, %f, %f, %f)\n",
1023 i, g_expected[(i * MAX_COMPONENTS) + 0],
1024 g_expected[(i * MAX_COMPONENTS) + 1],
1025 g_expected[(i * MAX_COMPONENTS) + 2],
1026 g_expected[(i * MAX_COMPONENTS) + 3],
1027 result[0], result[1], result[2], result[3]);
1028
1029 goto fail;
1030 }
1031 }
1032
1033 piglit_present_results();
1034
1035 /*
1036 * Cleanup the allocations.
1037 */
1038 free(colorBuffers);
1039 free(fboTextures);
1040
1041 piglit_report_result(PIGLIT_PASS);
1042
1043 return PIGLIT_PASS;
1044
1045 fail:
1046
1047 if (colorBuffers)
1048 free(colorBuffers);
1049
1050 if (fboTextures)
1051 free(fboTextures);
1052
1053 piglit_report_result(PIGLIT_FAIL);
1054
1055 return PIGLIT_FAIL;
1056 }
1057
1058
1059 /**
1060 * Core piglit_init callback. This function will query the implementation for
1061 * the maximum number of supported resources. We attempt to create a GLSL
1062 * shader which references all supported resources bindable within the GL 3.0
1063 * specification.
1064 *
1065 * Each resource will be populated with a unique prime value. This function is
1066 * also responsible for calculating the expected value and storing this in
1067 * the g_expected array.
1068 *
1069 * Note: If the number of primes is insufficient to assign a unique prime to
1070 * each resource, we will exit with PIGLIT_SKIP.
1071 *
1072 * Results: PIGLIT_PASS if the setup succeeded without error
1073 * PIGLIT_FAIL otherwise.
1074 */
1075
1076 void
piglit_init(int argc,char ** argv)1077 piglit_init(int argc, char **argv)
1078 {
1079 GLfloat *var;
1080 PackedDesc vsInput = { "in", "InValue", false, 0, &g_vec4Desc };
1081 PackedDesc vsUniform = { "uniform", "Texture", true, 0, &g_sampler2DDesc };
1082 PackedDesc vsOutput = { "out", "Variable", true, 0, &g_floatDesc };
1083 PackedDesc fsInput = { "in", "Variable", true, 0, &g_floatDesc };
1084 PackedDesc fsUniform = { "uniform", "Texture", true, 0, &g_sampler2DDesc };
1085 PackedDesc fsOutput = { NULL, g_fragData, true, 0, &g_rgbaDesc };
1086 char shaderTempText[MAX_SHADER_LINE_CHARS];
1087 char *vertexShaderText = (char *)g_vertexShaderText;
1088 char *fragmentShaderText = (char *)g_fragmentShaderText;
1089 int i = 0;
1090
1091 piglit_require_gl_version(30);
1092
1093 for (i = 1; i < argc; i++) {
1094 if (strcmp(argv[i], "-drawArraysVBO") == 0) {
1095 g_drawMode = DRAW_ARRAYS_VBO;
1096 }
1097 if (strcmp(argv[i], "-drawElementsVBO") == 0) {
1098 g_drawMode = DRAW_ELEMENTS_VBO;
1099 }
1100 if (strcmp(argv[i], "-drawImmediate") == 0) {
1101 g_drawMode = DRAW_IMMEDIATE;
1102 }
1103 if (strcmp(argv[i], "-debugInput") == 0) {
1104 g_debugMask |= DEBUG_INPUT;
1105 }
1106 if (strcmp(argv[i], "-debugReadback") == 0) {
1107 g_debugMask |= DEBUG_READBACK;
1108 }
1109 if (strcmp(argv[i], "-debugShaders") == 0) {
1110 g_debugMask |= DEBUG_SHADERS;
1111 }
1112 if (strcmp(argv[i], "-debugDraw") == 0) {
1113 g_debugMask |= DEBUG_DRAW;
1114 }
1115 if (strcmp(argv[i], "-dontClampMaxVaryings") == 0) {
1116 g_debugMask |= DEBUG_DONT_CLAMP_MAX_VARYINGS;
1117 }
1118 }
1119
1120 /*
1121 * Query the sampler capabilities.
1122 */
1123 glGetIntegerv(GL_MAX_VARYING_FLOATS, &g_maxVaryingFloats);
1124 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &g_maxVertexAttribs);
1125 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
1126 &g_maxVertexTextureImageUnits);
1127 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,
1128 &g_maxTextureImageUnits);
1129 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
1130 &g_maxCombinedTextureImageUnits);
1131
1132 printf("GL_MAX_VARYING_FLOATS: %d\n", g_maxVaryingFloats);
1133 printf("GL_MAX_VERTEX_ATTRIBS: %d\n", g_maxVertexAttribs);
1134 printf("GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: %d\n",
1135 g_maxVertexTextureImageUnits);
1136 printf("GL_MAX_TEXTURE_IMAGE_UNITS: %d\n",
1137 g_maxTextureImageUnits);
1138 printf("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: %d\n",
1139 g_maxCombinedTextureImageUnits);
1140
1141 /*
1142 * Query the render target capabilities.
1143 */
1144 glGetIntegerv(GL_AUX_BUFFERS, &g_maxAuxBuffers);
1145 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &g_maxDrawBuffers);
1146 glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &g_maxColorAttachments);
1147
1148 if (g_maxColorAttachments == 1) {
1149 fsOutput.variableName = g_fragColor;
1150 }
1151
1152 printf("GL_AUX_BUFFERS: %d\n", g_maxAuxBuffers);
1153 printf("GL_MAX_DRAW_BUFFERS: %d\n", g_maxDrawBuffers);
1154 printf("GL_MAX_COLOR_ATTACHMENTS: %d\n", g_maxColorAttachments);
1155
1156 if ((g_maxColorAttachments * MAX_COMPONENTS > NUM_PRIMES) ||
1157 (g_maxVaryingFloats > NUM_PRIMES) ||
1158 (g_maxVertexAttribs * MAX_COMPONENTS > NUM_PRIMES) ||
1159 (g_maxVertexTextureImageUnits * MAX_COMPONENTS > NUM_PRIMES) ||
1160 (g_maxTextureImageUnits * MAX_COMPONENTS > NUM_PRIMES)) {
1161 fprintf(stderr, "Unable to uniquely represent a result path.\n");
1162 piglit_report_result(PIGLIT_SKIP);
1163 }
1164
1165 /*
1166 * Clamp the max varyings by default to work around large array
1167 * issues with some GLSL implementations.
1168 */
1169 if ((g_debugMask & DEBUG_DONT_CLAMP_MAX_VARYINGS) == 0) {
1170 g_maxVaryingFloats = MIN2(g_maxVaryingFloats, 32);
1171 fprintf(stderr, "Clamped max varying floats to %u.\n",
1172 g_maxVaryingFloats);
1173 }
1174
1175 if (g_drawMode == DRAW_IMMEDIATE) {
1176 g_maxVertexAttribs = 1;
1177 fprintf(stderr,
1178 "Immediate mode selected, using only one vertex attrib.\n");
1179 }
1180
1181 /*
1182 * Build the shaders based upon the queried limits.
1183 */
1184 vsInput.count = g_maxVertexAttribs - 1;
1185 vsUniform.count = g_maxVertexTextureImageUnits;
1186 vsOutput.count = g_maxVaryingFloats;
1187 if (!build_reduce_glsl_shader(&vsInput,
1188 &vsUniform,
1189 &vsOutput,
1190 "gl_Position",
1191 "in vec4 InPosition;",
1192 "InPosition",
1193 &vertexShaderText)) {
1194 fprintf(stderr, "Failed to build GLSL vertex shader\n");
1195 piglit_report_result(PIGLIT_SKIP);
1196 }
1197
1198 if (g_debugMask & DEBUG_SHADERS) {
1199 printf("vertexShaderText:\n%s", vertexShaderText);
1200 }
1201
1202 fsInput.count = g_maxVaryingFloats;
1203 fsUniform.count = g_maxTextureImageUnits;
1204 fsOutput.count = g_maxColorAttachments;
1205 if (!build_reduce_glsl_shader(&fsInput,
1206 &fsUniform,
1207 &fsOutput,
1208 NULL,
1209 NULL,
1210 NULL,
1211 &fragmentShaderText)) {
1212 fprintf(stderr, "Failed to build GLSL vertex shader\n");
1213 piglit_report_result(PIGLIT_SKIP);
1214 }
1215
1216 if (g_debugMask & DEBUG_SHADERS) {
1217 printf("fragmentShaderText:\n%s", fragmentShaderText);
1218 }
1219
1220 /*
1221 * Build the vertex and fragment shaders.
1222 */
1223 g_program = piglit_build_simple_program(vertexShaderText,
1224 fragmentShaderText);
1225 if (!g_program) {
1226 fprintf(stderr, "Failed to compile/link program\n");
1227 piglit_report_result(PIGLIT_SKIP);
1228 }
1229
1230 snprintf(shaderTempText, sizeof(shaderTempText), "InPosition");
1231 glBindAttribLocation(g_program, 0, shaderTempText);
1232
1233 for (i = 0; i < g_maxVertexAttribs - 1; i++) {
1234 snprintf(shaderTempText, sizeof(shaderTempText), "InValue%u", i);
1235 glBindAttribLocation(g_program, i+1, shaderTempText);
1236 }
1237
1238 if (g_debugMask & DEBUG_SHADERS) {
1239 printf("Linking program...\n");
1240 }
1241
1242 glLinkProgram(g_program);
1243 glUseProgram(g_program);
1244
1245 if (!piglit_check_gl_error(GL_NO_ERROR)) {
1246 fprintf(stderr, "Failure to link shaders\n");
1247 fprintf(stderr, "vertexShaderText:\n%s", vertexShaderText);
1248 fprintf(stderr, "fragmentShaderText:\n%s", fragmentShaderText);
1249 free(vertexShaderText);
1250 free(fragmentShaderText);
1251 piglit_report_result(PIGLIT_FAIL);
1252 }
1253
1254 if (g_debugMask & DEBUG_SHADERS) {
1255 printf("Using program %u...\n", g_program);
1256 }
1257
1258 /* Delete the interim copies generated by build_reduce_glsl_shader */
1259 free(vertexShaderText);
1260 free(fragmentShaderText);
1261
1262 /*
1263 * Calculate the expected results for the bound resource limits.
1264 */
1265 var = calloc(g_maxVaryingFloats, sizeof(GLfloat));
1266
1267 if (NULL == var) {
1268 fprintf(stderr,
1269 "Failed to allocate temporary array for expected calculation.\n");
1270 piglit_report_result(PIGLIT_FAIL);
1271 }
1272
1273 g_expected = calloc(g_maxColorAttachments, sizeof(GLfloat)*MAX_COMPONENTS);
1274
1275 if (NULL == g_expected) {
1276 fprintf(stderr, "Failed to allocate array for expected calculation.\n");
1277 piglit_report_result(PIGLIT_FAIL);
1278 }
1279
1280 /*
1281 * Sampler coverage up to the total number of varying floats.
1282 */
1283 for (i = 0; i < g_maxVaryingFloats; i++) {
1284 if ((i < g_maxVertexTextureImageUnits*MAX_COMPONENTS) &&
1285 (i < NUM_PRIMES)) {
1286 var[i] = g_primes[i];
1287 } else {
1288 var[i] = 1.0;
1289 }
1290 }
1291
1292 /*
1293 * Multiply in all vertex attributes.
1294 */
1295 i = 0;
1296 while (i < (g_maxVertexAttribs-1)*MAX_COMPONENTS) {
1297 if (i < NUM_PRIMES) {
1298 var[i % g_maxVaryingFloats] *= g_primes[i];
1299 } else {
1300 var[i % g_maxVaryingFloats] *= 1.0;
1301 }
1302 i++;
1303 }
1304
1305 /*
1306 * Calculate the expected values for the FS stage.
1307 *
1308 * Sampler cover up to the total number of varying floats.
1309 */
1310 for (i = 0; i < g_maxColorAttachments*MAX_COMPONENTS; i++) {
1311 if ((i < g_maxVertexTextureImageUnits*MAX_COMPONENTS) &&
1312 (i < NUM_PRIMES)) {
1313 g_expected[i] = g_primes[i];
1314 } else {
1315 g_expected[i] = 1.0;
1316 }
1317 }
1318
1319 /*
1320 * Multiply in all the varying contributions generated by the VS.
1321 */
1322 i = 0;
1323 while (i < g_maxVaryingFloats) {
1324 g_expected[i % (g_maxColorAttachments*MAX_COMPONENTS)] *= var[i];
1325 i++;
1326 }
1327
1328 for (i = 0; i < g_maxColorAttachments; i++) {
1329 printf("g_expected[%u]=(%f, %f, %f, %f)\n", i,
1330 g_expected[(i * MAX_COMPONENTS) + 0],
1331 g_expected[(i * MAX_COMPONENTS) + 1],
1332 g_expected[(i * MAX_COMPONENTS) + 2],
1333 g_expected[(i * MAX_COMPONENTS) + 3]);
1334 }
1335
1336 free(var);
1337 }
1338