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