blob: a2ffd664cf5131cc8c0bb1666e4a9c81fa3a860d [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;
Tony Barbour84d448c2015-04-02 14:02:33 -0600180 int x, y;
181 XglImage displayImage(image->device());
182
183 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, XGL_LINEAR_TILING);
184 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600185
186 filename.append(basename);
187 filename.append(".ppm");
188
189 const XGL_IMAGE_SUBRESOURCE sr = {
190 XGL_IMAGE_ASPECT_COLOR, 0, 0
191 };
192 XGL_SUBRESOURCE_LAYOUT sr_layout;
Chia-I Wu99ff89d2014-12-27 14:14:50 +0800193 size_t data_size = sizeof(sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600194
195 err = xglGetImageSubresourceInfo( image->image(), &sr,
196 XGL_INFO_TYPE_SUBRESOURCE_LAYOUT,
197 &data_size, &sr_layout);
198 ASSERT_XGL_SUCCESS( err );
199 ASSERT_EQ(data_size, sizeof(sr_layout));
200
Tony Barbour84d448c2015-04-02 14:02:33 -0600201 char *ptr;
202 ptr = (char *) displayImage.map();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600203 ptr += sr_layout.offset;
204
205 ofstream file (filename.c_str());
206 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
207
208 file << "P6\n";
Tony Barbour84d448c2015-04-02 14:02:33 -0600209 file << displayImage.width() << "\n";
210 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600211 file << 255 << "\n";
212
Tony Barbour84d448c2015-04-02 14:02:33 -0600213 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700214 const int *row = (const int *) ptr;
215 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600216
Tony Barbour84d448c2015-04-02 14:02:33 -0600217 if (displayImage.format() == XGL_FMT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700218 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600219 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700220 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
221 file.write((char *) &swapped, 3);
222 row++;
223 }
224 }
Tony Barbour84d448c2015-04-02 14:02:33 -0600225 else if (displayImage.format() == XGL_FMT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700226 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600227 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700228 file.write((char *) row, 3);
229 row++;
230 }
231 }
232 else {
233 printf("Unrecognized image format - will not write image files");
234 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600235 }
236
237 ptr += sr_layout.rowPitch;
238 }
239
240 file.close();
Tony Barbour84d448c2015-04-02 14:02:33 -0600241 displayImage.unmap();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600242}
243
Tony Barbour247bf372014-10-30 14:29:04 -0600244void XglTestFramework::Compare(const char *basename, XglImage *image )
245{
246
247 MagickWand *magick_wand_1;
248 MagickWand *magick_wand_2;
249 MagickWand *compare_wand;
250 MagickBooleanType status;
Tony Barbour4ab45422014-12-10 17:00:20 -0700251 char testimage[256],golden[PATH_MAX+256],golddir[PATH_MAX] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600252 double differenz;
253
Tony Barbour4ab45422014-12-10 17:00:20 -0700254 if (getenv("RENDERTEST_GOLDEN_DIR"))
255 {
256 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
257 }
258
Tony Barbour247bf372014-10-30 14:29:04 -0600259 MagickWandGenesis();
260 magick_wand_1=NewMagickWand();
261 sprintf(testimage,"%s.ppm",basename);
262 status=MagickReadImage(magick_wand_1,testimage);
263 ASSERT_TRUE(status) << "Unable to open file: " << testimage;
264
265
266 MagickWandGenesis();
267 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700268 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600269 status=MagickReadImage(magick_wand_2,golden);
270 ASSERT_TRUE(status) << "Unable to open file: " << golden;
271
Tony Barbour247bf372014-10-30 14:29:04 -0600272 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
273 if (differenz != 0.0)
274 {
275 char difference[256];
276
277 sprintf(difference,"%s-diff.ppm",basename);
278 status = MagickWriteImage(compare_wand, difference);
279 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
280 }
281 DestroyMagickWand(compare_wand);
282
283 DestroyMagickWand(magick_wand_1);
284 DestroyMagickWand(magick_wand_2);
285 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700286
287 if (differenz == 0.0)
288 {
289 /*
290 * If test image and golden image match, we do not need to
291 * keep around the test image.
292 */
293 remove(testimage);
294 }
Tony Barbour247bf372014-10-30 14:29:04 -0600295}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600296
297void XglTestFramework::Show(const char *comment, XglImage *image)
298{
299 XGL_RESULT err;
300
301 const XGL_IMAGE_SUBRESOURCE sr = {
302 XGL_IMAGE_ASPECT_COLOR, 0, 0
303 };
304 XGL_SUBRESOURCE_LAYOUT sr_layout;
Chia-I Wu99ff89d2014-12-27 14:14:50 +0800305 size_t data_size = sizeof(sr_layout);
Tony Barbour96db8822015-02-25 12:28:39 -0700306 XglTestImageRecord record;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600307
308 if (!m_show_images) return;
309
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600310 err = xglGetImageSubresourceInfo( image->image(), &sr, XGL_INFO_TYPE_SUBRESOURCE_LAYOUT,
311 &data_size, &sr_layout);
312 ASSERT_XGL_SUCCESS( err );
313 ASSERT_EQ(data_size, sizeof(sr_layout));
314
Tony Barbour96db8822015-02-25 12:28:39 -0700315 char *ptr;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600316
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600317 err = image->MapMemory( (void **) &ptr );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600318 ASSERT_XGL_SUCCESS( err );
319
320 ptr += sr_layout.offset;
321
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600322 record.m_title.append(comment);
323 record.m_width = image->width();
324 record.m_height = image->height();
325 // TODO: Need to make this more robust to handle different image formats
326 record.m_data_size = image->width()*image->height()*4;
327 record.m_data = malloc(record.m_data_size);
328 memcpy(record.m_data, ptr, record.m_data_size);
329 m_images.push_back(record);
330 m_display_image = --m_images.end();
331
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600332 err = image->UnmapMemory();
333 ASSERT_XGL_SUCCESS( err );
Tony Barbour96db8822015-02-25 12:28:39 -0700334
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600335}
336
Tony Barbour247bf372014-10-30 14:29:04 -0600337void XglTestFramework::RecordImage(XglImage *image, char *tag)
338{
339 const ::testing::TestInfo* const test_info =
340 ::testing::UnitTest::GetInstance()->current_test_info();
341 ostringstream filestream;
342 string filename;
343
344 filestream << test_info->name() << "-" << tag;
345 filename = filestream.str();
346 // ToDo - scrub string for bad characters
347
348 if (m_save_images || m_compare_images) {
349 WritePPM(filename.c_str(), image);
350 if (m_compare_images) {
351 Compare(filename.c_str(), image);
352 }
353 }
354
355 if (m_show_images) {
356 Show(test_info->name(), image);
357 }
358}
359
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600360void XglTestFramework::RecordImage(XglImage *image)
361{
362 const ::testing::TestInfo* const test_info =
363 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600364 ostringstream filestream;
365 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600366
Tony Barbour247bf372014-10-30 14:29:04 -0600367 m_width = 40;
368
369 if (strcmp(test_info->name(), m_testName.c_str())) {
370 filestream << test_info->name();
371 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700372 m_frameNum = 2;
373 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600374 }
375 else {
376 filestream << test_info->name() << "-" << m_frameNum;
377 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700378 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600379 }
380
381
382 // ToDo - scrub string for bad characters
383
384 if (m_save_images || m_compare_images) {
385 WritePPM(filename.c_str(), image);
386 if (m_compare_images) {
387 Compare(filename.c_str(), image);
388 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600389 }
390
391 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600392 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600393 }
394}
395
Tony Barbour96db8822015-02-25 12:28:39 -0700396static xgl_testing::Environment *environment;
397
398TestFrameworkXglPresent::TestFrameworkXglPresent() :
399m_device(environment->default_device()),
400m_queue(*m_device.graphics_queues()[0]),
401m_cmdbuf(m_device, xgl_testing::CmdBuffer::create_info(XGL_QUEUE_TYPE_GRAPHICS))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600402{
Tony Barbour96db8822015-02-25 12:28:39 -0700403 m_quit = false;
404 m_pause = false;
405 m_width = 0;
406 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600407}
408
Tony Barbour96db8822015-02-25 12:28:39 -0700409void TestFrameworkXglPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600410{
Tony Barbour96db8822015-02-25 12:28:39 -0700411 XGL_RESULT err;
412
Tony Barbourbdf0a312015-04-01 17:10:07 -0600413 XGL_WSI_X11_PRESENT_INFO present = {};
414 present.destWindow = m_window;
415 present.srcImage = m_display_image->m_presentableImage;
Tony Barbour96db8822015-02-25 12:28:39 -0700416
417 xcb_change_property (environment->m_connection,
418 XCB_PROP_MODE_REPLACE,
419 m_window,
420 XCB_ATOM_WM_NAME,
421 XCB_ATOM_STRING,
422 8,
423 m_display_image->m_title.size(),
424 m_display_image->m_title.c_str());
425
426 err = xglWsiX11QueuePresent(m_queue.obj(), &present, NULL);
427 assert(!err);
428
429 m_queue.wait();
430
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600431}
432
Tony Barbour96db8822015-02-25 12:28:39 -0700433void TestFrameworkXglPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600434{
Tony Barbour96db8822015-02-25 12:28:39 -0700435 u_int8_t event_code = event->response_type & 0x7f;
436 switch (event_code) {
437 case XCB_EXPOSE:
438 Display(); // TODO: handle resize
439 break;
440 case XCB_CLIENT_MESSAGE:
441 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
442 (m_atom_wm_delete_window)->atom) {
443 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600444 }
445 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700446 case XCB_KEY_RELEASE:
447 {
448 const xcb_key_release_event_t *key =
449 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600450
Tony Barbour96db8822015-02-25 12:28:39 -0700451 switch (key->detail) {
452 case 0x9: // Escape
453 m_quit = true;
454 break;
455 case 0x71: // left arrow key
456 if (m_display_image == m_images.begin()) {
457 m_display_image = --m_images.end();
458 } else {
459 --m_display_image;
460 }
461 break;
462 case 0x72: // right arrow key
463 ++m_display_image;
464 if (m_display_image == m_images.end()) {
465 m_display_image = m_images.begin();
466 }
467 break;
468 case 0x41:
469 m_pause = !m_pause;
470 break;
471 }
472 Display();
473 }
474 break;
475 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600476 break;
477 }
Tony Barbour96db8822015-02-25 12:28:39 -0700478}
479
480void TestFrameworkXglPresent::Run()
481{
482 xcb_flush(environment->m_connection);
483
484 while (! m_quit) {
485 xcb_generic_event_t *event;
486
487 if (m_pause) {
488 event = xcb_wait_for_event(environment->m_connection);
489 } else {
490 event = xcb_poll_for_event(environment->m_connection);
491 }
492 if (event) {
493 HandleEvent(event);
494 free(event);
495 }
496 }
497}
498
499void TestFrameworkXglPresent::CreatePresentableImages()
500{
501 XGL_RESULT err;
502
503 m_display_image = m_images.begin();
504
505 for (int x=0; x < m_images.size(); x++)
506 {
Tony Barbourbdf0a312015-04-01 17:10:07 -0600507 XGL_WSI_X11_PRESENTABLE_IMAGE_CREATE_INFO presentable_image_info = {};
508 presentable_image_info.format = XGL_FMT_B8G8R8A8_UNORM;
509 presentable_image_info.usage = XGL_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
510 presentable_image_info.extent.width = m_display_image->m_width;
511 presentable_image_info.extent.height = m_display_image->m_height;
512 presentable_image_info.flags = 0;
Tony Barbour96db8822015-02-25 12:28:39 -0700513
514 void *dest_ptr;
515
516 err = xglWsiX11CreatePresentableImage(m_device.obj(), &presentable_image_info,
517 &m_display_image->m_presentableImage, &m_display_image->m_presentableMemory);
518 assert(!err);
519
520 xgl_testing::Buffer buf;
521 buf.init(m_device, (XGL_GPU_SIZE) m_display_image->m_data_size);
522 dest_ptr = buf.map();
523 memcpy(dest_ptr,m_display_image->m_data, m_display_image->m_data_size);
524 buf.unmap();
525
526 m_cmdbuf.begin();
527
528 XGL_BUFFER_IMAGE_COPY region = {};
529 region.imageExtent.height = m_display_image->m_height;
530 region.imageExtent.width = m_display_image->m_width;
531 region.imageExtent.depth = 1;
532
533 xglCmdCopyBufferToImage(m_cmdbuf.obj(), buf.obj(), m_display_image->m_presentableImage, 1, &region);
534 m_cmdbuf.end();
535
536 uint32_t numMemRefs=2;
537 XGL_MEMORY_REF memRefs[2];
538 memRefs[0].flags = 0;
539 memRefs[0].mem = m_display_image->m_presentableMemory;
540 memRefs[1].flags = 0;
541 memRefs[1].mem = buf.memories()[0];
542
543 XGL_CMD_BUFFER cmdBufs[1];
544 cmdBufs[0] = m_cmdbuf.obj();
545
546 xglQueueSubmit(m_queue.obj(), 1, cmdBufs, numMemRefs, memRefs, NULL);
547 m_queue.wait();
548
549
550 if (m_display_image->m_width > m_width)
551 m_width = m_display_image->m_width;
552
553 if (m_display_image->m_height > m_height)
554 m_height = m_display_image->m_height;
555
556
557 ++m_display_image;
558
559 }
560
561 m_display_image = m_images.begin();
562}
563
564void TestFrameworkXglPresent::InitPresentFramework(std::list<XglTestImageRecord> &imagesIn)
565{
566 m_images = imagesIn;
567}
568
569void TestFrameworkXglPresent::CreateWindow()
570{
571 uint32_t value_mask, value_list[32];
572
573 m_window = xcb_generate_id(environment->m_connection);
574
575 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
576 value_list[0] = environment->m_screen->black_pixel;
577 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
578 XCB_EVENT_MASK_EXPOSURE |
579 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
580
581 xcb_create_window(environment->m_connection,
582 XCB_COPY_FROM_PARENT,
583 m_window, environment->m_screen->root,
584 0, 0, m_width, m_height, 0,
585 XCB_WINDOW_CLASS_INPUT_OUTPUT,
586 environment->m_screen->root_visual,
587 value_mask, value_list);
588
589 /* Magic code that will send notification when window is destroyed */
590 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(environment->m_connection, 1, 12,
591 "WM_PROTOCOLS");
592 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(environment->m_connection, cookie, 0);
593
594 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(environment->m_connection, 0, 16, "WM_DELETE_WINDOW");
595 m_atom_wm_delete_window = xcb_intern_atom_reply(environment->m_connection, cookie2, 0);
596
597 xcb_change_property(environment->m_connection, XCB_PROP_MODE_REPLACE,
598 m_window, (*reply).atom, 4, 32, 1,
599 &(*m_atom_wm_delete_window).atom);
600 free(reply);
601
602 xcb_map_window(environment->m_connection, m_window);
603}
604
605void TestFrameworkXglPresent::TearDown()
606{
607 xcb_destroy_window(environment->m_connection, m_window);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600608}
609
610void XglTestFramework::Finish()
611{
612 if (m_images.size() == 0) return;
613
Tony Barbour96db8822015-02-25 12:28:39 -0700614 environment = new xgl_testing::Environment();
615 ::testing::AddGlobalTestEnvironment(environment);
616 environment->X11SetUp();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600617
Tony Barbour96db8822015-02-25 12:28:39 -0700618 {
619 TestFrameworkXglPresent xglPresent;
620
621 xglPresent.InitPresentFramework(m_images);
622 xglPresent.CreatePresentableImages();
623 xglPresent.CreateWindow();
624 xglPresent.Run();
625 xglPresent.TearDown();
626 }
627 environment->TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600628}
629
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600630//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600631// These are the default resources for TBuiltInResources, used for both
632// - parsing this string for the case where the user didn't supply one
633// - dumping out a template for user construction of a config file
634//
635static const char* DefaultConfig =
636 "MaxLights 32\n"
637 "MaxClipPlanes 6\n"
638 "MaxTextureUnits 32\n"
639 "MaxTextureCoords 32\n"
640 "MaxVertexAttribs 64\n"
641 "MaxVertexUniformComponents 4096\n"
642 "MaxVaryingFloats 64\n"
643 "MaxVertexTextureImageUnits 32\n"
644 "MaxCombinedTextureImageUnits 80\n"
645 "MaxTextureImageUnits 32\n"
646 "MaxFragmentUniformComponents 4096\n"
647 "MaxDrawBuffers 32\n"
648 "MaxVertexUniformVectors 128\n"
649 "MaxVaryingVectors 8\n"
650 "MaxFragmentUniformVectors 16\n"
651 "MaxVertexOutputVectors 16\n"
652 "MaxFragmentInputVectors 15\n"
653 "MinProgramTexelOffset -8\n"
654 "MaxProgramTexelOffset 7\n"
655 "MaxClipDistances 8\n"
656 "MaxComputeWorkGroupCountX 65535\n"
657 "MaxComputeWorkGroupCountY 65535\n"
658 "MaxComputeWorkGroupCountZ 65535\n"
659 "MaxComputeWorkGroupSizeX 1024\n"
660 "MaxComputeWorkGroupSizeY 1024\n"
661 "MaxComputeWorkGroupSizeZ 64\n"
662 "MaxComputeUniformComponents 1024\n"
663 "MaxComputeTextureImageUnits 16\n"
664 "MaxComputeImageUniforms 8\n"
665 "MaxComputeAtomicCounters 8\n"
666 "MaxComputeAtomicCounterBuffers 1\n"
667 "MaxVaryingComponents 60\n"
668 "MaxVertexOutputComponents 64\n"
669 "MaxGeometryInputComponents 64\n"
670 "MaxGeometryOutputComponents 128\n"
671 "MaxFragmentInputComponents 128\n"
672 "MaxImageUnits 8\n"
673 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
674 "MaxCombinedShaderOutputResources 8\n"
675 "MaxImageSamples 0\n"
676 "MaxVertexImageUniforms 0\n"
677 "MaxTessControlImageUniforms 0\n"
678 "MaxTessEvaluationImageUniforms 0\n"
679 "MaxGeometryImageUniforms 0\n"
680 "MaxFragmentImageUniforms 8\n"
681 "MaxCombinedImageUniforms 8\n"
682 "MaxGeometryTextureImageUnits 16\n"
683 "MaxGeometryOutputVertices 256\n"
684 "MaxGeometryTotalOutputComponents 1024\n"
685 "MaxGeometryUniformComponents 1024\n"
686 "MaxGeometryVaryingComponents 64\n"
687 "MaxTessControlInputComponents 128\n"
688 "MaxTessControlOutputComponents 128\n"
689 "MaxTessControlTextureImageUnits 16\n"
690 "MaxTessControlUniformComponents 1024\n"
691 "MaxTessControlTotalOutputComponents 4096\n"
692 "MaxTessEvaluationInputComponents 128\n"
693 "MaxTessEvaluationOutputComponents 128\n"
694 "MaxTessEvaluationTextureImageUnits 16\n"
695 "MaxTessEvaluationUniformComponents 1024\n"
696 "MaxTessPatchComponents 120\n"
697 "MaxPatchVertices 32\n"
698 "MaxTessGenLevel 64\n"
699 "MaxViewports 16\n"
700 "MaxVertexAtomicCounters 0\n"
701 "MaxTessControlAtomicCounters 0\n"
702 "MaxTessEvaluationAtomicCounters 0\n"
703 "MaxGeometryAtomicCounters 0\n"
704 "MaxFragmentAtomicCounters 8\n"
705 "MaxCombinedAtomicCounters 8\n"
706 "MaxAtomicCounterBindings 1\n"
707 "MaxVertexAtomicCounterBuffers 0\n"
708 "MaxTessControlAtomicCounterBuffers 0\n"
709 "MaxTessEvaluationAtomicCounterBuffers 0\n"
710 "MaxGeometryAtomicCounterBuffers 0\n"
711 "MaxFragmentAtomicCounterBuffers 1\n"
712 "MaxCombinedAtomicCounterBuffers 1\n"
713 "MaxAtomicCounterBufferSize 16384\n"
714 "MaxTransformFeedbackBuffers 4\n"
715 "MaxTransformFeedbackInterleavedComponents 64\n"
716 "MaxCullDistances 8\n"
717 "MaxCombinedClipAndCullDistances 8\n"
718 "MaxSamples 4\n"
719
720 "nonInductiveForLoops 1\n"
721 "whileLoops 1\n"
722 "doWhileLoops 1\n"
723 "generalUniformIndexing 1\n"
724 "generalAttributeMatrixVectorIndexing 1\n"
725 "generalVaryingIndexing 1\n"
726 "generalSamplerIndexing 1\n"
727 "generalVariableIndexing 1\n"
728 "generalConstantMatrixVectorIndexing 1\n"
729 ;
730
731//
732// *.conf => this is a config file that can set limits/resources
733//
734bool XglTestFramework::SetConfigFile(const std::string& name)
735{
736 if (name.size() < 5)
737 return false;
738
739 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
740 ConfigFile = name;
741 return true;
742 }
743
744 return false;
745}
746
747//
748// Parse either a .conf file provided by the user or the default string above.
749//
750void XglTestFramework::ProcessConfigFile()
751{
752 char** configStrings = 0;
753 char* config = 0;
754 if (ConfigFile.size() > 0) {
755 configStrings = ReadFileData(ConfigFile.c_str());
756 if (configStrings)
757 config = *configStrings;
758 else {
759 printf("Error opening configuration file; will instead use the default configuration\n");
760 }
761 }
762
763 if (config == 0) {
764 config = new char[strlen(DefaultConfig) + 1];
765 strcpy(config, DefaultConfig);
766 }
767
768 const char* delims = " \t\n\r";
769 const char* token = strtok(config, delims);
770 while (token) {
771 const char* valueStr = strtok(0, delims);
772 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
773 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
774 return;
775 }
776 int value = atoi(valueStr);
777
778 if (strcmp(token, "MaxLights") == 0)
779 Resources.maxLights = value;
780 else if (strcmp(token, "MaxClipPlanes") == 0)
781 Resources.maxClipPlanes = value;
782 else if (strcmp(token, "MaxTextureUnits") == 0)
783 Resources.maxTextureUnits = value;
784 else if (strcmp(token, "MaxTextureCoords") == 0)
785 Resources.maxTextureCoords = value;
786 else if (strcmp(token, "MaxVertexAttribs") == 0)
787 Resources.maxVertexAttribs = value;
788 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
789 Resources.maxVertexUniformComponents = value;
790 else if (strcmp(token, "MaxVaryingFloats") == 0)
791 Resources.maxVaryingFloats = value;
792 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
793 Resources.maxVertexTextureImageUnits = value;
794 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
795 Resources.maxCombinedTextureImageUnits = value;
796 else if (strcmp(token, "MaxTextureImageUnits") == 0)
797 Resources.maxTextureImageUnits = value;
798 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
799 Resources.maxFragmentUniformComponents = value;
800 else if (strcmp(token, "MaxDrawBuffers") == 0)
801 Resources.maxDrawBuffers = value;
802 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
803 Resources.maxVertexUniformVectors = value;
804 else if (strcmp(token, "MaxVaryingVectors") == 0)
805 Resources.maxVaryingVectors = value;
806 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
807 Resources.maxFragmentUniformVectors = value;
808 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
809 Resources.maxVertexOutputVectors = value;
810 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
811 Resources.maxFragmentInputVectors = value;
812 else if (strcmp(token, "MinProgramTexelOffset") == 0)
813 Resources.minProgramTexelOffset = value;
814 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
815 Resources.maxProgramTexelOffset = value;
816 else if (strcmp(token, "MaxClipDistances") == 0)
817 Resources.maxClipDistances = value;
818 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
819 Resources.maxComputeWorkGroupCountX = value;
820 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
821 Resources.maxComputeWorkGroupCountY = value;
822 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
823 Resources.maxComputeWorkGroupCountZ = value;
824 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
825 Resources.maxComputeWorkGroupSizeX = value;
826 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
827 Resources.maxComputeWorkGroupSizeY = value;
828 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
829 Resources.maxComputeWorkGroupSizeZ = value;
830 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
831 Resources.maxComputeUniformComponents = value;
832 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
833 Resources.maxComputeTextureImageUnits = value;
834 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
835 Resources.maxComputeImageUniforms = value;
836 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
837 Resources.maxComputeAtomicCounters = value;
838 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
839 Resources.maxComputeAtomicCounterBuffers = value;
840 else if (strcmp(token, "MaxVaryingComponents") == 0)
841 Resources.maxVaryingComponents = value;
842 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
843 Resources.maxVertexOutputComponents = value;
844 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
845 Resources.maxGeometryInputComponents = value;
846 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
847 Resources.maxGeometryOutputComponents = value;
848 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
849 Resources.maxFragmentInputComponents = value;
850 else if (strcmp(token, "MaxImageUnits") == 0)
851 Resources.maxImageUnits = value;
852 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
853 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
854 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
855 Resources.maxCombinedShaderOutputResources = value;
856 else if (strcmp(token, "MaxImageSamples") == 0)
857 Resources.maxImageSamples = value;
858 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
859 Resources.maxVertexImageUniforms = value;
860 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
861 Resources.maxTessControlImageUniforms = value;
862 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
863 Resources.maxTessEvaluationImageUniforms = value;
864 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
865 Resources.maxGeometryImageUniforms = value;
866 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
867 Resources.maxFragmentImageUniforms = value;
868 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
869 Resources.maxCombinedImageUniforms = value;
870 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
871 Resources.maxGeometryTextureImageUnits = value;
872 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
873 Resources.maxGeometryOutputVertices = value;
874 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
875 Resources.maxGeometryTotalOutputComponents = value;
876 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
877 Resources.maxGeometryUniformComponents = value;
878 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
879 Resources.maxGeometryVaryingComponents = value;
880 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
881 Resources.maxTessControlInputComponents = value;
882 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
883 Resources.maxTessControlOutputComponents = value;
884 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
885 Resources.maxTessControlTextureImageUnits = value;
886 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
887 Resources.maxTessControlUniformComponents = value;
888 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
889 Resources.maxTessControlTotalOutputComponents = value;
890 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
891 Resources.maxTessEvaluationInputComponents = value;
892 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
893 Resources.maxTessEvaluationOutputComponents = value;
894 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
895 Resources.maxTessEvaluationTextureImageUnits = value;
896 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
897 Resources.maxTessEvaluationUniformComponents = value;
898 else if (strcmp(token, "MaxTessPatchComponents") == 0)
899 Resources.maxTessPatchComponents = value;
900 else if (strcmp(token, "MaxPatchVertices") == 0)
901 Resources.maxPatchVertices = value;
902 else if (strcmp(token, "MaxTessGenLevel") == 0)
903 Resources.maxTessGenLevel = value;
904 else if (strcmp(token, "MaxViewports") == 0)
905 Resources.maxViewports = value;
906 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
907 Resources.maxVertexAtomicCounters = value;
908 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
909 Resources.maxTessControlAtomicCounters = value;
910 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
911 Resources.maxTessEvaluationAtomicCounters = value;
912 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
913 Resources.maxGeometryAtomicCounters = value;
914 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
915 Resources.maxFragmentAtomicCounters = value;
916 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
917 Resources.maxCombinedAtomicCounters = value;
918 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
919 Resources.maxAtomicCounterBindings = value;
920 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
921 Resources.maxVertexAtomicCounterBuffers = value;
922 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
923 Resources.maxTessControlAtomicCounterBuffers = value;
924 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
925 Resources.maxTessEvaluationAtomicCounterBuffers = value;
926 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
927 Resources.maxGeometryAtomicCounterBuffers = value;
928 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
929 Resources.maxFragmentAtomicCounterBuffers = value;
930 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
931 Resources.maxCombinedAtomicCounterBuffers = value;
932 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
933 Resources.maxAtomicCounterBufferSize = value;
934 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
935 Resources.maxTransformFeedbackBuffers = value;
936 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
937 Resources.maxTransformFeedbackInterleavedComponents = value;
938 else if (strcmp(token, "MaxCullDistances") == 0)
939 Resources.maxCullDistances = value;
940 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
941 Resources.maxCombinedClipAndCullDistances = value;
942 else if (strcmp(token, "MaxSamples") == 0)
943 Resources.maxSamples = value;
944
945 else if (strcmp(token, "nonInductiveForLoops") == 0)
946 Resources.limits.nonInductiveForLoops = (value != 0);
947 else if (strcmp(token, "whileLoops") == 0)
948 Resources.limits.whileLoops = (value != 0);
949 else if (strcmp(token, "doWhileLoops") == 0)
950 Resources.limits.doWhileLoops = (value != 0);
951 else if (strcmp(token, "generalUniformIndexing") == 0)
952 Resources.limits.generalUniformIndexing = (value != 0);
953 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
954 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
955 else if (strcmp(token, "generalVaryingIndexing") == 0)
956 Resources.limits.generalVaryingIndexing = (value != 0);
957 else if (strcmp(token, "generalSamplerIndexing") == 0)
958 Resources.limits.generalSamplerIndexing = (value != 0);
959 else if (strcmp(token, "generalVariableIndexing") == 0)
960 Resources.limits.generalVariableIndexing = (value != 0);
961 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
962 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
963 else
964 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
965
966 token = strtok(0, delims);
967 }
968 if (configStrings)
969 FreeFileData(configStrings);
970}
971
972void XglTestFramework::SetMessageOptions(EShMessages& messages)
973{
974 if (m_compile_options & EOptionRelaxedErrors)
975 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
976 if (m_compile_options & EOptionIntermediate)
977 messages = (EShMessages)(messages | EShMsgAST);
978 if (m_compile_options & EOptionSuppressWarnings)
979 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
980}
981
982//
983// Malloc a string of sufficient size and read a string into it.
984//
985char** XglTestFramework::ReadFileData(const char* fileName)
986{
987 FILE *in;
988 #if defined(_WIN32) && defined(__GNUC__)
989 in = fopen(fileName, "r");
990 int errorCode = in ? 0 : 1;
991 #else
992 int errorCode = fopen_s(&in, fileName, "r");
993 #endif
994
995 char *fdata;
996 int count = 0;
997 const int maxSourceStrings = 5;
998 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
999
1000 if (errorCode) {
1001 printf("Error: unable to open input file: %s\n", fileName);
1002 return 0;
1003 }
1004
1005 while (fgetc(in) != EOF)
1006 count++;
1007
1008 fseek(in, 0, SEEK_SET);
1009
1010 if (!(fdata = (char*)malloc(count+2))) {
1011 printf("Error allocating memory\n");
1012 return 0;
1013 }
1014 if (fread(fdata,1,count, in)!=count) {
1015 printf("Error reading input file: %s\n", fileName);
1016 return 0;
1017 }
1018 fdata[count] = '\0';
1019 fclose(in);
1020 if (count == 0) {
1021 return_data[0]=(char*)malloc(count+2);
1022 return_data[0][0]='\0';
1023 m_num_shader_strings = 0;
1024 return return_data;
1025 } else
1026 m_num_shader_strings = 1;
1027
1028 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1029 int ptr_len=0,i=0;
1030 while(count>0){
1031 return_data[i]=(char*)malloc(len+2);
1032 memcpy(return_data[i],fdata+ptr_len,len);
1033 return_data[i][len]='\0';
1034 count-=(len);
1035 ptr_len+=(len);
1036 if(count<len){
1037 if(count==0){
1038 m_num_shader_strings=(i+1);
1039 break;
1040 }
1041 len = count;
1042 }
1043 ++i;
1044 }
1045 return return_data;
1046}
1047
1048void XglTestFramework::FreeFileData(char** data)
1049{
1050 for(int i=0;i<m_num_shader_strings;i++)
1051 free(data[i]);
1052}
1053
1054//
1055// Deduce the language from the filename. Files must end in one of the
1056// following extensions:
1057//
1058// .vert = vertex
1059// .tesc = tessellation control
1060// .tese = tessellation evaluation
1061// .geom = geometry
1062// .frag = fragment
1063// .comp = compute
1064//
1065EShLanguage XglTestFramework::FindLanguage(const std::string& name)
1066{
1067 size_t ext = name.rfind('.');
1068 if (ext == std::string::npos) {
1069 return EShLangVertex;
1070 }
1071
1072 std::string suffix = name.substr(ext + 1, std::string::npos);
1073 if (suffix == "vert")
1074 return EShLangVertex;
1075 else if (suffix == "tesc")
1076 return EShLangTessControl;
1077 else if (suffix == "tese")
1078 return EShLangTessEvaluation;
1079 else if (suffix == "geom")
1080 return EShLangGeometry;
1081 else if (suffix == "frag")
1082 return EShLangFragment;
1083 else if (suffix == "comp")
1084 return EShLangCompute;
1085
1086 return EShLangVertex;
1087}
1088
1089//
1090// Convert XGL shader type to compiler's
1091//
1092EShLanguage XglTestFramework::FindLanguage(const XGL_PIPELINE_SHADER_STAGE shader_type)
1093{
1094 switch (shader_type) {
1095 case XGL_SHADER_STAGE_VERTEX:
1096 return EShLangVertex;
1097
1098 case XGL_SHADER_STAGE_TESS_CONTROL:
1099 return EShLangTessControl;
1100
1101 case XGL_SHADER_STAGE_TESS_EVALUATION:
1102 return EShLangTessEvaluation;
1103
1104 case XGL_SHADER_STAGE_GEOMETRY:
1105 return EShLangGeometry;
1106
1107 case XGL_SHADER_STAGE_FRAGMENT:
1108 return EShLangFragment;
1109
1110 case XGL_SHADER_STAGE_COMPUTE:
1111 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001112
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001113 default:
1114 return EShLangVertex;
1115 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001116}
1117
1118
1119//
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001120// Compile a given string containing GLSL into SPV for use by XGL
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001121// Return value of false means an error was encountered.
1122//
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001123bool XglTestFramework::GLSLtoSPV(const XGL_PIPELINE_SHADER_STAGE shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001124 const char *pshader,
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001125 std::vector<unsigned int> &spv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001126{
1127 glslang::TProgram& program = *new glslang::TProgram;
1128 const char *shaderStrings[1];
1129
1130 // TODO: Do we want to load a special config file depending on the
1131 // shader source? Optional name maybe?
1132 // SetConfigFile(fileName);
1133
1134 ProcessConfigFile();
1135
1136 EShMessages messages = EShMsgDefault;
1137 SetMessageOptions(messages);
1138
1139 EShLanguage stage = FindLanguage(shader_type);
1140 glslang::TShader* shader = new glslang::TShader(stage);
1141
1142 shaderStrings[0] = pshader;
1143 shader->setStrings(shaderStrings, 1);
1144
1145 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1146
Cody Northrop195d6622014-11-03 12:54:37 -07001147 if (! (m_compile_options & EOptionSuppressInfolog)) {
1148 puts(shader->getInfoLog());
1149 puts(shader->getInfoDebugLog());
1150 }
1151
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001152 return false; // something didn't work
1153 }
1154
1155 program.addShader(shader);
1156
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001157
1158 //
1159 // Program-level processing...
1160 //
1161
Cody Northrop195d6622014-11-03 12:54:37 -07001162 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001163
Cody Northrop195d6622014-11-03 12:54:37 -07001164 if (! (m_compile_options & EOptionSuppressInfolog)) {
1165 puts(shader->getInfoLog());
1166 puts(shader->getInfoDebugLog());
1167 }
1168
1169 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001170 }
1171
1172 if (m_compile_options & EOptionDumpReflection) {
1173 program.buildReflection();
1174 program.dumpReflection();
1175 }
1176
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001177 glslang::GlslangToSpv(*program.getIntermediate(stage), spv);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001178
1179 return true;
1180}
1181
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001182
1183
1184XglTestImageRecord::XglTestImageRecord() : // Constructor
1185 m_width( 0 ),
1186 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001187 m_data( NULL ),
Tony Barbour96db8822015-02-25 12:28:39 -07001188 m_presentableImage( NULL ),
1189 m_presentableMemory( NULL),
Chia-I Wu837f9952014-12-15 23:29:34 +08001190 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001191{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001192}
1193
1194XglTestImageRecord::~XglTestImageRecord()
1195{
1196
1197}
1198
1199XglTestImageRecord::XglTestImageRecord(const XglTestImageRecord &copyin) // Copy constructor to handle pass by value.
1200{
1201 m_title = copyin.m_title;
1202 m_width = copyin.m_width;
1203 m_height = copyin.m_height;
1204 m_data_size = copyin.m_data_size;
1205 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
Tony Barbour96db8822015-02-25 12:28:39 -07001206 m_presentableImage = copyin.m_presentableImage;
1207 m_presentableMemory = copyin.m_presentableMemory;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001208}
1209
1210ostream &operator<<(ostream &output, const XglTestImageRecord &XglTestImageRecord)
1211{
1212 output << XglTestImageRecord.m_title << " (" << XglTestImageRecord.m_width <<
1213 "," << XglTestImageRecord.m_height << ")" << endl;
1214 return output;
1215}
1216
1217XglTestImageRecord& XglTestImageRecord::operator=(const XglTestImageRecord &rhs)
1218{
1219 m_title = rhs.m_title;
1220 m_width = rhs.m_width;
1221 m_height = rhs.m_height;
1222 m_data_size = rhs.m_data_size;
1223 m_data = rhs.m_data;
Tony Barbour96db8822015-02-25 12:28:39 -07001224 m_presentableImage = rhs.m_presentableImage;
1225 m_presentableMemory = rhs.m_presentableMemory;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001226 return *this;
1227}
1228
1229int XglTestImageRecord::operator==(const XglTestImageRecord &rhs) const
1230{
1231 if( this->m_data != rhs.m_data) return 0;
1232 return 1;
1233}
1234
1235// This function is required for built-in STL list functions like sort
1236int XglTestImageRecord::operator<(const XglTestImageRecord &rhs) const
1237{
1238 if( this->m_data_size < rhs.m_data_size ) return 1;
1239 return 0;
1240}
1241