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