blob: 8015cb0f6ca1f1aeb41f102be4f2bca0c3f44ce3 [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_glut_initialized( false ),
91 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;
105int XglTestFramework::m_width = 0;
106int XglTestFramework::m_height = 0;
107int XglTestFramework::m_window = 0;
108std::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;
168 int x, y;
169
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
270 Display();
271
272 err = image->UnmapMemory();
273 ASSERT_XGL_SUCCESS( err );
274}
275
276void XglTestFramework::RecordImage(XglImage *image)
277{
278 const ::testing::TestInfo* const test_info =
279 ::testing::UnitTest::GetInstance()->current_test_info();
280
281 if (m_save_images) {
282 WritePPM(test_info->test_case_name(), image);
283 }
284
285 if (m_show_images) {
286 Show(test_info->test_case_name(), image);
287 }
288}
289
290void XglTestFramework::Display()
291{
292 glutSetWindowTitle(m_display_image->m_title.c_str());
293
294 glClearColor(0, 0, 0, 0);
295 glClear(GL_COLOR_BUFFER_BIT);
296 glRasterPos3f(0, 0, 0);
297 glBitmap(0, 0, 0, 0, 0, 0, NULL);
298 glDrawPixels(m_display_image->m_width, m_display_image->m_height,
299 GL_RGBA, GL_UNSIGNED_BYTE, m_display_image->m_data);
300
301 glutSwapBuffers();
302}
303
304void XglTestFramework::Key( unsigned char key, int x, int y )
305{
306 (void) x;
307 (void) y;
308 switch (key) {
309 case 27:
310 glutDestroyWindow(m_window);
311 exit(0);
312 break;
313 }
314 glutPostRedisplay();
315}
316
317void XglTestFramework::SpecialKey( int key, int x, int y )
318{
319 (void) x;
320 (void) y;
321 switch (key) {
322 case GLUT_KEY_UP:
323 case GLUT_KEY_RIGHT:
324 ++m_display_image;
325 if (m_display_image == m_images.end()) {
326 m_display_image = m_images.begin();
327 }
328 break;
329 case GLUT_KEY_DOWN:
330 case GLUT_KEY_LEFT:
331 if (m_display_image == m_images.begin()) {
332 m_display_image = --m_images.end();
333 } else {
334 --m_display_image;
335 }
336
337 break;
338 }
339 glutPostRedisplay();
340}
341
342void XglTestFramework::Finish()
343{
344 if (m_images.size() == 0) return;
345
346 glutReshapeFunc( Reshape );
347 glutKeyboardFunc( Key );
348 glutSpecialFunc( SpecialKey );
349 glutDisplayFunc( Display );
350
351 glutMainLoop();
352}
353
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600354//
355// ShInitialize() should be called exactly once per process, not per thread.
356//
357//int XglTestFramework::ShInitialize()
358//{
359// glslang::InitGlobalLock();
360
361// if (! InitProcess())
362// return 0;
363
364// if (! PerProcessGPA)
365// PerProcessGPA = new TPoolAllocator();
366
367// glslang::TScanContext::fillInKeywordMap();
368
369// return 1;
370//}
371
372//
373// These are the default resources for TBuiltInResources, used for both
374// - parsing this string for the case where the user didn't supply one
375// - dumping out a template for user construction of a config file
376//
377static const char* DefaultConfig =
378 "MaxLights 32\n"
379 "MaxClipPlanes 6\n"
380 "MaxTextureUnits 32\n"
381 "MaxTextureCoords 32\n"
382 "MaxVertexAttribs 64\n"
383 "MaxVertexUniformComponents 4096\n"
384 "MaxVaryingFloats 64\n"
385 "MaxVertexTextureImageUnits 32\n"
386 "MaxCombinedTextureImageUnits 80\n"
387 "MaxTextureImageUnits 32\n"
388 "MaxFragmentUniformComponents 4096\n"
389 "MaxDrawBuffers 32\n"
390 "MaxVertexUniformVectors 128\n"
391 "MaxVaryingVectors 8\n"
392 "MaxFragmentUniformVectors 16\n"
393 "MaxVertexOutputVectors 16\n"
394 "MaxFragmentInputVectors 15\n"
395 "MinProgramTexelOffset -8\n"
396 "MaxProgramTexelOffset 7\n"
397 "MaxClipDistances 8\n"
398 "MaxComputeWorkGroupCountX 65535\n"
399 "MaxComputeWorkGroupCountY 65535\n"
400 "MaxComputeWorkGroupCountZ 65535\n"
401 "MaxComputeWorkGroupSizeX 1024\n"
402 "MaxComputeWorkGroupSizeY 1024\n"
403 "MaxComputeWorkGroupSizeZ 64\n"
404 "MaxComputeUniformComponents 1024\n"
405 "MaxComputeTextureImageUnits 16\n"
406 "MaxComputeImageUniforms 8\n"
407 "MaxComputeAtomicCounters 8\n"
408 "MaxComputeAtomicCounterBuffers 1\n"
409 "MaxVaryingComponents 60\n"
410 "MaxVertexOutputComponents 64\n"
411 "MaxGeometryInputComponents 64\n"
412 "MaxGeometryOutputComponents 128\n"
413 "MaxFragmentInputComponents 128\n"
414 "MaxImageUnits 8\n"
415 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
416 "MaxCombinedShaderOutputResources 8\n"
417 "MaxImageSamples 0\n"
418 "MaxVertexImageUniforms 0\n"
419 "MaxTessControlImageUniforms 0\n"
420 "MaxTessEvaluationImageUniforms 0\n"
421 "MaxGeometryImageUniforms 0\n"
422 "MaxFragmentImageUniforms 8\n"
423 "MaxCombinedImageUniforms 8\n"
424 "MaxGeometryTextureImageUnits 16\n"
425 "MaxGeometryOutputVertices 256\n"
426 "MaxGeometryTotalOutputComponents 1024\n"
427 "MaxGeometryUniformComponents 1024\n"
428 "MaxGeometryVaryingComponents 64\n"
429 "MaxTessControlInputComponents 128\n"
430 "MaxTessControlOutputComponents 128\n"
431 "MaxTessControlTextureImageUnits 16\n"
432 "MaxTessControlUniformComponents 1024\n"
433 "MaxTessControlTotalOutputComponents 4096\n"
434 "MaxTessEvaluationInputComponents 128\n"
435 "MaxTessEvaluationOutputComponents 128\n"
436 "MaxTessEvaluationTextureImageUnits 16\n"
437 "MaxTessEvaluationUniformComponents 1024\n"
438 "MaxTessPatchComponents 120\n"
439 "MaxPatchVertices 32\n"
440 "MaxTessGenLevel 64\n"
441 "MaxViewports 16\n"
442 "MaxVertexAtomicCounters 0\n"
443 "MaxTessControlAtomicCounters 0\n"
444 "MaxTessEvaluationAtomicCounters 0\n"
445 "MaxGeometryAtomicCounters 0\n"
446 "MaxFragmentAtomicCounters 8\n"
447 "MaxCombinedAtomicCounters 8\n"
448 "MaxAtomicCounterBindings 1\n"
449 "MaxVertexAtomicCounterBuffers 0\n"
450 "MaxTessControlAtomicCounterBuffers 0\n"
451 "MaxTessEvaluationAtomicCounterBuffers 0\n"
452 "MaxGeometryAtomicCounterBuffers 0\n"
453 "MaxFragmentAtomicCounterBuffers 1\n"
454 "MaxCombinedAtomicCounterBuffers 1\n"
455 "MaxAtomicCounterBufferSize 16384\n"
456 "MaxTransformFeedbackBuffers 4\n"
457 "MaxTransformFeedbackInterleavedComponents 64\n"
458 "MaxCullDistances 8\n"
459 "MaxCombinedClipAndCullDistances 8\n"
460 "MaxSamples 4\n"
461
462 "nonInductiveForLoops 1\n"
463 "whileLoops 1\n"
464 "doWhileLoops 1\n"
465 "generalUniformIndexing 1\n"
466 "generalAttributeMatrixVectorIndexing 1\n"
467 "generalVaryingIndexing 1\n"
468 "generalSamplerIndexing 1\n"
469 "generalVariableIndexing 1\n"
470 "generalConstantMatrixVectorIndexing 1\n"
471 ;
472
473//
474// *.conf => this is a config file that can set limits/resources
475//
476bool XglTestFramework::SetConfigFile(const std::string& name)
477{
478 if (name.size() < 5)
479 return false;
480
481 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
482 ConfigFile = name;
483 return true;
484 }
485
486 return false;
487}
488
489//
490// Parse either a .conf file provided by the user or the default string above.
491//
492void XglTestFramework::ProcessConfigFile()
493{
494 char** configStrings = 0;
495 char* config = 0;
496 if (ConfigFile.size() > 0) {
497 configStrings = ReadFileData(ConfigFile.c_str());
498 if (configStrings)
499 config = *configStrings;
500 else {
501 printf("Error opening configuration file; will instead use the default configuration\n");
502 }
503 }
504
505 if (config == 0) {
506 config = new char[strlen(DefaultConfig) + 1];
507 strcpy(config, DefaultConfig);
508 }
509
510 const char* delims = " \t\n\r";
511 const char* token = strtok(config, delims);
512 while (token) {
513 const char* valueStr = strtok(0, delims);
514 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
515 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
516 return;
517 }
518 int value = atoi(valueStr);
519
520 if (strcmp(token, "MaxLights") == 0)
521 Resources.maxLights = value;
522 else if (strcmp(token, "MaxClipPlanes") == 0)
523 Resources.maxClipPlanes = value;
524 else if (strcmp(token, "MaxTextureUnits") == 0)
525 Resources.maxTextureUnits = value;
526 else if (strcmp(token, "MaxTextureCoords") == 0)
527 Resources.maxTextureCoords = value;
528 else if (strcmp(token, "MaxVertexAttribs") == 0)
529 Resources.maxVertexAttribs = value;
530 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
531 Resources.maxVertexUniformComponents = value;
532 else if (strcmp(token, "MaxVaryingFloats") == 0)
533 Resources.maxVaryingFloats = value;
534 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
535 Resources.maxVertexTextureImageUnits = value;
536 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
537 Resources.maxCombinedTextureImageUnits = value;
538 else if (strcmp(token, "MaxTextureImageUnits") == 0)
539 Resources.maxTextureImageUnits = value;
540 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
541 Resources.maxFragmentUniformComponents = value;
542 else if (strcmp(token, "MaxDrawBuffers") == 0)
543 Resources.maxDrawBuffers = value;
544 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
545 Resources.maxVertexUniformVectors = value;
546 else if (strcmp(token, "MaxVaryingVectors") == 0)
547 Resources.maxVaryingVectors = value;
548 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
549 Resources.maxFragmentUniformVectors = value;
550 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
551 Resources.maxVertexOutputVectors = value;
552 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
553 Resources.maxFragmentInputVectors = value;
554 else if (strcmp(token, "MinProgramTexelOffset") == 0)
555 Resources.minProgramTexelOffset = value;
556 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
557 Resources.maxProgramTexelOffset = value;
558 else if (strcmp(token, "MaxClipDistances") == 0)
559 Resources.maxClipDistances = value;
560 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
561 Resources.maxComputeWorkGroupCountX = value;
562 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
563 Resources.maxComputeWorkGroupCountY = value;
564 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
565 Resources.maxComputeWorkGroupCountZ = value;
566 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
567 Resources.maxComputeWorkGroupSizeX = value;
568 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
569 Resources.maxComputeWorkGroupSizeY = value;
570 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
571 Resources.maxComputeWorkGroupSizeZ = value;
572 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
573 Resources.maxComputeUniformComponents = value;
574 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
575 Resources.maxComputeTextureImageUnits = value;
576 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
577 Resources.maxComputeImageUniforms = value;
578 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
579 Resources.maxComputeAtomicCounters = value;
580 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
581 Resources.maxComputeAtomicCounterBuffers = value;
582 else if (strcmp(token, "MaxVaryingComponents") == 0)
583 Resources.maxVaryingComponents = value;
584 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
585 Resources.maxVertexOutputComponents = value;
586 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
587 Resources.maxGeometryInputComponents = value;
588 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
589 Resources.maxGeometryOutputComponents = value;
590 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
591 Resources.maxFragmentInputComponents = value;
592 else if (strcmp(token, "MaxImageUnits") == 0)
593 Resources.maxImageUnits = value;
594 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
595 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
596 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
597 Resources.maxCombinedShaderOutputResources = value;
598 else if (strcmp(token, "MaxImageSamples") == 0)
599 Resources.maxImageSamples = value;
600 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
601 Resources.maxVertexImageUniforms = value;
602 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
603 Resources.maxTessControlImageUniforms = value;
604 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
605 Resources.maxTessEvaluationImageUniforms = value;
606 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
607 Resources.maxGeometryImageUniforms = value;
608 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
609 Resources.maxFragmentImageUniforms = value;
610 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
611 Resources.maxCombinedImageUniforms = value;
612 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
613 Resources.maxGeometryTextureImageUnits = value;
614 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
615 Resources.maxGeometryOutputVertices = value;
616 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
617 Resources.maxGeometryTotalOutputComponents = value;
618 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
619 Resources.maxGeometryUniformComponents = value;
620 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
621 Resources.maxGeometryVaryingComponents = value;
622 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
623 Resources.maxTessControlInputComponents = value;
624 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
625 Resources.maxTessControlOutputComponents = value;
626 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
627 Resources.maxTessControlTextureImageUnits = value;
628 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
629 Resources.maxTessControlUniformComponents = value;
630 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
631 Resources.maxTessControlTotalOutputComponents = value;
632 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
633 Resources.maxTessEvaluationInputComponents = value;
634 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
635 Resources.maxTessEvaluationOutputComponents = value;
636 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
637 Resources.maxTessEvaluationTextureImageUnits = value;
638 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
639 Resources.maxTessEvaluationUniformComponents = value;
640 else if (strcmp(token, "MaxTessPatchComponents") == 0)
641 Resources.maxTessPatchComponents = value;
642 else if (strcmp(token, "MaxPatchVertices") == 0)
643 Resources.maxPatchVertices = value;
644 else if (strcmp(token, "MaxTessGenLevel") == 0)
645 Resources.maxTessGenLevel = value;
646 else if (strcmp(token, "MaxViewports") == 0)
647 Resources.maxViewports = value;
648 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
649 Resources.maxVertexAtomicCounters = value;
650 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
651 Resources.maxTessControlAtomicCounters = value;
652 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
653 Resources.maxTessEvaluationAtomicCounters = value;
654 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
655 Resources.maxGeometryAtomicCounters = value;
656 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
657 Resources.maxFragmentAtomicCounters = value;
658 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
659 Resources.maxCombinedAtomicCounters = value;
660 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
661 Resources.maxAtomicCounterBindings = value;
662 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
663 Resources.maxVertexAtomicCounterBuffers = value;
664 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
665 Resources.maxTessControlAtomicCounterBuffers = value;
666 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
667 Resources.maxTessEvaluationAtomicCounterBuffers = value;
668 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
669 Resources.maxGeometryAtomicCounterBuffers = value;
670 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
671 Resources.maxFragmentAtomicCounterBuffers = value;
672 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
673 Resources.maxCombinedAtomicCounterBuffers = value;
674 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
675 Resources.maxAtomicCounterBufferSize = value;
676 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
677 Resources.maxTransformFeedbackBuffers = value;
678 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
679 Resources.maxTransformFeedbackInterleavedComponents = value;
680 else if (strcmp(token, "MaxCullDistances") == 0)
681 Resources.maxCullDistances = value;
682 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
683 Resources.maxCombinedClipAndCullDistances = value;
684 else if (strcmp(token, "MaxSamples") == 0)
685 Resources.maxSamples = value;
686
687 else if (strcmp(token, "nonInductiveForLoops") == 0)
688 Resources.limits.nonInductiveForLoops = (value != 0);
689 else if (strcmp(token, "whileLoops") == 0)
690 Resources.limits.whileLoops = (value != 0);
691 else if (strcmp(token, "doWhileLoops") == 0)
692 Resources.limits.doWhileLoops = (value != 0);
693 else if (strcmp(token, "generalUniformIndexing") == 0)
694 Resources.limits.generalUniformIndexing = (value != 0);
695 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
696 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
697 else if (strcmp(token, "generalVaryingIndexing") == 0)
698 Resources.limits.generalVaryingIndexing = (value != 0);
699 else if (strcmp(token, "generalSamplerIndexing") == 0)
700 Resources.limits.generalSamplerIndexing = (value != 0);
701 else if (strcmp(token, "generalVariableIndexing") == 0)
702 Resources.limits.generalVariableIndexing = (value != 0);
703 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
704 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
705 else
706 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
707
708 token = strtok(0, delims);
709 }
710 if (configStrings)
711 FreeFileData(configStrings);
712}
713
714void XglTestFramework::SetMessageOptions(EShMessages& messages)
715{
716 if (m_compile_options & EOptionRelaxedErrors)
717 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
718 if (m_compile_options & EOptionIntermediate)
719 messages = (EShMessages)(messages | EShMsgAST);
720 if (m_compile_options & EOptionSuppressWarnings)
721 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
722}
723
724//
725// Malloc a string of sufficient size and read a string into it.
726//
727char** XglTestFramework::ReadFileData(const char* fileName)
728{
729 FILE *in;
730 #if defined(_WIN32) && defined(__GNUC__)
731 in = fopen(fileName, "r");
732 int errorCode = in ? 0 : 1;
733 #else
734 int errorCode = fopen_s(&in, fileName, "r");
735 #endif
736
737 char *fdata;
738 int count = 0;
739 const int maxSourceStrings = 5;
740 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
741
742 if (errorCode) {
743 printf("Error: unable to open input file: %s\n", fileName);
744 return 0;
745 }
746
747 while (fgetc(in) != EOF)
748 count++;
749
750 fseek(in, 0, SEEK_SET);
751
752 if (!(fdata = (char*)malloc(count+2))) {
753 printf("Error allocating memory\n");
754 return 0;
755 }
756 if (fread(fdata,1,count, in)!=count) {
757 printf("Error reading input file: %s\n", fileName);
758 return 0;
759 }
760 fdata[count] = '\0';
761 fclose(in);
762 if (count == 0) {
763 return_data[0]=(char*)malloc(count+2);
764 return_data[0][0]='\0';
765 m_num_shader_strings = 0;
766 return return_data;
767 } else
768 m_num_shader_strings = 1;
769
770 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
771 int ptr_len=0,i=0;
772 while(count>0){
773 return_data[i]=(char*)malloc(len+2);
774 memcpy(return_data[i],fdata+ptr_len,len);
775 return_data[i][len]='\0';
776 count-=(len);
777 ptr_len+=(len);
778 if(count<len){
779 if(count==0){
780 m_num_shader_strings=(i+1);
781 break;
782 }
783 len = count;
784 }
785 ++i;
786 }
787 return return_data;
788}
789
790void XglTestFramework::FreeFileData(char** data)
791{
792 for(int i=0;i<m_num_shader_strings;i++)
793 free(data[i]);
794}
795
796//
797// Deduce the language from the filename. Files must end in one of the
798// following extensions:
799//
800// .vert = vertex
801// .tesc = tessellation control
802// .tese = tessellation evaluation
803// .geom = geometry
804// .frag = fragment
805// .comp = compute
806//
807EShLanguage XglTestFramework::FindLanguage(const std::string& name)
808{
809 size_t ext = name.rfind('.');
810 if (ext == std::string::npos) {
811 return EShLangVertex;
812 }
813
814 std::string suffix = name.substr(ext + 1, std::string::npos);
815 if (suffix == "vert")
816 return EShLangVertex;
817 else if (suffix == "tesc")
818 return EShLangTessControl;
819 else if (suffix == "tese")
820 return EShLangTessEvaluation;
821 else if (suffix == "geom")
822 return EShLangGeometry;
823 else if (suffix == "frag")
824 return EShLangFragment;
825 else if (suffix == "comp")
826 return EShLangCompute;
827
828 return EShLangVertex;
829}
830
831//
832// Convert XGL shader type to compiler's
833//
834EShLanguage XglTestFramework::FindLanguage(const XGL_PIPELINE_SHADER_STAGE shader_type)
835{
836 switch (shader_type) {
837 case XGL_SHADER_STAGE_VERTEX:
838 return EShLangVertex;
839
840 case XGL_SHADER_STAGE_TESS_CONTROL:
841 return EShLangTessControl;
842
843 case XGL_SHADER_STAGE_TESS_EVALUATION:
844 return EShLangTessEvaluation;
845
846 case XGL_SHADER_STAGE_GEOMETRY:
847 return EShLangGeometry;
848
849 case XGL_SHADER_STAGE_FRAGMENT:
850 return EShLangFragment;
851
852 case XGL_SHADER_STAGE_COMPUTE:
853 return EShLangCompute;
854 }
855
856 return EShLangVertex;
857}
858
859
860//
861// Compile a given string containing GLSL into BIL for use by XGL
862// Return value of false means an error was encountered.
863//
864bool XglTestFramework::GLSLtoBIL(const XGL_PIPELINE_SHADER_STAGE shader_type,
865 const char *pshader,
866 std::vector<unsigned int> &bil)
867{
868 glslang::TProgram& program = *new glslang::TProgram;
869 const char *shaderStrings[1];
870
871 // TODO: Do we want to load a special config file depending on the
872 // shader source? Optional name maybe?
873 // SetConfigFile(fileName);
874
875 ProcessConfigFile();
876
877 EShMessages messages = EShMsgDefault;
878 SetMessageOptions(messages);
879
880 EShLanguage stage = FindLanguage(shader_type);
881 glslang::TShader* shader = new glslang::TShader(stage);
882
883 shaderStrings[0] = pshader;
884 shader->setStrings(shaderStrings, 1);
885
886 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
887
888 return false; // something didn't work
889 }
890
891 program.addShader(shader);
892
893 if (! (m_compile_options & EOptionSuppressInfolog)) {
894 puts(shader->getInfoLog());
895 puts(shader->getInfoDebugLog());
896 }
897
898 //
899 // Program-level processing...
900 //
901
902 if (! program.link(messages))
903 return false;
904
905 if (! (m_compile_options & EOptionSuppressInfolog)) {
906 puts(program.getInfoLog());
907 puts(program.getInfoDebugLog());
908 }
909
910 if (m_compile_options & EOptionDumpReflection) {
911 program.buildReflection();
912 program.dumpReflection();
913 }
914
915 glslang::GlslangToBil(*program.getIntermediate(stage), bil);
916
917 return true;
918}
919
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600920
921
922XglTestImageRecord::XglTestImageRecord() : // Constructor
923 m_width( 0 ),
924 m_height( 0 ),
925 m_data( NULL )
926{
927 m_data_size = 0;
928}
929
930XglTestImageRecord::~XglTestImageRecord()
931{
932
933}
934
935XglTestImageRecord::XglTestImageRecord(const XglTestImageRecord &copyin) // Copy constructor to handle pass by value.
936{
937 m_title = copyin.m_title;
938 m_width = copyin.m_width;
939 m_height = copyin.m_height;
940 m_data_size = copyin.m_data_size;
941 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
942}
943
944ostream &operator<<(ostream &output, const XglTestImageRecord &XglTestImageRecord)
945{
946 output << XglTestImageRecord.m_title << " (" << XglTestImageRecord.m_width <<
947 "," << XglTestImageRecord.m_height << ")" << endl;
948 return output;
949}
950
951XglTestImageRecord& XglTestImageRecord::operator=(const XglTestImageRecord &rhs)
952{
953 m_title = rhs.m_title;
954 m_width = rhs.m_width;
955 m_height = rhs.m_height;
956 m_data_size = rhs.m_data_size;
957 m_data = rhs.m_data;
958 return *this;
959}
960
961int XglTestImageRecord::operator==(const XglTestImageRecord &rhs) const
962{
963 if( this->m_data != rhs.m_data) return 0;
964 return 1;
965}
966
967// This function is required for built-in STL list functions like sort
968int XglTestImageRecord::operator<(const XglTestImageRecord &rhs) const
969{
970 if( this->m_data_size < rhs.m_data_size ) return 1;
971 return 0;
972}
973