blob: 2ae24e09d317063680042ad997bee58b6e4fc726 [file] [log] [blame]
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001// XGL tests
2//
3// Copyright (C) 2014 LunarG, Inc.
4//
5// Permission is hereby granted, free of charge, to any person obtaining a
6// copy of this software and associated documentation files (the "Software"),
7// to deal in the Software without restriction, including without limitation
8// the rights to use, copy, modify, merge, publish, distribute, sublicense,
9// and/or sell copies of the Software, and to permit persons to whom the
10// Software is furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included
13// in all copies or substantial portions of the 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#include "xgltestframework.h"
24#include "GL/freeglut_std.h"
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060025//#include "ShaderLang.h"
26#include "GlslangToBil.h"
27#include <math.h>
28
29// Command-line options
30enum TOptions {
31 EOptionNone = 0x000,
32 EOptionIntermediate = 0x001,
33 EOptionSuppressInfolog = 0x002,
34 EOptionMemoryLeakMode = 0x004,
35 EOptionRelaxedErrors = 0x008,
36 EOptionGiveWarnings = 0x010,
37 EOptionLinkProgram = 0x020,
38 EOptionMultiThreaded = 0x040,
39 EOptionDumpConfig = 0x080,
40 EOptionDumpReflection = 0x100,
41 EOptionSuppressWarnings = 0x200,
42 EOptionDumpVersions = 0x400,
43 EOptionBil = 0x800,
44 EOptionDefaultDesktop = 0x1000,
45};
46
47#ifndef _WIN32
48
49#include <errno.h>
50
51int fopen_s(
52 FILE** pFile,
53 const char* filename,
54 const char* mode
55)
56{
57 if (!pFile || !filename || !mode) {
58 return EINVAL;
59 }
60
61 FILE* f = fopen(filename, mode);
62 if (! f) {
63 if (errno != 0) {
64 return errno;
65 } else {
66 return ENOENT;
67 }
68 }
69 *pFile = f;
70
71 return 0;
72}
73
74#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -060075
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -060076// Set up environment for GLSL compiler
77// Must be done once per process
78void TestEnvironment::SetUp()
79{
80 // Initialize GLSL to BIL compiler utility
81 glslang::InitializeProcess();
82}
83
84void TestEnvironment::TearDown()
85{
86 glslang::FinalizeProcess();
87}
88
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -060089XglTestFramework::XglTestFramework() :
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060090 m_compile_options( 0 ),
91 m_num_shader_strings( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -060092{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -060093
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060094}
95
96XglTestFramework::~XglTestFramework()
97{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -060098
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -060099}
100
101// Define all the static elements
102bool XglTestFramework::m_show_images = false;
103bool XglTestFramework::m_save_images = false;
Courtney Goeltzenleuchterc44e3ee2014-10-31 14:13:33 -0600104bool XglTestFramework::m_use_bil = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600105int XglTestFramework::m_width = 0;
106int XglTestFramework::m_height = 0;
107int XglTestFramework::m_window = 0;
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600108bool XglTestFramework::m_glut_initialized = false;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600109std::list<XglTestImageRecord> XglTestFramework::m_images;
110std::list<XglTestImageRecord>::iterator XglTestFramework::m_display_image;
111int m_display_image_idx = 0;
112
113void XglTestFramework::InitArgs(int *argc, char *argv[])
114{
115 int i, n;
116
117 for (i=0, n=0; i< *argc; i++) {
118 if (strncmp("--show-images", argv[i], 13) == 0) {
119 m_show_images = true;
120 continue;
121 }
122 if (strncmp("--save-images", argv[i], 13) == 0) {
123 m_save_images = true;
124 continue;
125 }
126
Courtney Goeltzenleuchterb666dc62014-10-09 09:13:56 -0600127 if (strncmp("--use-BIL", argv[i], 13) == 0) {
128 m_use_bil = true;
129 continue;
130 }
131
Courtney Goeltzenleuchterc44e3ee2014-10-31 14:13:33 -0600132 if (strncmp("--no-BIL", argv[i], 13) == 0) {
133 m_use_bil = false;
134 continue;
135 }
136
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600137 /*
138 * Since the above "consume" inputs, update argv
139 * so that it contains the trimmed list of args for glutInit
140 */
141 argv[n] = argv[i];
142 n++;
143 }
144
145 if (m_show_images) {
146 glutInit(argc, argv);
147 }
148}
149
150void XglTestFramework::Reshape( int w, int h )
151{
152 if (!m_show_images) return; // Do nothing except save info if not enabled
153
154 // Resize window to be large enough to handle biggest image we've seen
155 // TODO: Probably need some sort of limits for the Window system.
156 if (w > m_width) {
157 m_width = w;
158 }
159 if (h > m_height) {
160 m_height = h;
161 }
162
163 glutReshapeWindow(m_width, m_height);
164
165 glViewport( 0, 0, m_width, m_height );
166 glMatrixMode( GL_PROJECTION );
167 glLoadIdentity();
168 glOrtho( 0.0, m_width, 0.0, m_height, 0.0, 2.0 );
169 glMatrixMode( GL_MODELVIEW );
170 glLoadIdentity();
171
172// glScissor(width/4, height/4, width/2, height/2);
173}
174
175void XglTestFramework::WritePPM( const char *basename, XglImage *image )
176{
177 string filename;
178 XGL_RESULT err;
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600179 int x, y;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600180
181 filename.append(basename);
182 filename.append(".ppm");
183
184 const XGL_IMAGE_SUBRESOURCE sr = {
185 XGL_IMAGE_ASPECT_COLOR, 0, 0
186 };
187 XGL_SUBRESOURCE_LAYOUT sr_layout;
Jon Ashburne494a1a2014-09-25 14:36:58 -0600188 XGL_UINT data_size = sizeof(sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600189
190 err = xglGetImageSubresourceInfo( image->image(), &sr,
191 XGL_INFO_TYPE_SUBRESOURCE_LAYOUT,
192 &data_size, &sr_layout);
193 ASSERT_XGL_SUCCESS( err );
194 ASSERT_EQ(data_size, sizeof(sr_layout));
195
196 const char *ptr;
197
198 err = xglMapMemory( image->memory(), 0, (XGL_VOID **) &ptr );
199 ASSERT_XGL_SUCCESS( err );
200
201 ptr += sr_layout.offset;
202
203 ofstream file (filename.c_str());
204 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
205
206 file << "P6\n";
207 file << image->width() << "\n";
208 file << image->height() << "\n";
209 file << 255 << "\n";
210
211 for (y = 0; y < image->height(); y++) {
212 const char *row = ptr;
213
214 for (x = 0; x < image->width(); x++) {
215 file.write(row, 3);
216 row += 4;
217 }
218
219 ptr += sr_layout.rowPitch;
220 }
221
222 file.close();
223
224 err = xglUnmapMemory( image->memory() );
225 ASSERT_XGL_SUCCESS( err );
226}
227
228void XglTestFramework::InitGLUT(int w, int h)
229{
230
231 if (!m_show_images) return;
232
233 if (!m_glut_initialized) {
234 glutInitWindowSize(w, h);
235
236 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
237 m_window = glutCreateWindow(NULL);
238 m_glut_initialized = true;
239 }
240
241 Reshape(w, h);
242}
243
244void XglTestFramework::Show(const char *comment, XglImage *image)
245{
246 XGL_RESULT err;
247
248 const XGL_IMAGE_SUBRESOURCE sr = {
249 XGL_IMAGE_ASPECT_COLOR, 0, 0
250 };
251 XGL_SUBRESOURCE_LAYOUT sr_layout;
Jon Ashburne494a1a2014-09-25 14:36:58 -0600252 XGL_UINT data_size = sizeof(sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600253
254 if (!m_show_images) return;
255
256 InitGLUT(image->width(), image->height());
257
258 err = xglGetImageSubresourceInfo( image->image(), &sr, XGL_INFO_TYPE_SUBRESOURCE_LAYOUT,
259 &data_size, &sr_layout);
260 ASSERT_XGL_SUCCESS( err );
261 ASSERT_EQ(data_size, sizeof(sr_layout));
262
263 const char *ptr;
264
265 err = image->MapMemory( (XGL_VOID **) &ptr );
266 ASSERT_XGL_SUCCESS( err );
267
268 ptr += sr_layout.offset;
269
270 XglTestImageRecord record;
271 record.m_title.append(comment);
272 record.m_width = image->width();
273 record.m_height = image->height();
274 // TODO: Need to make this more robust to handle different image formats
275 record.m_data_size = image->width()*image->height()*4;
276 record.m_data = malloc(record.m_data_size);
277 memcpy(record.m_data, ptr, record.m_data_size);
278 m_images.push_back(record);
279 m_display_image = --m_images.end();
280
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600281// Display();
282 glutPostRedisplay();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600283
284 err = image->UnmapMemory();
285 ASSERT_XGL_SUCCESS( err );
286}
287
288void XglTestFramework::RecordImage(XglImage *image)
289{
290 const ::testing::TestInfo* const test_info =
291 ::testing::UnitTest::GetInstance()->current_test_info();
292
293 if (m_save_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600294 WritePPM(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600295 }
296
297 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600298 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600299 }
300}
301
302void XglTestFramework::Display()
303{
304 glutSetWindowTitle(m_display_image->m_title.c_str());
305
306 glClearColor(0, 0, 0, 0);
307 glClear(GL_COLOR_BUFFER_BIT);
308 glRasterPos3f(0, 0, 0);
309 glBitmap(0, 0, 0, 0, 0, 0, NULL);
310 glDrawPixels(m_display_image->m_width, m_display_image->m_height,
311 GL_RGBA, GL_UNSIGNED_BYTE, m_display_image->m_data);
312
313 glutSwapBuffers();
314}
315
316void XglTestFramework::Key( unsigned char key, int x, int y )
317{
318 (void) x;
319 (void) y;
320 switch (key) {
321 case 27:
322 glutDestroyWindow(m_window);
323 exit(0);
324 break;
325 }
326 glutPostRedisplay();
327}
328
329void XglTestFramework::SpecialKey( int key, int x, int y )
330{
331 (void) x;
332 (void) y;
333 switch (key) {
334 case GLUT_KEY_UP:
335 case GLUT_KEY_RIGHT:
336 ++m_display_image;
337 if (m_display_image == m_images.end()) {
338 m_display_image = m_images.begin();
339 }
340 break;
341 case GLUT_KEY_DOWN:
342 case GLUT_KEY_LEFT:
343 if (m_display_image == m_images.begin()) {
344 m_display_image = --m_images.end();
345 } else {
346 --m_display_image;
347 }
348
349 break;
350 }
351 glutPostRedisplay();
352}
353
354void XglTestFramework::Finish()
355{
356 if (m_images.size() == 0) return;
357
358 glutReshapeFunc( Reshape );
359 glutKeyboardFunc( Key );
360 glutSpecialFunc( SpecialKey );
361 glutDisplayFunc( Display );
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600362 glutIdleFunc(NULL);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600363
364 glutMainLoop();
365}
366
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600367//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600368// These are the default resources for TBuiltInResources, used for both
369// - parsing this string for the case where the user didn't supply one
370// - dumping out a template for user construction of a config file
371//
372static const char* DefaultConfig =
373 "MaxLights 32\n"
374 "MaxClipPlanes 6\n"
375 "MaxTextureUnits 32\n"
376 "MaxTextureCoords 32\n"
377 "MaxVertexAttribs 64\n"
378 "MaxVertexUniformComponents 4096\n"
379 "MaxVaryingFloats 64\n"
380 "MaxVertexTextureImageUnits 32\n"
381 "MaxCombinedTextureImageUnits 80\n"
382 "MaxTextureImageUnits 32\n"
383 "MaxFragmentUniformComponents 4096\n"
384 "MaxDrawBuffers 32\n"
385 "MaxVertexUniformVectors 128\n"
386 "MaxVaryingVectors 8\n"
387 "MaxFragmentUniformVectors 16\n"
388 "MaxVertexOutputVectors 16\n"
389 "MaxFragmentInputVectors 15\n"
390 "MinProgramTexelOffset -8\n"
391 "MaxProgramTexelOffset 7\n"
392 "MaxClipDistances 8\n"
393 "MaxComputeWorkGroupCountX 65535\n"
394 "MaxComputeWorkGroupCountY 65535\n"
395 "MaxComputeWorkGroupCountZ 65535\n"
396 "MaxComputeWorkGroupSizeX 1024\n"
397 "MaxComputeWorkGroupSizeY 1024\n"
398 "MaxComputeWorkGroupSizeZ 64\n"
399 "MaxComputeUniformComponents 1024\n"
400 "MaxComputeTextureImageUnits 16\n"
401 "MaxComputeImageUniforms 8\n"
402 "MaxComputeAtomicCounters 8\n"
403 "MaxComputeAtomicCounterBuffers 1\n"
404 "MaxVaryingComponents 60\n"
405 "MaxVertexOutputComponents 64\n"
406 "MaxGeometryInputComponents 64\n"
407 "MaxGeometryOutputComponents 128\n"
408 "MaxFragmentInputComponents 128\n"
409 "MaxImageUnits 8\n"
410 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
411 "MaxCombinedShaderOutputResources 8\n"
412 "MaxImageSamples 0\n"
413 "MaxVertexImageUniforms 0\n"
414 "MaxTessControlImageUniforms 0\n"
415 "MaxTessEvaluationImageUniforms 0\n"
416 "MaxGeometryImageUniforms 0\n"
417 "MaxFragmentImageUniforms 8\n"
418 "MaxCombinedImageUniforms 8\n"
419 "MaxGeometryTextureImageUnits 16\n"
420 "MaxGeometryOutputVertices 256\n"
421 "MaxGeometryTotalOutputComponents 1024\n"
422 "MaxGeometryUniformComponents 1024\n"
423 "MaxGeometryVaryingComponents 64\n"
424 "MaxTessControlInputComponents 128\n"
425 "MaxTessControlOutputComponents 128\n"
426 "MaxTessControlTextureImageUnits 16\n"
427 "MaxTessControlUniformComponents 1024\n"
428 "MaxTessControlTotalOutputComponents 4096\n"
429 "MaxTessEvaluationInputComponents 128\n"
430 "MaxTessEvaluationOutputComponents 128\n"
431 "MaxTessEvaluationTextureImageUnits 16\n"
432 "MaxTessEvaluationUniformComponents 1024\n"
433 "MaxTessPatchComponents 120\n"
434 "MaxPatchVertices 32\n"
435 "MaxTessGenLevel 64\n"
436 "MaxViewports 16\n"
437 "MaxVertexAtomicCounters 0\n"
438 "MaxTessControlAtomicCounters 0\n"
439 "MaxTessEvaluationAtomicCounters 0\n"
440 "MaxGeometryAtomicCounters 0\n"
441 "MaxFragmentAtomicCounters 8\n"
442 "MaxCombinedAtomicCounters 8\n"
443 "MaxAtomicCounterBindings 1\n"
444 "MaxVertexAtomicCounterBuffers 0\n"
445 "MaxTessControlAtomicCounterBuffers 0\n"
446 "MaxTessEvaluationAtomicCounterBuffers 0\n"
447 "MaxGeometryAtomicCounterBuffers 0\n"
448 "MaxFragmentAtomicCounterBuffers 1\n"
449 "MaxCombinedAtomicCounterBuffers 1\n"
450 "MaxAtomicCounterBufferSize 16384\n"
451 "MaxTransformFeedbackBuffers 4\n"
452 "MaxTransformFeedbackInterleavedComponents 64\n"
453 "MaxCullDistances 8\n"
454 "MaxCombinedClipAndCullDistances 8\n"
455 "MaxSamples 4\n"
456
457 "nonInductiveForLoops 1\n"
458 "whileLoops 1\n"
459 "doWhileLoops 1\n"
460 "generalUniformIndexing 1\n"
461 "generalAttributeMatrixVectorIndexing 1\n"
462 "generalVaryingIndexing 1\n"
463 "generalSamplerIndexing 1\n"
464 "generalVariableIndexing 1\n"
465 "generalConstantMatrixVectorIndexing 1\n"
466 ;
467
468//
469// *.conf => this is a config file that can set limits/resources
470//
471bool XglTestFramework::SetConfigFile(const std::string& name)
472{
473 if (name.size() < 5)
474 return false;
475
476 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
477 ConfigFile = name;
478 return true;
479 }
480
481 return false;
482}
483
484//
485// Parse either a .conf file provided by the user or the default string above.
486//
487void XglTestFramework::ProcessConfigFile()
488{
489 char** configStrings = 0;
490 char* config = 0;
491 if (ConfigFile.size() > 0) {
492 configStrings = ReadFileData(ConfigFile.c_str());
493 if (configStrings)
494 config = *configStrings;
495 else {
496 printf("Error opening configuration file; will instead use the default configuration\n");
497 }
498 }
499
500 if (config == 0) {
501 config = new char[strlen(DefaultConfig) + 1];
502 strcpy(config, DefaultConfig);
503 }
504
505 const char* delims = " \t\n\r";
506 const char* token = strtok(config, delims);
507 while (token) {
508 const char* valueStr = strtok(0, delims);
509 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
510 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
511 return;
512 }
513 int value = atoi(valueStr);
514
515 if (strcmp(token, "MaxLights") == 0)
516 Resources.maxLights = value;
517 else if (strcmp(token, "MaxClipPlanes") == 0)
518 Resources.maxClipPlanes = value;
519 else if (strcmp(token, "MaxTextureUnits") == 0)
520 Resources.maxTextureUnits = value;
521 else if (strcmp(token, "MaxTextureCoords") == 0)
522 Resources.maxTextureCoords = value;
523 else if (strcmp(token, "MaxVertexAttribs") == 0)
524 Resources.maxVertexAttribs = value;
525 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
526 Resources.maxVertexUniformComponents = value;
527 else if (strcmp(token, "MaxVaryingFloats") == 0)
528 Resources.maxVaryingFloats = value;
529 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
530 Resources.maxVertexTextureImageUnits = value;
531 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
532 Resources.maxCombinedTextureImageUnits = value;
533 else if (strcmp(token, "MaxTextureImageUnits") == 0)
534 Resources.maxTextureImageUnits = value;
535 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
536 Resources.maxFragmentUniformComponents = value;
537 else if (strcmp(token, "MaxDrawBuffers") == 0)
538 Resources.maxDrawBuffers = value;
539 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
540 Resources.maxVertexUniformVectors = value;
541 else if (strcmp(token, "MaxVaryingVectors") == 0)
542 Resources.maxVaryingVectors = value;
543 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
544 Resources.maxFragmentUniformVectors = value;
545 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
546 Resources.maxVertexOutputVectors = value;
547 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
548 Resources.maxFragmentInputVectors = value;
549 else if (strcmp(token, "MinProgramTexelOffset") == 0)
550 Resources.minProgramTexelOffset = value;
551 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
552 Resources.maxProgramTexelOffset = value;
553 else if (strcmp(token, "MaxClipDistances") == 0)
554 Resources.maxClipDistances = value;
555 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
556 Resources.maxComputeWorkGroupCountX = value;
557 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
558 Resources.maxComputeWorkGroupCountY = value;
559 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
560 Resources.maxComputeWorkGroupCountZ = value;
561 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
562 Resources.maxComputeWorkGroupSizeX = value;
563 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
564 Resources.maxComputeWorkGroupSizeY = value;
565 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
566 Resources.maxComputeWorkGroupSizeZ = value;
567 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
568 Resources.maxComputeUniformComponents = value;
569 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
570 Resources.maxComputeTextureImageUnits = value;
571 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
572 Resources.maxComputeImageUniforms = value;
573 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
574 Resources.maxComputeAtomicCounters = value;
575 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
576 Resources.maxComputeAtomicCounterBuffers = value;
577 else if (strcmp(token, "MaxVaryingComponents") == 0)
578 Resources.maxVaryingComponents = value;
579 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
580 Resources.maxVertexOutputComponents = value;
581 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
582 Resources.maxGeometryInputComponents = value;
583 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
584 Resources.maxGeometryOutputComponents = value;
585 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
586 Resources.maxFragmentInputComponents = value;
587 else if (strcmp(token, "MaxImageUnits") == 0)
588 Resources.maxImageUnits = value;
589 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
590 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
591 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
592 Resources.maxCombinedShaderOutputResources = value;
593 else if (strcmp(token, "MaxImageSamples") == 0)
594 Resources.maxImageSamples = value;
595 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
596 Resources.maxVertexImageUniforms = value;
597 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
598 Resources.maxTessControlImageUniforms = value;
599 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
600 Resources.maxTessEvaluationImageUniforms = value;
601 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
602 Resources.maxGeometryImageUniforms = value;
603 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
604 Resources.maxFragmentImageUniforms = value;
605 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
606 Resources.maxCombinedImageUniforms = value;
607 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
608 Resources.maxGeometryTextureImageUnits = value;
609 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
610 Resources.maxGeometryOutputVertices = value;
611 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
612 Resources.maxGeometryTotalOutputComponents = value;
613 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
614 Resources.maxGeometryUniformComponents = value;
615 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
616 Resources.maxGeometryVaryingComponents = value;
617 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
618 Resources.maxTessControlInputComponents = value;
619 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
620 Resources.maxTessControlOutputComponents = value;
621 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
622 Resources.maxTessControlTextureImageUnits = value;
623 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
624 Resources.maxTessControlUniformComponents = value;
625 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
626 Resources.maxTessControlTotalOutputComponents = value;
627 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
628 Resources.maxTessEvaluationInputComponents = value;
629 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
630 Resources.maxTessEvaluationOutputComponents = value;
631 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
632 Resources.maxTessEvaluationTextureImageUnits = value;
633 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
634 Resources.maxTessEvaluationUniformComponents = value;
635 else if (strcmp(token, "MaxTessPatchComponents") == 0)
636 Resources.maxTessPatchComponents = value;
637 else if (strcmp(token, "MaxPatchVertices") == 0)
638 Resources.maxPatchVertices = value;
639 else if (strcmp(token, "MaxTessGenLevel") == 0)
640 Resources.maxTessGenLevel = value;
641 else if (strcmp(token, "MaxViewports") == 0)
642 Resources.maxViewports = value;
643 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
644 Resources.maxVertexAtomicCounters = value;
645 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
646 Resources.maxTessControlAtomicCounters = value;
647 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
648 Resources.maxTessEvaluationAtomicCounters = value;
649 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
650 Resources.maxGeometryAtomicCounters = value;
651 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
652 Resources.maxFragmentAtomicCounters = value;
653 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
654 Resources.maxCombinedAtomicCounters = value;
655 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
656 Resources.maxAtomicCounterBindings = value;
657 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
658 Resources.maxVertexAtomicCounterBuffers = value;
659 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
660 Resources.maxTessControlAtomicCounterBuffers = value;
661 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
662 Resources.maxTessEvaluationAtomicCounterBuffers = value;
663 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
664 Resources.maxGeometryAtomicCounterBuffers = value;
665 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
666 Resources.maxFragmentAtomicCounterBuffers = value;
667 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
668 Resources.maxCombinedAtomicCounterBuffers = value;
669 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
670 Resources.maxAtomicCounterBufferSize = value;
671 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
672 Resources.maxTransformFeedbackBuffers = value;
673 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
674 Resources.maxTransformFeedbackInterleavedComponents = value;
675 else if (strcmp(token, "MaxCullDistances") == 0)
676 Resources.maxCullDistances = value;
677 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
678 Resources.maxCombinedClipAndCullDistances = value;
679 else if (strcmp(token, "MaxSamples") == 0)
680 Resources.maxSamples = value;
681
682 else if (strcmp(token, "nonInductiveForLoops") == 0)
683 Resources.limits.nonInductiveForLoops = (value != 0);
684 else if (strcmp(token, "whileLoops") == 0)
685 Resources.limits.whileLoops = (value != 0);
686 else if (strcmp(token, "doWhileLoops") == 0)
687 Resources.limits.doWhileLoops = (value != 0);
688 else if (strcmp(token, "generalUniformIndexing") == 0)
689 Resources.limits.generalUniformIndexing = (value != 0);
690 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
691 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
692 else if (strcmp(token, "generalVaryingIndexing") == 0)
693 Resources.limits.generalVaryingIndexing = (value != 0);
694 else if (strcmp(token, "generalSamplerIndexing") == 0)
695 Resources.limits.generalSamplerIndexing = (value != 0);
696 else if (strcmp(token, "generalVariableIndexing") == 0)
697 Resources.limits.generalVariableIndexing = (value != 0);
698 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
699 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
700 else
701 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
702
703 token = strtok(0, delims);
704 }
705 if (configStrings)
706 FreeFileData(configStrings);
707}
708
709void XglTestFramework::SetMessageOptions(EShMessages& messages)
710{
711 if (m_compile_options & EOptionRelaxedErrors)
712 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
713 if (m_compile_options & EOptionIntermediate)
714 messages = (EShMessages)(messages | EShMsgAST);
715 if (m_compile_options & EOptionSuppressWarnings)
716 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
717}
718
719//
720// Malloc a string of sufficient size and read a string into it.
721//
722char** XglTestFramework::ReadFileData(const char* fileName)
723{
724 FILE *in;
725 #if defined(_WIN32) && defined(__GNUC__)
726 in = fopen(fileName, "r");
727 int errorCode = in ? 0 : 1;
728 #else
729 int errorCode = fopen_s(&in, fileName, "r");
730 #endif
731
732 char *fdata;
733 int count = 0;
734 const int maxSourceStrings = 5;
735 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
736
737 if (errorCode) {
738 printf("Error: unable to open input file: %s\n", fileName);
739 return 0;
740 }
741
742 while (fgetc(in) != EOF)
743 count++;
744
745 fseek(in, 0, SEEK_SET);
746
747 if (!(fdata = (char*)malloc(count+2))) {
748 printf("Error allocating memory\n");
749 return 0;
750 }
751 if (fread(fdata,1,count, in)!=count) {
752 printf("Error reading input file: %s\n", fileName);
753 return 0;
754 }
755 fdata[count] = '\0';
756 fclose(in);
757 if (count == 0) {
758 return_data[0]=(char*)malloc(count+2);
759 return_data[0][0]='\0';
760 m_num_shader_strings = 0;
761 return return_data;
762 } else
763 m_num_shader_strings = 1;
764
765 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
766 int ptr_len=0,i=0;
767 while(count>0){
768 return_data[i]=(char*)malloc(len+2);
769 memcpy(return_data[i],fdata+ptr_len,len);
770 return_data[i][len]='\0';
771 count-=(len);
772 ptr_len+=(len);
773 if(count<len){
774 if(count==0){
775 m_num_shader_strings=(i+1);
776 break;
777 }
778 len = count;
779 }
780 ++i;
781 }
782 return return_data;
783}
784
785void XglTestFramework::FreeFileData(char** data)
786{
787 for(int i=0;i<m_num_shader_strings;i++)
788 free(data[i]);
789}
790
791//
792// Deduce the language from the filename. Files must end in one of the
793// following extensions:
794//
795// .vert = vertex
796// .tesc = tessellation control
797// .tese = tessellation evaluation
798// .geom = geometry
799// .frag = fragment
800// .comp = compute
801//
802EShLanguage XglTestFramework::FindLanguage(const std::string& name)
803{
804 size_t ext = name.rfind('.');
805 if (ext == std::string::npos) {
806 return EShLangVertex;
807 }
808
809 std::string suffix = name.substr(ext + 1, std::string::npos);
810 if (suffix == "vert")
811 return EShLangVertex;
812 else if (suffix == "tesc")
813 return EShLangTessControl;
814 else if (suffix == "tese")
815 return EShLangTessEvaluation;
816 else if (suffix == "geom")
817 return EShLangGeometry;
818 else if (suffix == "frag")
819 return EShLangFragment;
820 else if (suffix == "comp")
821 return EShLangCompute;
822
823 return EShLangVertex;
824}
825
826//
827// Convert XGL shader type to compiler's
828//
829EShLanguage XglTestFramework::FindLanguage(const XGL_PIPELINE_SHADER_STAGE shader_type)
830{
831 switch (shader_type) {
832 case XGL_SHADER_STAGE_VERTEX:
833 return EShLangVertex;
834
835 case XGL_SHADER_STAGE_TESS_CONTROL:
836 return EShLangTessControl;
837
838 case XGL_SHADER_STAGE_TESS_EVALUATION:
839 return EShLangTessEvaluation;
840
841 case XGL_SHADER_STAGE_GEOMETRY:
842 return EShLangGeometry;
843
844 case XGL_SHADER_STAGE_FRAGMENT:
845 return EShLangFragment;
846
847 case XGL_SHADER_STAGE_COMPUTE:
848 return EShLangCompute;
849 }
850
851 return EShLangVertex;
852}
853
854
855//
856// Compile a given string containing GLSL into BIL for use by XGL
857// Return value of false means an error was encountered.
858//
859bool XglTestFramework::GLSLtoBIL(const XGL_PIPELINE_SHADER_STAGE shader_type,
860 const char *pshader,
861 std::vector<unsigned int> &bil)
862{
863 glslang::TProgram& program = *new glslang::TProgram;
864 const char *shaderStrings[1];
865
866 // TODO: Do we want to load a special config file depending on the
867 // shader source? Optional name maybe?
868 // SetConfigFile(fileName);
869
870 ProcessConfigFile();
871
872 EShMessages messages = EShMsgDefault;
873 SetMessageOptions(messages);
874
875 EShLanguage stage = FindLanguage(shader_type);
876 glslang::TShader* shader = new glslang::TShader(stage);
877
878 shaderStrings[0] = pshader;
879 shader->setStrings(shaderStrings, 1);
880
881 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
882
Cody Northrop195d6622014-11-03 12:54:37 -0700883 if (! (m_compile_options & EOptionSuppressInfolog)) {
884 puts(shader->getInfoLog());
885 puts(shader->getInfoDebugLog());
886 }
887
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600888 return false; // something didn't work
889 }
890
891 program.addShader(shader);
892
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600893
894 //
895 // Program-level processing...
896 //
897
Cody Northrop195d6622014-11-03 12:54:37 -0700898 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600899
Cody Northrop195d6622014-11-03 12:54:37 -0700900 if (! (m_compile_options & EOptionSuppressInfolog)) {
901 puts(shader->getInfoLog());
902 puts(shader->getInfoDebugLog());
903 }
904
905 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600906 }
907
908 if (m_compile_options & EOptionDumpReflection) {
909 program.buildReflection();
910 program.dumpReflection();
911 }
912
913 glslang::GlslangToBil(*program.getIntermediate(stage), bil);
914
915 return true;
916}
917
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600918
919
920XglTestImageRecord::XglTestImageRecord() : // Constructor
921 m_width( 0 ),
922 m_height( 0 ),
923 m_data( NULL )
924{
925 m_data_size = 0;
926}
927
928XglTestImageRecord::~XglTestImageRecord()
929{
930
931}
932
933XglTestImageRecord::XglTestImageRecord(const XglTestImageRecord &copyin) // Copy constructor to handle pass by value.
934{
935 m_title = copyin.m_title;
936 m_width = copyin.m_width;
937 m_height = copyin.m_height;
938 m_data_size = copyin.m_data_size;
939 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
940}
941
942ostream &operator<<(ostream &output, const XglTestImageRecord &XglTestImageRecord)
943{
944 output << XglTestImageRecord.m_title << " (" << XglTestImageRecord.m_width <<
945 "," << XglTestImageRecord.m_height << ")" << endl;
946 return output;
947}
948
949XglTestImageRecord& XglTestImageRecord::operator=(const XglTestImageRecord &rhs)
950{
951 m_title = rhs.m_title;
952 m_width = rhs.m_width;
953 m_height = rhs.m_height;
954 m_data_size = rhs.m_data_size;
955 m_data = rhs.m_data;
956 return *this;
957}
958
959int XglTestImageRecord::operator==(const XglTestImageRecord &rhs) const
960{
961 if( this->m_data != rhs.m_data) return 0;
962 return 1;
963}
964
965// This function is required for built-in STL list functions like sort
966int XglTestImageRecord::operator<(const XglTestImageRecord &rhs) const
967{
968 if( this->m_data_size < rhs.m_data_size ) return 1;
969 return 0;
970}
971