blob: 72e8de560e3bb031df57a320822c9152f88b1688 [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"
Chia-I Wua6bc0ce2014-12-29 14:38:28 +080024#include "xglrenderframework.h"
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -060025#include "GL/freeglut_std.h"
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060026//#include "ShaderLang.h"
Steve Kc1638cc2015-03-17 09:40:23 -060027#include "GlslangToSpv.h"
Tony Barbour4ab45422014-12-10 17:00:20 -070028#include <limits.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060029#include <math.h>
Chia-I Wuec664fa2014-12-02 11:54:24 +080030#include <wand/MagickWand.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060031
32// Command-line options
33enum TOptions {
34 EOptionNone = 0x000,
35 EOptionIntermediate = 0x001,
36 EOptionSuppressInfolog = 0x002,
37 EOptionMemoryLeakMode = 0x004,
38 EOptionRelaxedErrors = 0x008,
39 EOptionGiveWarnings = 0x010,
40 EOptionLinkProgram = 0x020,
41 EOptionMultiThreaded = 0x040,
42 EOptionDumpConfig = 0x080,
43 EOptionDumpReflection = 0x100,
44 EOptionSuppressWarnings = 0x200,
45 EOptionDumpVersions = 0x400,
Cody Northrop3bfd27c2015-03-17 15:55:58 -060046 EOptionSpv = 0x800,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060047 EOptionDefaultDesktop = 0x1000,
48};
49
50#ifndef _WIN32
51
52#include <errno.h>
53
54int fopen_s(
55 FILE** pFile,
56 const char* filename,
57 const char* mode
58)
59{
60 if (!pFile || !filename || !mode) {
61 return EINVAL;
62 }
63
64 FILE* f = fopen(filename, mode);
65 if (! f) {
66 if (errno != 0) {
67 return errno;
68 } else {
69 return ENOENT;
70 }
71 }
72 *pFile = f;
73
74 return 0;
75}
76
77#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -060078
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -060079// Set up environment for GLSL compiler
80// Must be done once per process
81void TestEnvironment::SetUp()
82{
Cody Northrop3bfd27c2015-03-17 15:55:58 -060083 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -060084 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +080085
86 xgl_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -060087}
88
89void TestEnvironment::TearDown()
90{
91 glslang::FinalizeProcess();
92}
93
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -060094XglTestFramework::XglTestFramework() :
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060095 m_compile_options( 0 ),
96 m_num_shader_strings( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -060097{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -060098
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060099}
100
101XglTestFramework::~XglTestFramework()
102{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600103
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600104}
105
106// Define all the static elements
107bool XglTestFramework::m_show_images = false;
108bool XglTestFramework::m_save_images = false;
Tony Barbour247bf372014-10-30 14:29:04 -0600109bool XglTestFramework::m_compare_images = false;
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600110bool XglTestFramework::m_use_spv = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600111int XglTestFramework::m_width = 0;
112int XglTestFramework::m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600113std::list<XglTestImageRecord> XglTestFramework::m_images;
114std::list<XglTestImageRecord>::iterator XglTestFramework::m_display_image;
115int m_display_image_idx = 0;
116
117void XglTestFramework::InitArgs(int *argc, char *argv[])
118{
119 int i, n;
120
121 for (i=0, n=0; i< *argc; i++) {
122 if (strncmp("--show-images", argv[i], 13) == 0) {
123 m_show_images = true;
124 continue;
125 }
126 if (strncmp("--save-images", argv[i], 13) == 0) {
127 m_save_images = true;
128 continue;
129 }
130
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600131 if (strncmp("--use-SPV", argv[i], 13) == 0) {
132 m_use_spv = true;
Courtney Goeltzenleuchterb666dc62014-10-09 09:13:56 -0600133 continue;
134 }
135
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600136 if (strncmp("--no-SPV", argv[i], 13) == 0) {
137 m_use_spv = false;
Courtney Goeltzenleuchterc44e3ee2014-10-31 14:13:33 -0600138 continue;
139 }
140
Tony Barbour247bf372014-10-30 14:29:04 -0600141 if (strncmp("--compare-images", argv[i], 16) == 0) {
142 m_compare_images = true;
143 continue;
144 }
145
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600146 /*
147 * Since the above "consume" inputs, update argv
148 * so that it contains the trimmed list of args for glutInit
149 */
Tony Barboura98d3932014-12-11 09:52:49 -0700150 if (strncmp("--help", argv[i], 6) == 0 || strncmp("-h", argv[i], 2) == 0) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700151 printf("\nOther options:\n");
152 printf("\t--show-images\n"
153 "\t\tDisplay test images in viewer after tests complete.\n");
154 printf("\t--save-images\n"
155 "\t\tSave tests images as ppm files in current working directory.\n"
156 "\t\tUsed to generate golden images for compare-images.\n");
157 printf("\t--compare-images\n"
158 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barboura98d3932014-12-11 09:52:49 -0700159 "\t\tAlso saves the generated test image in current working\n"
160 "\t\t\tdirectory but only if the image is different from the golden\n"
161 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
162 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700163 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600164 printf("\t--use-SPV\n"
165 "\t\tUse SPV code path (default).\n");
166 printf("\t--no-SPV\n"
167 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700168 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700169 }
170
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600171 argv[n] = argv[i];
172 n++;
173 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600174}
175
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600176void XglTestFramework::WritePPM( const char *basename, XglImage *image )
177{
178 string filename;
179 XGL_RESULT err;
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600180 int x, y;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600181
182 filename.append(basename);
183 filename.append(".ppm");
184
185 const XGL_IMAGE_SUBRESOURCE sr = {
186 XGL_IMAGE_ASPECT_COLOR, 0, 0
187 };
188 XGL_SUBRESOURCE_LAYOUT sr_layout;
Chia-I Wu99ff89d2014-12-27 14:14:50 +0800189 size_t data_size = sizeof(sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600190
191 err = xglGetImageSubresourceInfo( image->image(), &sr,
192 XGL_INFO_TYPE_SUBRESOURCE_LAYOUT,
193 &data_size, &sr_layout);
194 ASSERT_XGL_SUCCESS( err );
195 ASSERT_EQ(data_size, sizeof(sr_layout));
196
197 const char *ptr;
198
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600199 err = xglMapMemory( image->memory(), 0, (void **) &ptr );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600200 ASSERT_XGL_SUCCESS( err );
201
202 ptr += sr_layout.offset;
203
204 ofstream file (filename.c_str());
205 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
206
207 file << "P6\n";
208 file << image->width() << "\n";
209 file << image->height() << "\n";
210 file << 255 << "\n";
211
212 for (y = 0; y < image->height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700213 const int *row = (const int *) ptr;
214 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600215
Tony Barboura53a6942015-02-25 11:25:11 -0700216 if (image->format() == XGL_FMT_B8G8R8A8_UNORM)
217 {
218 for (x = 0; x < image->width(); x++) {
219 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
220 file.write((char *) &swapped, 3);
221 row++;
222 }
223 }
224 else if (image->format() == XGL_FMT_R8G8B8A8_UNORM)
225 {
226 for (x = 0; x < image->width(); x++) {
227 file.write((char *) row, 3);
228 row++;
229 }
230 }
231 else {
232 printf("Unrecognized image format - will not write image files");
233 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600234 }
235
236 ptr += sr_layout.rowPitch;
237 }
238
239 file.close();
240
241 err = xglUnmapMemory( image->memory() );
242 ASSERT_XGL_SUCCESS( err );
243}
244
Tony Barbour247bf372014-10-30 14:29:04 -0600245void XglTestFramework::Compare(const char *basename, XglImage *image )
246{
247
248 MagickWand *magick_wand_1;
249 MagickWand *magick_wand_2;
250 MagickWand *compare_wand;
251 MagickBooleanType status;
Tony Barbour4ab45422014-12-10 17:00:20 -0700252 char testimage[256],golden[PATH_MAX+256],golddir[PATH_MAX] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600253 double differenz;
254
Tony Barbour4ab45422014-12-10 17:00:20 -0700255 if (getenv("RENDERTEST_GOLDEN_DIR"))
256 {
257 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
258 }
259
Tony Barbour247bf372014-10-30 14:29:04 -0600260 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();
Tony Barbour4ab45422014-12-10 17:00:20 -0700269 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600270 status=MagickReadImage(magick_wand_2,golden);
271 ASSERT_TRUE(status) << "Unable to open file: " << golden;
272
Tony Barbour247bf372014-10-30 14:29:04 -0600273 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
274 if (differenz != 0.0)
275 {
276 char difference[256];
277
278 sprintf(difference,"%s-diff.ppm",basename);
279 status = MagickWriteImage(compare_wand, difference);
280 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
281 }
282 DestroyMagickWand(compare_wand);
283
284 DestroyMagickWand(magick_wand_1);
285 DestroyMagickWand(magick_wand_2);
286 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700287
288 if (differenz == 0.0)
289 {
290 /*
291 * If test image and golden image match, we do not need to
292 * keep around the test image.
293 */
294 remove(testimage);
295 }
Tony Barbour247bf372014-10-30 14:29:04 -0600296}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600297
298void XglTestFramework::Show(const char *comment, XglImage *image)
299{
300 XGL_RESULT err;
301
302 const XGL_IMAGE_SUBRESOURCE sr = {
303 XGL_IMAGE_ASPECT_COLOR, 0, 0
304 };
305 XGL_SUBRESOURCE_LAYOUT sr_layout;
Chia-I Wu99ff89d2014-12-27 14:14:50 +0800306 size_t data_size = sizeof(sr_layout);
Tony Barbour96db8822015-02-25 12:28:39 -0700307 XglTestImageRecord record;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600308
309 if (!m_show_images) return;
310
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600311 err = xglGetImageSubresourceInfo( image->image(), &sr, XGL_INFO_TYPE_SUBRESOURCE_LAYOUT,
312 &data_size, &sr_layout);
313 ASSERT_XGL_SUCCESS( err );
314 ASSERT_EQ(data_size, sizeof(sr_layout));
315
Tony Barbour96db8822015-02-25 12:28:39 -0700316 char *ptr;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600317
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600318 err = image->MapMemory( (void **) &ptr );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600319 ASSERT_XGL_SUCCESS( err );
320
321 ptr += sr_layout.offset;
322
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600323 record.m_title.append(comment);
324 record.m_width = image->width();
325 record.m_height = image->height();
326 // TODO: Need to make this more robust to handle different image formats
327 record.m_data_size = image->width()*image->height()*4;
328 record.m_data = malloc(record.m_data_size);
329 memcpy(record.m_data, ptr, record.m_data_size);
330 m_images.push_back(record);
331 m_display_image = --m_images.end();
332
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600333 err = image->UnmapMemory();
334 ASSERT_XGL_SUCCESS( err );
Tony Barbour96db8822015-02-25 12:28:39 -0700335
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600336}
337
Tony Barbour247bf372014-10-30 14:29:04 -0600338void XglTestFramework::RecordImage(XglImage *image, char *tag)
339{
340 const ::testing::TestInfo* const test_info =
341 ::testing::UnitTest::GetInstance()->current_test_info();
342 ostringstream filestream;
343 string filename;
344
345 filestream << test_info->name() << "-" << tag;
346 filename = filestream.str();
347 // ToDo - scrub string for bad characters
348
349 if (m_save_images || m_compare_images) {
350 WritePPM(filename.c_str(), image);
351 if (m_compare_images) {
352 Compare(filename.c_str(), image);
353 }
354 }
355
356 if (m_show_images) {
357 Show(test_info->name(), image);
358 }
359}
360
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600361void XglTestFramework::RecordImage(XglImage *image)
362{
363 const ::testing::TestInfo* const test_info =
364 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600365 ostringstream filestream;
366 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600367
Tony Barbour247bf372014-10-30 14:29:04 -0600368 m_width = 40;
369
370 if (strcmp(test_info->name(), m_testName.c_str())) {
371 filestream << test_info->name();
372 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700373 m_frameNum = 2;
374 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600375 }
376 else {
377 filestream << test_info->name() << "-" << m_frameNum;
378 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700379 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600380 }
381
382
383 // ToDo - scrub string for bad characters
384
385 if (m_save_images || m_compare_images) {
386 WritePPM(filename.c_str(), image);
387 if (m_compare_images) {
388 Compare(filename.c_str(), image);
389 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600390 }
391
392 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600393 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600394 }
395}
396
Tony Barbour96db8822015-02-25 12:28:39 -0700397static xgl_testing::Environment *environment;
398
399TestFrameworkXglPresent::TestFrameworkXglPresent() :
400m_device(environment->default_device()),
401m_queue(*m_device.graphics_queues()[0]),
402m_cmdbuf(m_device, xgl_testing::CmdBuffer::create_info(XGL_QUEUE_TYPE_GRAPHICS))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600403{
Tony Barbour96db8822015-02-25 12:28:39 -0700404 m_quit = false;
405 m_pause = false;
406 m_width = 0;
407 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600408}
409
Tony Barbour96db8822015-02-25 12:28:39 -0700410void TestFrameworkXglPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600411{
Tony Barbour96db8822015-02-25 12:28:39 -0700412 XGL_RESULT err;
413
Tony Barbourbdf0a312015-04-01 17:10:07 -0600414 XGL_WSI_X11_PRESENT_INFO present = {};
415 present.destWindow = m_window;
416 present.srcImage = m_display_image->m_presentableImage;
Tony Barbour96db8822015-02-25 12:28:39 -0700417
418 xcb_change_property (environment->m_connection,
419 XCB_PROP_MODE_REPLACE,
420 m_window,
421 XCB_ATOM_WM_NAME,
422 XCB_ATOM_STRING,
423 8,
424 m_display_image->m_title.size(),
425 m_display_image->m_title.c_str());
426
427 err = xglWsiX11QueuePresent(m_queue.obj(), &present, NULL);
428 assert(!err);
429
430 m_queue.wait();
431
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600432}
433
Tony Barbour96db8822015-02-25 12:28:39 -0700434void TestFrameworkXglPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600435{
Tony Barbour96db8822015-02-25 12:28:39 -0700436 u_int8_t event_code = event->response_type & 0x7f;
437 switch (event_code) {
438 case XCB_EXPOSE:
439 Display(); // TODO: handle resize
440 break;
441 case XCB_CLIENT_MESSAGE:
442 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
443 (m_atom_wm_delete_window)->atom) {
444 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600445 }
446 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700447 case XCB_KEY_RELEASE:
448 {
449 const xcb_key_release_event_t *key =
450 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600451
Tony Barbour96db8822015-02-25 12:28:39 -0700452 switch (key->detail) {
453 case 0x9: // Escape
454 m_quit = true;
455 break;
456 case 0x71: // left arrow key
457 if (m_display_image == m_images.begin()) {
458 m_display_image = --m_images.end();
459 } else {
460 --m_display_image;
461 }
462 break;
463 case 0x72: // right arrow key
464 ++m_display_image;
465 if (m_display_image == m_images.end()) {
466 m_display_image = m_images.begin();
467 }
468 break;
469 case 0x41:
470 m_pause = !m_pause;
471 break;
472 }
473 Display();
474 }
475 break;
476 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600477 break;
478 }
Tony Barbour96db8822015-02-25 12:28:39 -0700479}
480
481void TestFrameworkXglPresent::Run()
482{
483 xcb_flush(environment->m_connection);
484
485 while (! m_quit) {
486 xcb_generic_event_t *event;
487
488 if (m_pause) {
489 event = xcb_wait_for_event(environment->m_connection);
490 } else {
491 event = xcb_poll_for_event(environment->m_connection);
492 }
493 if (event) {
494 HandleEvent(event);
495 free(event);
496 }
497 }
498}
499
500void TestFrameworkXglPresent::CreatePresentableImages()
501{
502 XGL_RESULT err;
503
504 m_display_image = m_images.begin();
505
506 for (int x=0; x < m_images.size(); x++)
507 {
Tony Barbourbdf0a312015-04-01 17:10:07 -0600508 XGL_WSI_X11_PRESENTABLE_IMAGE_CREATE_INFO presentable_image_info = {};
509 presentable_image_info.format = XGL_FMT_B8G8R8A8_UNORM;
510 presentable_image_info.usage = XGL_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
511 presentable_image_info.extent.width = m_display_image->m_width;
512 presentable_image_info.extent.height = m_display_image->m_height;
513 presentable_image_info.flags = 0;
Tony Barbour96db8822015-02-25 12:28:39 -0700514
515 void *dest_ptr;
516
517 err = xglWsiX11CreatePresentableImage(m_device.obj(), &presentable_image_info,
518 &m_display_image->m_presentableImage, &m_display_image->m_presentableMemory);
519 assert(!err);
520
521 xgl_testing::Buffer buf;
522 buf.init(m_device, (XGL_GPU_SIZE) m_display_image->m_data_size);
523 dest_ptr = buf.map();
524 memcpy(dest_ptr,m_display_image->m_data, m_display_image->m_data_size);
525 buf.unmap();
526
527 m_cmdbuf.begin();
528
529 XGL_BUFFER_IMAGE_COPY region = {};
530 region.imageExtent.height = m_display_image->m_height;
531 region.imageExtent.width = m_display_image->m_width;
532 region.imageExtent.depth = 1;
533
534 xglCmdCopyBufferToImage(m_cmdbuf.obj(), buf.obj(), m_display_image->m_presentableImage, 1, &region);
535 m_cmdbuf.end();
536
537 uint32_t numMemRefs=2;
538 XGL_MEMORY_REF memRefs[2];
539 memRefs[0].flags = 0;
540 memRefs[0].mem = m_display_image->m_presentableMemory;
541 memRefs[1].flags = 0;
542 memRefs[1].mem = buf.memories()[0];
543
544 XGL_CMD_BUFFER cmdBufs[1];
545 cmdBufs[0] = m_cmdbuf.obj();
546
547 xglQueueSubmit(m_queue.obj(), 1, cmdBufs, numMemRefs, memRefs, NULL);
548 m_queue.wait();
549
550
551 if (m_display_image->m_width > m_width)
552 m_width = m_display_image->m_width;
553
554 if (m_display_image->m_height > m_height)
555 m_height = m_display_image->m_height;
556
557
558 ++m_display_image;
559
560 }
561
562 m_display_image = m_images.begin();
563}
564
565void TestFrameworkXglPresent::InitPresentFramework(std::list<XglTestImageRecord> &imagesIn)
566{
567 m_images = imagesIn;
568}
569
570void TestFrameworkXglPresent::CreateWindow()
571{
572 uint32_t value_mask, value_list[32];
573
574 m_window = xcb_generate_id(environment->m_connection);
575
576 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
577 value_list[0] = environment->m_screen->black_pixel;
578 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
579 XCB_EVENT_MASK_EXPOSURE |
580 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
581
582 xcb_create_window(environment->m_connection,
583 XCB_COPY_FROM_PARENT,
584 m_window, environment->m_screen->root,
585 0, 0, m_width, m_height, 0,
586 XCB_WINDOW_CLASS_INPUT_OUTPUT,
587 environment->m_screen->root_visual,
588 value_mask, value_list);
589
590 /* Magic code that will send notification when window is destroyed */
591 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(environment->m_connection, 1, 12,
592 "WM_PROTOCOLS");
593 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(environment->m_connection, cookie, 0);
594
595 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(environment->m_connection, 0, 16, "WM_DELETE_WINDOW");
596 m_atom_wm_delete_window = xcb_intern_atom_reply(environment->m_connection, cookie2, 0);
597
598 xcb_change_property(environment->m_connection, XCB_PROP_MODE_REPLACE,
599 m_window, (*reply).atom, 4, 32, 1,
600 &(*m_atom_wm_delete_window).atom);
601 free(reply);
602
603 xcb_map_window(environment->m_connection, m_window);
604}
605
606void TestFrameworkXglPresent::TearDown()
607{
608 xcb_destroy_window(environment->m_connection, m_window);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600609}
610
611void XglTestFramework::Finish()
612{
613 if (m_images.size() == 0) return;
614
Tony Barbour96db8822015-02-25 12:28:39 -0700615 environment = new xgl_testing::Environment();
616 ::testing::AddGlobalTestEnvironment(environment);
617 environment->X11SetUp();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600618
Tony Barbour96db8822015-02-25 12:28:39 -0700619 {
620 TestFrameworkXglPresent xglPresent;
621
622 xglPresent.InitPresentFramework(m_images);
623 xglPresent.CreatePresentableImages();
624 xglPresent.CreateWindow();
625 xglPresent.Run();
626 xglPresent.TearDown();
627 }
628 environment->TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600629}
630
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600631//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600632// These are the default resources for TBuiltInResources, used for both
633// - parsing this string for the case where the user didn't supply one
634// - dumping out a template for user construction of a config file
635//
636static const char* DefaultConfig =
637 "MaxLights 32\n"
638 "MaxClipPlanes 6\n"
639 "MaxTextureUnits 32\n"
640 "MaxTextureCoords 32\n"
641 "MaxVertexAttribs 64\n"
642 "MaxVertexUniformComponents 4096\n"
643 "MaxVaryingFloats 64\n"
644 "MaxVertexTextureImageUnits 32\n"
645 "MaxCombinedTextureImageUnits 80\n"
646 "MaxTextureImageUnits 32\n"
647 "MaxFragmentUniformComponents 4096\n"
648 "MaxDrawBuffers 32\n"
649 "MaxVertexUniformVectors 128\n"
650 "MaxVaryingVectors 8\n"
651 "MaxFragmentUniformVectors 16\n"
652 "MaxVertexOutputVectors 16\n"
653 "MaxFragmentInputVectors 15\n"
654 "MinProgramTexelOffset -8\n"
655 "MaxProgramTexelOffset 7\n"
656 "MaxClipDistances 8\n"
657 "MaxComputeWorkGroupCountX 65535\n"
658 "MaxComputeWorkGroupCountY 65535\n"
659 "MaxComputeWorkGroupCountZ 65535\n"
660 "MaxComputeWorkGroupSizeX 1024\n"
661 "MaxComputeWorkGroupSizeY 1024\n"
662 "MaxComputeWorkGroupSizeZ 64\n"
663 "MaxComputeUniformComponents 1024\n"
664 "MaxComputeTextureImageUnits 16\n"
665 "MaxComputeImageUniforms 8\n"
666 "MaxComputeAtomicCounters 8\n"
667 "MaxComputeAtomicCounterBuffers 1\n"
668 "MaxVaryingComponents 60\n"
669 "MaxVertexOutputComponents 64\n"
670 "MaxGeometryInputComponents 64\n"
671 "MaxGeometryOutputComponents 128\n"
672 "MaxFragmentInputComponents 128\n"
673 "MaxImageUnits 8\n"
674 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
675 "MaxCombinedShaderOutputResources 8\n"
676 "MaxImageSamples 0\n"
677 "MaxVertexImageUniforms 0\n"
678 "MaxTessControlImageUniforms 0\n"
679 "MaxTessEvaluationImageUniforms 0\n"
680 "MaxGeometryImageUniforms 0\n"
681 "MaxFragmentImageUniforms 8\n"
682 "MaxCombinedImageUniforms 8\n"
683 "MaxGeometryTextureImageUnits 16\n"
684 "MaxGeometryOutputVertices 256\n"
685 "MaxGeometryTotalOutputComponents 1024\n"
686 "MaxGeometryUniformComponents 1024\n"
687 "MaxGeometryVaryingComponents 64\n"
688 "MaxTessControlInputComponents 128\n"
689 "MaxTessControlOutputComponents 128\n"
690 "MaxTessControlTextureImageUnits 16\n"
691 "MaxTessControlUniformComponents 1024\n"
692 "MaxTessControlTotalOutputComponents 4096\n"
693 "MaxTessEvaluationInputComponents 128\n"
694 "MaxTessEvaluationOutputComponents 128\n"
695 "MaxTessEvaluationTextureImageUnits 16\n"
696 "MaxTessEvaluationUniformComponents 1024\n"
697 "MaxTessPatchComponents 120\n"
698 "MaxPatchVertices 32\n"
699 "MaxTessGenLevel 64\n"
700 "MaxViewports 16\n"
701 "MaxVertexAtomicCounters 0\n"
702 "MaxTessControlAtomicCounters 0\n"
703 "MaxTessEvaluationAtomicCounters 0\n"
704 "MaxGeometryAtomicCounters 0\n"
705 "MaxFragmentAtomicCounters 8\n"
706 "MaxCombinedAtomicCounters 8\n"
707 "MaxAtomicCounterBindings 1\n"
708 "MaxVertexAtomicCounterBuffers 0\n"
709 "MaxTessControlAtomicCounterBuffers 0\n"
710 "MaxTessEvaluationAtomicCounterBuffers 0\n"
711 "MaxGeometryAtomicCounterBuffers 0\n"
712 "MaxFragmentAtomicCounterBuffers 1\n"
713 "MaxCombinedAtomicCounterBuffers 1\n"
714 "MaxAtomicCounterBufferSize 16384\n"
715 "MaxTransformFeedbackBuffers 4\n"
716 "MaxTransformFeedbackInterleavedComponents 64\n"
717 "MaxCullDistances 8\n"
718 "MaxCombinedClipAndCullDistances 8\n"
719 "MaxSamples 4\n"
720
721 "nonInductiveForLoops 1\n"
722 "whileLoops 1\n"
723 "doWhileLoops 1\n"
724 "generalUniformIndexing 1\n"
725 "generalAttributeMatrixVectorIndexing 1\n"
726 "generalVaryingIndexing 1\n"
727 "generalSamplerIndexing 1\n"
728 "generalVariableIndexing 1\n"
729 "generalConstantMatrixVectorIndexing 1\n"
730 ;
731
732//
733// *.conf => this is a config file that can set limits/resources
734//
735bool XglTestFramework::SetConfigFile(const std::string& name)
736{
737 if (name.size() < 5)
738 return false;
739
740 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
741 ConfigFile = name;
742 return true;
743 }
744
745 return false;
746}
747
748//
749// Parse either a .conf file provided by the user or the default string above.
750//
751void XglTestFramework::ProcessConfigFile()
752{
753 char** configStrings = 0;
754 char* config = 0;
755 if (ConfigFile.size() > 0) {
756 configStrings = ReadFileData(ConfigFile.c_str());
757 if (configStrings)
758 config = *configStrings;
759 else {
760 printf("Error opening configuration file; will instead use the default configuration\n");
761 }
762 }
763
764 if (config == 0) {
765 config = new char[strlen(DefaultConfig) + 1];
766 strcpy(config, DefaultConfig);
767 }
768
769 const char* delims = " \t\n\r";
770 const char* token = strtok(config, delims);
771 while (token) {
772 const char* valueStr = strtok(0, delims);
773 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
774 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
775 return;
776 }
777 int value = atoi(valueStr);
778
779 if (strcmp(token, "MaxLights") == 0)
780 Resources.maxLights = value;
781 else if (strcmp(token, "MaxClipPlanes") == 0)
782 Resources.maxClipPlanes = value;
783 else if (strcmp(token, "MaxTextureUnits") == 0)
784 Resources.maxTextureUnits = value;
785 else if (strcmp(token, "MaxTextureCoords") == 0)
786 Resources.maxTextureCoords = value;
787 else if (strcmp(token, "MaxVertexAttribs") == 0)
788 Resources.maxVertexAttribs = value;
789 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
790 Resources.maxVertexUniformComponents = value;
791 else if (strcmp(token, "MaxVaryingFloats") == 0)
792 Resources.maxVaryingFloats = value;
793 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
794 Resources.maxVertexTextureImageUnits = value;
795 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
796 Resources.maxCombinedTextureImageUnits = value;
797 else if (strcmp(token, "MaxTextureImageUnits") == 0)
798 Resources.maxTextureImageUnits = value;
799 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
800 Resources.maxFragmentUniformComponents = value;
801 else if (strcmp(token, "MaxDrawBuffers") == 0)
802 Resources.maxDrawBuffers = value;
803 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
804 Resources.maxVertexUniformVectors = value;
805 else if (strcmp(token, "MaxVaryingVectors") == 0)
806 Resources.maxVaryingVectors = value;
807 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
808 Resources.maxFragmentUniformVectors = value;
809 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
810 Resources.maxVertexOutputVectors = value;
811 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
812 Resources.maxFragmentInputVectors = value;
813 else if (strcmp(token, "MinProgramTexelOffset") == 0)
814 Resources.minProgramTexelOffset = value;
815 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
816 Resources.maxProgramTexelOffset = value;
817 else if (strcmp(token, "MaxClipDistances") == 0)
818 Resources.maxClipDistances = value;
819 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
820 Resources.maxComputeWorkGroupCountX = value;
821 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
822 Resources.maxComputeWorkGroupCountY = value;
823 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
824 Resources.maxComputeWorkGroupCountZ = value;
825 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
826 Resources.maxComputeWorkGroupSizeX = value;
827 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
828 Resources.maxComputeWorkGroupSizeY = value;
829 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
830 Resources.maxComputeWorkGroupSizeZ = value;
831 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
832 Resources.maxComputeUniformComponents = value;
833 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
834 Resources.maxComputeTextureImageUnits = value;
835 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
836 Resources.maxComputeImageUniforms = value;
837 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
838 Resources.maxComputeAtomicCounters = value;
839 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
840 Resources.maxComputeAtomicCounterBuffers = value;
841 else if (strcmp(token, "MaxVaryingComponents") == 0)
842 Resources.maxVaryingComponents = value;
843 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
844 Resources.maxVertexOutputComponents = value;
845 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
846 Resources.maxGeometryInputComponents = value;
847 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
848 Resources.maxGeometryOutputComponents = value;
849 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
850 Resources.maxFragmentInputComponents = value;
851 else if (strcmp(token, "MaxImageUnits") == 0)
852 Resources.maxImageUnits = value;
853 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
854 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
855 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
856 Resources.maxCombinedShaderOutputResources = value;
857 else if (strcmp(token, "MaxImageSamples") == 0)
858 Resources.maxImageSamples = value;
859 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
860 Resources.maxVertexImageUniforms = value;
861 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
862 Resources.maxTessControlImageUniforms = value;
863 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
864 Resources.maxTessEvaluationImageUniforms = value;
865 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
866 Resources.maxGeometryImageUniforms = value;
867 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
868 Resources.maxFragmentImageUniforms = value;
869 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
870 Resources.maxCombinedImageUniforms = value;
871 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
872 Resources.maxGeometryTextureImageUnits = value;
873 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
874 Resources.maxGeometryOutputVertices = value;
875 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
876 Resources.maxGeometryTotalOutputComponents = value;
877 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
878 Resources.maxGeometryUniformComponents = value;
879 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
880 Resources.maxGeometryVaryingComponents = value;
881 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
882 Resources.maxTessControlInputComponents = value;
883 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
884 Resources.maxTessControlOutputComponents = value;
885 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
886 Resources.maxTessControlTextureImageUnits = value;
887 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
888 Resources.maxTessControlUniformComponents = value;
889 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
890 Resources.maxTessControlTotalOutputComponents = value;
891 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
892 Resources.maxTessEvaluationInputComponents = value;
893 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
894 Resources.maxTessEvaluationOutputComponents = value;
895 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
896 Resources.maxTessEvaluationTextureImageUnits = value;
897 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
898 Resources.maxTessEvaluationUniformComponents = value;
899 else if (strcmp(token, "MaxTessPatchComponents") == 0)
900 Resources.maxTessPatchComponents = value;
901 else if (strcmp(token, "MaxPatchVertices") == 0)
902 Resources.maxPatchVertices = value;
903 else if (strcmp(token, "MaxTessGenLevel") == 0)
904 Resources.maxTessGenLevel = value;
905 else if (strcmp(token, "MaxViewports") == 0)
906 Resources.maxViewports = value;
907 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
908 Resources.maxVertexAtomicCounters = value;
909 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
910 Resources.maxTessControlAtomicCounters = value;
911 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
912 Resources.maxTessEvaluationAtomicCounters = value;
913 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
914 Resources.maxGeometryAtomicCounters = value;
915 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
916 Resources.maxFragmentAtomicCounters = value;
917 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
918 Resources.maxCombinedAtomicCounters = value;
919 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
920 Resources.maxAtomicCounterBindings = value;
921 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
922 Resources.maxVertexAtomicCounterBuffers = value;
923 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
924 Resources.maxTessControlAtomicCounterBuffers = value;
925 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
926 Resources.maxTessEvaluationAtomicCounterBuffers = value;
927 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
928 Resources.maxGeometryAtomicCounterBuffers = value;
929 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
930 Resources.maxFragmentAtomicCounterBuffers = value;
931 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
932 Resources.maxCombinedAtomicCounterBuffers = value;
933 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
934 Resources.maxAtomicCounterBufferSize = value;
935 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
936 Resources.maxTransformFeedbackBuffers = value;
937 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
938 Resources.maxTransformFeedbackInterleavedComponents = value;
939 else if (strcmp(token, "MaxCullDistances") == 0)
940 Resources.maxCullDistances = value;
941 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
942 Resources.maxCombinedClipAndCullDistances = value;
943 else if (strcmp(token, "MaxSamples") == 0)
944 Resources.maxSamples = value;
945
946 else if (strcmp(token, "nonInductiveForLoops") == 0)
947 Resources.limits.nonInductiveForLoops = (value != 0);
948 else if (strcmp(token, "whileLoops") == 0)
949 Resources.limits.whileLoops = (value != 0);
950 else if (strcmp(token, "doWhileLoops") == 0)
951 Resources.limits.doWhileLoops = (value != 0);
952 else if (strcmp(token, "generalUniformIndexing") == 0)
953 Resources.limits.generalUniformIndexing = (value != 0);
954 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
955 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
956 else if (strcmp(token, "generalVaryingIndexing") == 0)
957 Resources.limits.generalVaryingIndexing = (value != 0);
958 else if (strcmp(token, "generalSamplerIndexing") == 0)
959 Resources.limits.generalSamplerIndexing = (value != 0);
960 else if (strcmp(token, "generalVariableIndexing") == 0)
961 Resources.limits.generalVariableIndexing = (value != 0);
962 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
963 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
964 else
965 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
966
967 token = strtok(0, delims);
968 }
969 if (configStrings)
970 FreeFileData(configStrings);
971}
972
973void XglTestFramework::SetMessageOptions(EShMessages& messages)
974{
975 if (m_compile_options & EOptionRelaxedErrors)
976 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
977 if (m_compile_options & EOptionIntermediate)
978 messages = (EShMessages)(messages | EShMsgAST);
979 if (m_compile_options & EOptionSuppressWarnings)
980 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
981}
982
983//
984// Malloc a string of sufficient size and read a string into it.
985//
986char** XglTestFramework::ReadFileData(const char* fileName)
987{
988 FILE *in;
989 #if defined(_WIN32) && defined(__GNUC__)
990 in = fopen(fileName, "r");
991 int errorCode = in ? 0 : 1;
992 #else
993 int errorCode = fopen_s(&in, fileName, "r");
994 #endif
995
996 char *fdata;
997 int count = 0;
998 const int maxSourceStrings = 5;
999 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1000
1001 if (errorCode) {
1002 printf("Error: unable to open input file: %s\n", fileName);
1003 return 0;
1004 }
1005
1006 while (fgetc(in) != EOF)
1007 count++;
1008
1009 fseek(in, 0, SEEK_SET);
1010
1011 if (!(fdata = (char*)malloc(count+2))) {
1012 printf("Error allocating memory\n");
1013 return 0;
1014 }
1015 if (fread(fdata,1,count, in)!=count) {
1016 printf("Error reading input file: %s\n", fileName);
1017 return 0;
1018 }
1019 fdata[count] = '\0';
1020 fclose(in);
1021 if (count == 0) {
1022 return_data[0]=(char*)malloc(count+2);
1023 return_data[0][0]='\0';
1024 m_num_shader_strings = 0;
1025 return return_data;
1026 } else
1027 m_num_shader_strings = 1;
1028
1029 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1030 int ptr_len=0,i=0;
1031 while(count>0){
1032 return_data[i]=(char*)malloc(len+2);
1033 memcpy(return_data[i],fdata+ptr_len,len);
1034 return_data[i][len]='\0';
1035 count-=(len);
1036 ptr_len+=(len);
1037 if(count<len){
1038 if(count==0){
1039 m_num_shader_strings=(i+1);
1040 break;
1041 }
1042 len = count;
1043 }
1044 ++i;
1045 }
1046 return return_data;
1047}
1048
1049void XglTestFramework::FreeFileData(char** data)
1050{
1051 for(int i=0;i<m_num_shader_strings;i++)
1052 free(data[i]);
1053}
1054
1055//
1056// Deduce the language from the filename. Files must end in one of the
1057// following extensions:
1058//
1059// .vert = vertex
1060// .tesc = tessellation control
1061// .tese = tessellation evaluation
1062// .geom = geometry
1063// .frag = fragment
1064// .comp = compute
1065//
1066EShLanguage XglTestFramework::FindLanguage(const std::string& name)
1067{
1068 size_t ext = name.rfind('.');
1069 if (ext == std::string::npos) {
1070 return EShLangVertex;
1071 }
1072
1073 std::string suffix = name.substr(ext + 1, std::string::npos);
1074 if (suffix == "vert")
1075 return EShLangVertex;
1076 else if (suffix == "tesc")
1077 return EShLangTessControl;
1078 else if (suffix == "tese")
1079 return EShLangTessEvaluation;
1080 else if (suffix == "geom")
1081 return EShLangGeometry;
1082 else if (suffix == "frag")
1083 return EShLangFragment;
1084 else if (suffix == "comp")
1085 return EShLangCompute;
1086
1087 return EShLangVertex;
1088}
1089
1090//
1091// Convert XGL shader type to compiler's
1092//
1093EShLanguage XglTestFramework::FindLanguage(const XGL_PIPELINE_SHADER_STAGE shader_type)
1094{
1095 switch (shader_type) {
1096 case XGL_SHADER_STAGE_VERTEX:
1097 return EShLangVertex;
1098
1099 case XGL_SHADER_STAGE_TESS_CONTROL:
1100 return EShLangTessControl;
1101
1102 case XGL_SHADER_STAGE_TESS_EVALUATION:
1103 return EShLangTessEvaluation;
1104
1105 case XGL_SHADER_STAGE_GEOMETRY:
1106 return EShLangGeometry;
1107
1108 case XGL_SHADER_STAGE_FRAGMENT:
1109 return EShLangFragment;
1110
1111 case XGL_SHADER_STAGE_COMPUTE:
1112 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001113
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001114 default:
1115 return EShLangVertex;
1116 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001117}
1118
1119
1120//
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001121// Compile a given string containing GLSL into SPV for use by XGL
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001122// Return value of false means an error was encountered.
1123//
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001124bool XglTestFramework::GLSLtoSPV(const XGL_PIPELINE_SHADER_STAGE shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001125 const char *pshader,
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001126 std::vector<unsigned int> &spv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001127{
1128 glslang::TProgram& program = *new glslang::TProgram;
1129 const char *shaderStrings[1];
1130
1131 // TODO: Do we want to load a special config file depending on the
1132 // shader source? Optional name maybe?
1133 // SetConfigFile(fileName);
1134
1135 ProcessConfigFile();
1136
1137 EShMessages messages = EShMsgDefault;
1138 SetMessageOptions(messages);
1139
1140 EShLanguage stage = FindLanguage(shader_type);
1141 glslang::TShader* shader = new glslang::TShader(stage);
1142
1143 shaderStrings[0] = pshader;
1144 shader->setStrings(shaderStrings, 1);
1145
1146 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1147
Cody Northrop195d6622014-11-03 12:54:37 -07001148 if (! (m_compile_options & EOptionSuppressInfolog)) {
1149 puts(shader->getInfoLog());
1150 puts(shader->getInfoDebugLog());
1151 }
1152
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001153 return false; // something didn't work
1154 }
1155
1156 program.addShader(shader);
1157
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001158
1159 //
1160 // Program-level processing...
1161 //
1162
Cody Northrop195d6622014-11-03 12:54:37 -07001163 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001164
Cody Northrop195d6622014-11-03 12:54:37 -07001165 if (! (m_compile_options & EOptionSuppressInfolog)) {
1166 puts(shader->getInfoLog());
1167 puts(shader->getInfoDebugLog());
1168 }
1169
1170 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001171 }
1172
1173 if (m_compile_options & EOptionDumpReflection) {
1174 program.buildReflection();
1175 program.dumpReflection();
1176 }
1177
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001178 glslang::GlslangToSpv(*program.getIntermediate(stage), spv);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001179
1180 return true;
1181}
1182
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001183
1184
1185XglTestImageRecord::XglTestImageRecord() : // Constructor
1186 m_width( 0 ),
1187 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001188 m_data( NULL ),
Tony Barbour96db8822015-02-25 12:28:39 -07001189 m_presentableImage( NULL ),
1190 m_presentableMemory( NULL),
Chia-I Wu837f9952014-12-15 23:29:34 +08001191 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001192{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001193}
1194
1195XglTestImageRecord::~XglTestImageRecord()
1196{
1197
1198}
1199
1200XglTestImageRecord::XglTestImageRecord(const XglTestImageRecord &copyin) // Copy constructor to handle pass by value.
1201{
1202 m_title = copyin.m_title;
1203 m_width = copyin.m_width;
1204 m_height = copyin.m_height;
1205 m_data_size = copyin.m_data_size;
1206 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
Tony Barbour96db8822015-02-25 12:28:39 -07001207 m_presentableImage = copyin.m_presentableImage;
1208 m_presentableMemory = copyin.m_presentableMemory;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001209}
1210
1211ostream &operator<<(ostream &output, const XglTestImageRecord &XglTestImageRecord)
1212{
1213 output << XglTestImageRecord.m_title << " (" << XglTestImageRecord.m_width <<
1214 "," << XglTestImageRecord.m_height << ")" << endl;
1215 return output;
1216}
1217
1218XglTestImageRecord& XglTestImageRecord::operator=(const XglTestImageRecord &rhs)
1219{
1220 m_title = rhs.m_title;
1221 m_width = rhs.m_width;
1222 m_height = rhs.m_height;
1223 m_data_size = rhs.m_data_size;
1224 m_data = rhs.m_data;
Tony Barbour96db8822015-02-25 12:28:39 -07001225 m_presentableImage = rhs.m_presentableImage;
1226 m_presentableMemory = rhs.m_presentableMemory;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001227 return *this;
1228}
1229
1230int XglTestImageRecord::operator==(const XglTestImageRecord &rhs) const
1231{
1232 if( this->m_data != rhs.m_data) return 0;
1233 return 1;
1234}
1235
1236// This function is required for built-in STL list functions like sort
1237int XglTestImageRecord::operator<(const XglTestImageRecord &rhs) const
1238{
1239 if( this->m_data_size < rhs.m_data_size ) return 1;
1240 return 0;
1241}
1242