blob: 20b03f2456d1201a0acd17e2f11e0a69600f0004 [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;
Tony Barbour0dd968a2015-04-02 15:48:24 -0600110#ifdef _WIN32
111bool XglTestFramework::m_use_spv = false;
112#else
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600113bool XglTestFramework::m_use_spv = true;
Tony Barbour0dd968a2015-04-02 15:48:24 -0600114#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600115int XglTestFramework::m_width = 0;
116int XglTestFramework::m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600117std::list<XglTestImageRecord> XglTestFramework::m_images;
118std::list<XglTestImageRecord>::iterator XglTestFramework::m_display_image;
119int m_display_image_idx = 0;
120
121void XglTestFramework::InitArgs(int *argc, char *argv[])
122{
123 int i, n;
124
125 for (i=0, n=0; i< *argc; i++) {
126 if (strncmp("--show-images", argv[i], 13) == 0) {
127 m_show_images = true;
128 continue;
129 }
130 if (strncmp("--save-images", argv[i], 13) == 0) {
131 m_save_images = true;
132 continue;
133 }
134
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600135 if (strncmp("--use-SPV", argv[i], 13) == 0) {
136 m_use_spv = true;
Courtney Goeltzenleuchterb666dc62014-10-09 09:13:56 -0600137 continue;
138 }
139
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600140 if (strncmp("--no-SPV", argv[i], 13) == 0) {
141 m_use_spv = false;
Courtney Goeltzenleuchterc44e3ee2014-10-31 14:13:33 -0600142 continue;
143 }
144
Tony Barbour247bf372014-10-30 14:29:04 -0600145 if (strncmp("--compare-images", argv[i], 16) == 0) {
146 m_compare_images = true;
147 continue;
148 }
149
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600150 /*
151 * Since the above "consume" inputs, update argv
152 * so that it contains the trimmed list of args for glutInit
153 */
Tony Barboura98d3932014-12-11 09:52:49 -0700154 if (strncmp("--help", argv[i], 6) == 0 || strncmp("-h", argv[i], 2) == 0) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700155 printf("\nOther options:\n");
156 printf("\t--show-images\n"
157 "\t\tDisplay test images in viewer after tests complete.\n");
158 printf("\t--save-images\n"
159 "\t\tSave tests images as ppm files in current working directory.\n"
160 "\t\tUsed to generate golden images for compare-images.\n");
161 printf("\t--compare-images\n"
162 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barboura98d3932014-12-11 09:52:49 -0700163 "\t\tAlso saves the generated test image in current working\n"
164 "\t\t\tdirectory but only if the image is different from the golden\n"
165 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
166 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700167 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600168 printf("\t--use-SPV\n"
169 "\t\tUse SPV code path (default).\n");
170 printf("\t--no-SPV\n"
171 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700172 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700173 }
174
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600175 argv[n] = argv[i];
176 n++;
177 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600178}
179
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600180void XglTestFramework::WritePPM( const char *basename, XglImage *image )
181{
182 string filename;
183 XGL_RESULT err;
Tony Barbour84d448c2015-04-02 14:02:33 -0600184 int x, y;
185 XglImage displayImage(image->device());
186
187 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, XGL_LINEAR_TILING);
188 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600189
190 filename.append(basename);
191 filename.append(".ppm");
192
193 const XGL_IMAGE_SUBRESOURCE sr = {
194 XGL_IMAGE_ASPECT_COLOR, 0, 0
195 };
196 XGL_SUBRESOURCE_LAYOUT sr_layout;
Chia-I Wu99ff89d2014-12-27 14:14:50 +0800197 size_t data_size = sizeof(sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600198
199 err = xglGetImageSubresourceInfo( image->image(), &sr,
200 XGL_INFO_TYPE_SUBRESOURCE_LAYOUT,
201 &data_size, &sr_layout);
202 ASSERT_XGL_SUCCESS( err );
203 ASSERT_EQ(data_size, sizeof(sr_layout));
204
Tony Barbour84d448c2015-04-02 14:02:33 -0600205 char *ptr;
206 ptr = (char *) displayImage.map();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600207 ptr += sr_layout.offset;
208
209 ofstream file (filename.c_str());
210 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
211
212 file << "P6\n";
Tony Barbour84d448c2015-04-02 14:02:33 -0600213 file << displayImage.width() << "\n";
214 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600215 file << 255 << "\n";
216
Tony Barbour84d448c2015-04-02 14:02:33 -0600217 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700218 const int *row = (const int *) ptr;
219 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600220
Tony Barbour84d448c2015-04-02 14:02:33 -0600221 if (displayImage.format() == XGL_FMT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700222 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600223 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700224 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
225 file.write((char *) &swapped, 3);
226 row++;
227 }
228 }
Tony Barbour84d448c2015-04-02 14:02:33 -0600229 else if (displayImage.format() == XGL_FMT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700230 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600231 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700232 file.write((char *) row, 3);
233 row++;
234 }
235 }
236 else {
237 printf("Unrecognized image format - will not write image files");
238 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600239 }
240
241 ptr += sr_layout.rowPitch;
242 }
243
244 file.close();
Tony Barbour84d448c2015-04-02 14:02:33 -0600245 displayImage.unmap();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600246}
247
Tony Barbour247bf372014-10-30 14:29:04 -0600248void XglTestFramework::Compare(const char *basename, XglImage *image )
249{
250
251 MagickWand *magick_wand_1;
252 MagickWand *magick_wand_2;
253 MagickWand *compare_wand;
254 MagickBooleanType status;
Tony Barbour4ab45422014-12-10 17:00:20 -0700255 char testimage[256],golden[PATH_MAX+256],golddir[PATH_MAX] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600256 double differenz;
257
Tony Barbour4ab45422014-12-10 17:00:20 -0700258 if (getenv("RENDERTEST_GOLDEN_DIR"))
259 {
260 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
261 }
262
Tony Barbour247bf372014-10-30 14:29:04 -0600263 MagickWandGenesis();
264 magick_wand_1=NewMagickWand();
265 sprintf(testimage,"%s.ppm",basename);
266 status=MagickReadImage(magick_wand_1,testimage);
267 ASSERT_TRUE(status) << "Unable to open file: " << testimage;
268
269
270 MagickWandGenesis();
271 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700272 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600273 status=MagickReadImage(magick_wand_2,golden);
274 ASSERT_TRUE(status) << "Unable to open file: " << golden;
275
Tony Barbour247bf372014-10-30 14:29:04 -0600276 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
277 if (differenz != 0.0)
278 {
279 char difference[256];
280
281 sprintf(difference,"%s-diff.ppm",basename);
282 status = MagickWriteImage(compare_wand, difference);
283 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
284 }
285 DestroyMagickWand(compare_wand);
286
287 DestroyMagickWand(magick_wand_1);
288 DestroyMagickWand(magick_wand_2);
289 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700290
291 if (differenz == 0.0)
292 {
293 /*
294 * If test image and golden image match, we do not need to
295 * keep around the test image.
296 */
297 remove(testimage);
298 }
Tony Barbour247bf372014-10-30 14:29:04 -0600299}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600300
301void XglTestFramework::Show(const char *comment, XglImage *image)
302{
303 XGL_RESULT err;
304
305 const XGL_IMAGE_SUBRESOURCE sr = {
306 XGL_IMAGE_ASPECT_COLOR, 0, 0
307 };
308 XGL_SUBRESOURCE_LAYOUT sr_layout;
Chia-I Wu99ff89d2014-12-27 14:14:50 +0800309 size_t data_size = sizeof(sr_layout);
Tony Barbour96db8822015-02-25 12:28:39 -0700310 XglTestImageRecord record;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600311
312 if (!m_show_images) return;
313
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600314 err = xglGetImageSubresourceInfo( image->image(), &sr, XGL_INFO_TYPE_SUBRESOURCE_LAYOUT,
315 &data_size, &sr_layout);
316 ASSERT_XGL_SUCCESS( err );
317 ASSERT_EQ(data_size, sizeof(sr_layout));
318
Tony Barbour96db8822015-02-25 12:28:39 -0700319 char *ptr;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600320
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600321 err = image->MapMemory( (void **) &ptr );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600322 ASSERT_XGL_SUCCESS( err );
323
324 ptr += sr_layout.offset;
325
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600326 record.m_title.append(comment);
327 record.m_width = image->width();
328 record.m_height = image->height();
329 // TODO: Need to make this more robust to handle different image formats
330 record.m_data_size = image->width()*image->height()*4;
331 record.m_data = malloc(record.m_data_size);
332 memcpy(record.m_data, ptr, record.m_data_size);
333 m_images.push_back(record);
334 m_display_image = --m_images.end();
335
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600336 err = image->UnmapMemory();
337 ASSERT_XGL_SUCCESS( err );
Tony Barbour96db8822015-02-25 12:28:39 -0700338
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600339}
340
Tony Barbour247bf372014-10-30 14:29:04 -0600341void XglTestFramework::RecordImage(XglImage *image, char *tag)
342{
343 const ::testing::TestInfo* const test_info =
344 ::testing::UnitTest::GetInstance()->current_test_info();
345 ostringstream filestream;
346 string filename;
347
348 filestream << test_info->name() << "-" << tag;
349 filename = filestream.str();
350 // ToDo - scrub string for bad characters
351
352 if (m_save_images || m_compare_images) {
353 WritePPM(filename.c_str(), image);
354 if (m_compare_images) {
355 Compare(filename.c_str(), image);
356 }
357 }
358
359 if (m_show_images) {
360 Show(test_info->name(), image);
361 }
362}
363
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600364void XglTestFramework::RecordImage(XglImage *image)
365{
366 const ::testing::TestInfo* const test_info =
367 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600368 ostringstream filestream;
369 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600370
Tony Barbour247bf372014-10-30 14:29:04 -0600371 m_width = 40;
372
373 if (strcmp(test_info->name(), m_testName.c_str())) {
374 filestream << test_info->name();
375 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700376 m_frameNum = 2;
377 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600378 }
379 else {
380 filestream << test_info->name() << "-" << m_frameNum;
381 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700382 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600383 }
384
385
386 // ToDo - scrub string for bad characters
387
388 if (m_save_images || m_compare_images) {
389 WritePPM(filename.c_str(), image);
390 if (m_compare_images) {
391 Compare(filename.c_str(), image);
392 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600393 }
394
395 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600396 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600397 }
398}
399
Tony Barbour96db8822015-02-25 12:28:39 -0700400static xgl_testing::Environment *environment;
401
402TestFrameworkXglPresent::TestFrameworkXglPresent() :
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700403 m_device(environment->default_device()),
404 m_queue(*m_device.graphics_queues()[0]),
405 m_cmdbuf(m_device, xgl_testing::CmdBuffer::create_info(m_device.graphics_queue_node_index_))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600406{
Tony Barbour96db8822015-02-25 12:28:39 -0700407 m_quit = false;
408 m_pause = false;
409 m_width = 0;
410 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600411}
412
Tony Barbour96db8822015-02-25 12:28:39 -0700413void TestFrameworkXglPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600414{
Tony Barbour96db8822015-02-25 12:28:39 -0700415 XGL_RESULT err;
416
Tony Barbourbdf0a312015-04-01 17:10:07 -0600417 XGL_WSI_X11_PRESENT_INFO present = {};
418 present.destWindow = m_window;
419 present.srcImage = m_display_image->m_presentableImage;
Tony Barbour96db8822015-02-25 12:28:39 -0700420
421 xcb_change_property (environment->m_connection,
422 XCB_PROP_MODE_REPLACE,
423 m_window,
424 XCB_ATOM_WM_NAME,
425 XCB_ATOM_STRING,
426 8,
427 m_display_image->m_title.size(),
428 m_display_image->m_title.c_str());
429
430 err = xglWsiX11QueuePresent(m_queue.obj(), &present, NULL);
431 assert(!err);
432
433 m_queue.wait();
434
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600435}
436
Tony Barbour96db8822015-02-25 12:28:39 -0700437void TestFrameworkXglPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600438{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600439 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700440 switch (event_code) {
441 case XCB_EXPOSE:
442 Display(); // TODO: handle resize
443 break;
444 case XCB_CLIENT_MESSAGE:
445 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
446 (m_atom_wm_delete_window)->atom) {
447 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600448 }
449 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700450 case XCB_KEY_RELEASE:
451 {
452 const xcb_key_release_event_t *key =
453 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600454
Tony Barbour96db8822015-02-25 12:28:39 -0700455 switch (key->detail) {
456 case 0x9: // Escape
457 m_quit = true;
458 break;
459 case 0x71: // left arrow key
460 if (m_display_image == m_images.begin()) {
461 m_display_image = --m_images.end();
462 } else {
463 --m_display_image;
464 }
465 break;
466 case 0x72: // right arrow key
467 ++m_display_image;
468 if (m_display_image == m_images.end()) {
469 m_display_image = m_images.begin();
470 }
471 break;
472 case 0x41:
473 m_pause = !m_pause;
474 break;
475 }
476 Display();
477 }
478 break;
479 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600480 break;
481 }
Tony Barbour96db8822015-02-25 12:28:39 -0700482}
483
484void TestFrameworkXglPresent::Run()
485{
486 xcb_flush(environment->m_connection);
487
488 while (! m_quit) {
489 xcb_generic_event_t *event;
490
491 if (m_pause) {
492 event = xcb_wait_for_event(environment->m_connection);
493 } else {
494 event = xcb_poll_for_event(environment->m_connection);
495 }
496 if (event) {
497 HandleEvent(event);
498 free(event);
499 }
500 }
501}
502
503void TestFrameworkXglPresent::CreatePresentableImages()
504{
505 XGL_RESULT err;
506
507 m_display_image = m_images.begin();
508
509 for (int x=0; x < m_images.size(); x++)
510 {
Tony Barbourbdf0a312015-04-01 17:10:07 -0600511 XGL_WSI_X11_PRESENTABLE_IMAGE_CREATE_INFO presentable_image_info = {};
512 presentable_image_info.format = XGL_FMT_B8G8R8A8_UNORM;
513 presentable_image_info.usage = XGL_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
514 presentable_image_info.extent.width = m_display_image->m_width;
515 presentable_image_info.extent.height = m_display_image->m_height;
516 presentable_image_info.flags = 0;
Tony Barbour96db8822015-02-25 12:28:39 -0700517
518 void *dest_ptr;
519
520 err = xglWsiX11CreatePresentableImage(m_device.obj(), &presentable_image_info,
521 &m_display_image->m_presentableImage, &m_display_image->m_presentableMemory);
522 assert(!err);
523
524 xgl_testing::Buffer buf;
525 buf.init(m_device, (XGL_GPU_SIZE) m_display_image->m_data_size);
526 dest_ptr = buf.map();
527 memcpy(dest_ptr,m_display_image->m_data, m_display_image->m_data_size);
528 buf.unmap();
529
530 m_cmdbuf.begin();
531
532 XGL_BUFFER_IMAGE_COPY region = {};
533 region.imageExtent.height = m_display_image->m_height;
534 region.imageExtent.width = m_display_image->m_width;
535 region.imageExtent.depth = 1;
536
Courtney Goeltzenleuchterb3efe9b2015-03-25 11:25:10 -0600537 xglCmdCopyBufferToImage(m_cmdbuf.obj(),
538 buf.obj(),
539 m_display_image->m_presentableImage, XGL_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
540 1, &region);
Tony Barbour96db8822015-02-25 12:28:39 -0700541 m_cmdbuf.end();
542
543 uint32_t numMemRefs=2;
544 XGL_MEMORY_REF memRefs[2];
545 memRefs[0].flags = 0;
546 memRefs[0].mem = m_display_image->m_presentableMemory;
547 memRefs[1].flags = 0;
548 memRefs[1].mem = buf.memories()[0];
549
550 XGL_CMD_BUFFER cmdBufs[1];
551 cmdBufs[0] = m_cmdbuf.obj();
552
553 xglQueueSubmit(m_queue.obj(), 1, cmdBufs, numMemRefs, memRefs, NULL);
554 m_queue.wait();
555
556
557 if (m_display_image->m_width > m_width)
558 m_width = m_display_image->m_width;
559
560 if (m_display_image->m_height > m_height)
561 m_height = m_display_image->m_height;
562
563
564 ++m_display_image;
565
566 }
567
568 m_display_image = m_images.begin();
569}
570
571void TestFrameworkXglPresent::InitPresentFramework(std::list<XglTestImageRecord> &imagesIn)
572{
573 m_images = imagesIn;
574}
575
Tony Barbour2b3ae0f2015-04-02 15:52:36 -0600576void TestFrameworkXglPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -0700577{
578 uint32_t value_mask, value_list[32];
579
580 m_window = xcb_generate_id(environment->m_connection);
581
582 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
583 value_list[0] = environment->m_screen->black_pixel;
584 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
585 XCB_EVENT_MASK_EXPOSURE |
586 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
587
588 xcb_create_window(environment->m_connection,
589 XCB_COPY_FROM_PARENT,
590 m_window, environment->m_screen->root,
591 0, 0, m_width, m_height, 0,
592 XCB_WINDOW_CLASS_INPUT_OUTPUT,
593 environment->m_screen->root_visual,
594 value_mask, value_list);
595
596 /* Magic code that will send notification when window is destroyed */
597 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(environment->m_connection, 1, 12,
598 "WM_PROTOCOLS");
599 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(environment->m_connection, cookie, 0);
600
601 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(environment->m_connection, 0, 16, "WM_DELETE_WINDOW");
602 m_atom_wm_delete_window = xcb_intern_atom_reply(environment->m_connection, cookie2, 0);
603
604 xcb_change_property(environment->m_connection, XCB_PROP_MODE_REPLACE,
605 m_window, (*reply).atom, 4, 32, 1,
606 &(*m_atom_wm_delete_window).atom);
607 free(reply);
608
609 xcb_map_window(environment->m_connection, m_window);
610}
611
612void TestFrameworkXglPresent::TearDown()
613{
614 xcb_destroy_window(environment->m_connection, m_window);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600615}
616
617void XglTestFramework::Finish()
618{
619 if (m_images.size() == 0) return;
620
Tony Barbour96db8822015-02-25 12:28:39 -0700621 environment = new xgl_testing::Environment();
622 ::testing::AddGlobalTestEnvironment(environment);
623 environment->X11SetUp();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600624
Tony Barbour96db8822015-02-25 12:28:39 -0700625 {
626 TestFrameworkXglPresent xglPresent;
627
628 xglPresent.InitPresentFramework(m_images);
629 xglPresent.CreatePresentableImages();
Tony Barbour2b3ae0f2015-04-02 15:52:36 -0600630 xglPresent.CreateMyWindow();
Tony Barbour96db8822015-02-25 12:28:39 -0700631 xglPresent.Run();
632 xglPresent.TearDown();
633 }
634 environment->TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600635}
636
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600637//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600638// These are the default resources for TBuiltInResources, used for both
639// - parsing this string for the case where the user didn't supply one
640// - dumping out a template for user construction of a config file
641//
642static const char* DefaultConfig =
643 "MaxLights 32\n"
644 "MaxClipPlanes 6\n"
645 "MaxTextureUnits 32\n"
646 "MaxTextureCoords 32\n"
647 "MaxVertexAttribs 64\n"
648 "MaxVertexUniformComponents 4096\n"
649 "MaxVaryingFloats 64\n"
650 "MaxVertexTextureImageUnits 32\n"
651 "MaxCombinedTextureImageUnits 80\n"
652 "MaxTextureImageUnits 32\n"
653 "MaxFragmentUniformComponents 4096\n"
654 "MaxDrawBuffers 32\n"
655 "MaxVertexUniformVectors 128\n"
656 "MaxVaryingVectors 8\n"
657 "MaxFragmentUniformVectors 16\n"
658 "MaxVertexOutputVectors 16\n"
659 "MaxFragmentInputVectors 15\n"
660 "MinProgramTexelOffset -8\n"
661 "MaxProgramTexelOffset 7\n"
662 "MaxClipDistances 8\n"
663 "MaxComputeWorkGroupCountX 65535\n"
664 "MaxComputeWorkGroupCountY 65535\n"
665 "MaxComputeWorkGroupCountZ 65535\n"
666 "MaxComputeWorkGroupSizeX 1024\n"
667 "MaxComputeWorkGroupSizeY 1024\n"
668 "MaxComputeWorkGroupSizeZ 64\n"
669 "MaxComputeUniformComponents 1024\n"
670 "MaxComputeTextureImageUnits 16\n"
671 "MaxComputeImageUniforms 8\n"
672 "MaxComputeAtomicCounters 8\n"
673 "MaxComputeAtomicCounterBuffers 1\n"
674 "MaxVaryingComponents 60\n"
675 "MaxVertexOutputComponents 64\n"
676 "MaxGeometryInputComponents 64\n"
677 "MaxGeometryOutputComponents 128\n"
678 "MaxFragmentInputComponents 128\n"
679 "MaxImageUnits 8\n"
680 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
681 "MaxCombinedShaderOutputResources 8\n"
682 "MaxImageSamples 0\n"
683 "MaxVertexImageUniforms 0\n"
684 "MaxTessControlImageUniforms 0\n"
685 "MaxTessEvaluationImageUniforms 0\n"
686 "MaxGeometryImageUniforms 0\n"
687 "MaxFragmentImageUniforms 8\n"
688 "MaxCombinedImageUniforms 8\n"
689 "MaxGeometryTextureImageUnits 16\n"
690 "MaxGeometryOutputVertices 256\n"
691 "MaxGeometryTotalOutputComponents 1024\n"
692 "MaxGeometryUniformComponents 1024\n"
693 "MaxGeometryVaryingComponents 64\n"
694 "MaxTessControlInputComponents 128\n"
695 "MaxTessControlOutputComponents 128\n"
696 "MaxTessControlTextureImageUnits 16\n"
697 "MaxTessControlUniformComponents 1024\n"
698 "MaxTessControlTotalOutputComponents 4096\n"
699 "MaxTessEvaluationInputComponents 128\n"
700 "MaxTessEvaluationOutputComponents 128\n"
701 "MaxTessEvaluationTextureImageUnits 16\n"
702 "MaxTessEvaluationUniformComponents 1024\n"
703 "MaxTessPatchComponents 120\n"
704 "MaxPatchVertices 32\n"
705 "MaxTessGenLevel 64\n"
706 "MaxViewports 16\n"
707 "MaxVertexAtomicCounters 0\n"
708 "MaxTessControlAtomicCounters 0\n"
709 "MaxTessEvaluationAtomicCounters 0\n"
710 "MaxGeometryAtomicCounters 0\n"
711 "MaxFragmentAtomicCounters 8\n"
712 "MaxCombinedAtomicCounters 8\n"
713 "MaxAtomicCounterBindings 1\n"
714 "MaxVertexAtomicCounterBuffers 0\n"
715 "MaxTessControlAtomicCounterBuffers 0\n"
716 "MaxTessEvaluationAtomicCounterBuffers 0\n"
717 "MaxGeometryAtomicCounterBuffers 0\n"
718 "MaxFragmentAtomicCounterBuffers 1\n"
719 "MaxCombinedAtomicCounterBuffers 1\n"
720 "MaxAtomicCounterBufferSize 16384\n"
721 "MaxTransformFeedbackBuffers 4\n"
722 "MaxTransformFeedbackInterleavedComponents 64\n"
723 "MaxCullDistances 8\n"
724 "MaxCombinedClipAndCullDistances 8\n"
725 "MaxSamples 4\n"
726
727 "nonInductiveForLoops 1\n"
728 "whileLoops 1\n"
729 "doWhileLoops 1\n"
730 "generalUniformIndexing 1\n"
731 "generalAttributeMatrixVectorIndexing 1\n"
732 "generalVaryingIndexing 1\n"
733 "generalSamplerIndexing 1\n"
734 "generalVariableIndexing 1\n"
735 "generalConstantMatrixVectorIndexing 1\n"
736 ;
737
738//
739// *.conf => this is a config file that can set limits/resources
740//
741bool XglTestFramework::SetConfigFile(const std::string& name)
742{
743 if (name.size() < 5)
744 return false;
745
746 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
747 ConfigFile = name;
748 return true;
749 }
750
751 return false;
752}
753
754//
755// Parse either a .conf file provided by the user or the default string above.
756//
757void XglTestFramework::ProcessConfigFile()
758{
759 char** configStrings = 0;
760 char* config = 0;
761 if (ConfigFile.size() > 0) {
762 configStrings = ReadFileData(ConfigFile.c_str());
763 if (configStrings)
764 config = *configStrings;
765 else {
766 printf("Error opening configuration file; will instead use the default configuration\n");
767 }
768 }
769
770 if (config == 0) {
771 config = new char[strlen(DefaultConfig) + 1];
772 strcpy(config, DefaultConfig);
773 }
774
775 const char* delims = " \t\n\r";
776 const char* token = strtok(config, delims);
777 while (token) {
778 const char* valueStr = strtok(0, delims);
779 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
780 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
781 return;
782 }
783 int value = atoi(valueStr);
784
785 if (strcmp(token, "MaxLights") == 0)
786 Resources.maxLights = value;
787 else if (strcmp(token, "MaxClipPlanes") == 0)
788 Resources.maxClipPlanes = value;
789 else if (strcmp(token, "MaxTextureUnits") == 0)
790 Resources.maxTextureUnits = value;
791 else if (strcmp(token, "MaxTextureCoords") == 0)
792 Resources.maxTextureCoords = value;
793 else if (strcmp(token, "MaxVertexAttribs") == 0)
794 Resources.maxVertexAttribs = value;
795 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
796 Resources.maxVertexUniformComponents = value;
797 else if (strcmp(token, "MaxVaryingFloats") == 0)
798 Resources.maxVaryingFloats = value;
799 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
800 Resources.maxVertexTextureImageUnits = value;
801 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
802 Resources.maxCombinedTextureImageUnits = value;
803 else if (strcmp(token, "MaxTextureImageUnits") == 0)
804 Resources.maxTextureImageUnits = value;
805 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
806 Resources.maxFragmentUniformComponents = value;
807 else if (strcmp(token, "MaxDrawBuffers") == 0)
808 Resources.maxDrawBuffers = value;
809 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
810 Resources.maxVertexUniformVectors = value;
811 else if (strcmp(token, "MaxVaryingVectors") == 0)
812 Resources.maxVaryingVectors = value;
813 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
814 Resources.maxFragmentUniformVectors = value;
815 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
816 Resources.maxVertexOutputVectors = value;
817 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
818 Resources.maxFragmentInputVectors = value;
819 else if (strcmp(token, "MinProgramTexelOffset") == 0)
820 Resources.minProgramTexelOffset = value;
821 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
822 Resources.maxProgramTexelOffset = value;
823 else if (strcmp(token, "MaxClipDistances") == 0)
824 Resources.maxClipDistances = value;
825 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
826 Resources.maxComputeWorkGroupCountX = value;
827 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
828 Resources.maxComputeWorkGroupCountY = value;
829 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
830 Resources.maxComputeWorkGroupCountZ = value;
831 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
832 Resources.maxComputeWorkGroupSizeX = value;
833 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
834 Resources.maxComputeWorkGroupSizeY = value;
835 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
836 Resources.maxComputeWorkGroupSizeZ = value;
837 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
838 Resources.maxComputeUniformComponents = value;
839 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
840 Resources.maxComputeTextureImageUnits = value;
841 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
842 Resources.maxComputeImageUniforms = value;
843 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
844 Resources.maxComputeAtomicCounters = value;
845 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
846 Resources.maxComputeAtomicCounterBuffers = value;
847 else if (strcmp(token, "MaxVaryingComponents") == 0)
848 Resources.maxVaryingComponents = value;
849 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
850 Resources.maxVertexOutputComponents = value;
851 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
852 Resources.maxGeometryInputComponents = value;
853 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
854 Resources.maxGeometryOutputComponents = value;
855 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
856 Resources.maxFragmentInputComponents = value;
857 else if (strcmp(token, "MaxImageUnits") == 0)
858 Resources.maxImageUnits = value;
859 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
860 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
861 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
862 Resources.maxCombinedShaderOutputResources = value;
863 else if (strcmp(token, "MaxImageSamples") == 0)
864 Resources.maxImageSamples = value;
865 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
866 Resources.maxVertexImageUniforms = value;
867 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
868 Resources.maxTessControlImageUniforms = value;
869 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
870 Resources.maxTessEvaluationImageUniforms = value;
871 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
872 Resources.maxGeometryImageUniforms = value;
873 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
874 Resources.maxFragmentImageUniforms = value;
875 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
876 Resources.maxCombinedImageUniforms = value;
877 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
878 Resources.maxGeometryTextureImageUnits = value;
879 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
880 Resources.maxGeometryOutputVertices = value;
881 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
882 Resources.maxGeometryTotalOutputComponents = value;
883 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
884 Resources.maxGeometryUniformComponents = value;
885 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
886 Resources.maxGeometryVaryingComponents = value;
887 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
888 Resources.maxTessControlInputComponents = value;
889 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
890 Resources.maxTessControlOutputComponents = value;
891 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
892 Resources.maxTessControlTextureImageUnits = value;
893 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
894 Resources.maxTessControlUniformComponents = value;
895 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
896 Resources.maxTessControlTotalOutputComponents = value;
897 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
898 Resources.maxTessEvaluationInputComponents = value;
899 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
900 Resources.maxTessEvaluationOutputComponents = value;
901 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
902 Resources.maxTessEvaluationTextureImageUnits = value;
903 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
904 Resources.maxTessEvaluationUniformComponents = value;
905 else if (strcmp(token, "MaxTessPatchComponents") == 0)
906 Resources.maxTessPatchComponents = value;
907 else if (strcmp(token, "MaxPatchVertices") == 0)
908 Resources.maxPatchVertices = value;
909 else if (strcmp(token, "MaxTessGenLevel") == 0)
910 Resources.maxTessGenLevel = value;
911 else if (strcmp(token, "MaxViewports") == 0)
912 Resources.maxViewports = value;
913 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
914 Resources.maxVertexAtomicCounters = value;
915 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
916 Resources.maxTessControlAtomicCounters = value;
917 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
918 Resources.maxTessEvaluationAtomicCounters = value;
919 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
920 Resources.maxGeometryAtomicCounters = value;
921 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
922 Resources.maxFragmentAtomicCounters = value;
923 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
924 Resources.maxCombinedAtomicCounters = value;
925 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
926 Resources.maxAtomicCounterBindings = value;
927 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
928 Resources.maxVertexAtomicCounterBuffers = value;
929 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
930 Resources.maxTessControlAtomicCounterBuffers = value;
931 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
932 Resources.maxTessEvaluationAtomicCounterBuffers = value;
933 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
934 Resources.maxGeometryAtomicCounterBuffers = value;
935 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
936 Resources.maxFragmentAtomicCounterBuffers = value;
937 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
938 Resources.maxCombinedAtomicCounterBuffers = value;
939 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
940 Resources.maxAtomicCounterBufferSize = value;
941 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
942 Resources.maxTransformFeedbackBuffers = value;
943 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
944 Resources.maxTransformFeedbackInterleavedComponents = value;
945 else if (strcmp(token, "MaxCullDistances") == 0)
946 Resources.maxCullDistances = value;
947 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
948 Resources.maxCombinedClipAndCullDistances = value;
949 else if (strcmp(token, "MaxSamples") == 0)
950 Resources.maxSamples = value;
951
952 else if (strcmp(token, "nonInductiveForLoops") == 0)
953 Resources.limits.nonInductiveForLoops = (value != 0);
954 else if (strcmp(token, "whileLoops") == 0)
955 Resources.limits.whileLoops = (value != 0);
956 else if (strcmp(token, "doWhileLoops") == 0)
957 Resources.limits.doWhileLoops = (value != 0);
958 else if (strcmp(token, "generalUniformIndexing") == 0)
959 Resources.limits.generalUniformIndexing = (value != 0);
960 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
961 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
962 else if (strcmp(token, "generalVaryingIndexing") == 0)
963 Resources.limits.generalVaryingIndexing = (value != 0);
964 else if (strcmp(token, "generalSamplerIndexing") == 0)
965 Resources.limits.generalSamplerIndexing = (value != 0);
966 else if (strcmp(token, "generalVariableIndexing") == 0)
967 Resources.limits.generalVariableIndexing = (value != 0);
968 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
969 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
970 else
971 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
972
973 token = strtok(0, delims);
974 }
975 if (configStrings)
976 FreeFileData(configStrings);
977}
978
979void XglTestFramework::SetMessageOptions(EShMessages& messages)
980{
981 if (m_compile_options & EOptionRelaxedErrors)
982 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
983 if (m_compile_options & EOptionIntermediate)
984 messages = (EShMessages)(messages | EShMsgAST);
985 if (m_compile_options & EOptionSuppressWarnings)
986 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
987}
988
989//
990// Malloc a string of sufficient size and read a string into it.
991//
992char** XglTestFramework::ReadFileData(const char* fileName)
993{
994 FILE *in;
995 #if defined(_WIN32) && defined(__GNUC__)
996 in = fopen(fileName, "r");
997 int errorCode = in ? 0 : 1;
998 #else
999 int errorCode = fopen_s(&in, fileName, "r");
1000 #endif
1001
1002 char *fdata;
1003 int count = 0;
1004 const int maxSourceStrings = 5;
1005 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1006
1007 if (errorCode) {
1008 printf("Error: unable to open input file: %s\n", fileName);
1009 return 0;
1010 }
1011
1012 while (fgetc(in) != EOF)
1013 count++;
1014
1015 fseek(in, 0, SEEK_SET);
1016
1017 if (!(fdata = (char*)malloc(count+2))) {
1018 printf("Error allocating memory\n");
1019 return 0;
1020 }
1021 if (fread(fdata,1,count, in)!=count) {
1022 printf("Error reading input file: %s\n", fileName);
1023 return 0;
1024 }
1025 fdata[count] = '\0';
1026 fclose(in);
1027 if (count == 0) {
1028 return_data[0]=(char*)malloc(count+2);
1029 return_data[0][0]='\0';
1030 m_num_shader_strings = 0;
1031 return return_data;
1032 } else
1033 m_num_shader_strings = 1;
1034
1035 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1036 int ptr_len=0,i=0;
1037 while(count>0){
1038 return_data[i]=(char*)malloc(len+2);
1039 memcpy(return_data[i],fdata+ptr_len,len);
1040 return_data[i][len]='\0';
1041 count-=(len);
1042 ptr_len+=(len);
1043 if(count<len){
1044 if(count==0){
1045 m_num_shader_strings=(i+1);
1046 break;
1047 }
1048 len = count;
1049 }
1050 ++i;
1051 }
1052 return return_data;
1053}
1054
1055void XglTestFramework::FreeFileData(char** data)
1056{
1057 for(int i=0;i<m_num_shader_strings;i++)
1058 free(data[i]);
1059}
1060
1061//
1062// Deduce the language from the filename. Files must end in one of the
1063// following extensions:
1064//
1065// .vert = vertex
1066// .tesc = tessellation control
1067// .tese = tessellation evaluation
1068// .geom = geometry
1069// .frag = fragment
1070// .comp = compute
1071//
1072EShLanguage XglTestFramework::FindLanguage(const std::string& name)
1073{
1074 size_t ext = name.rfind('.');
1075 if (ext == std::string::npos) {
1076 return EShLangVertex;
1077 }
1078
1079 std::string suffix = name.substr(ext + 1, std::string::npos);
1080 if (suffix == "vert")
1081 return EShLangVertex;
1082 else if (suffix == "tesc")
1083 return EShLangTessControl;
1084 else if (suffix == "tese")
1085 return EShLangTessEvaluation;
1086 else if (suffix == "geom")
1087 return EShLangGeometry;
1088 else if (suffix == "frag")
1089 return EShLangFragment;
1090 else if (suffix == "comp")
1091 return EShLangCompute;
1092
1093 return EShLangVertex;
1094}
1095
1096//
1097// Convert XGL shader type to compiler's
1098//
1099EShLanguage XglTestFramework::FindLanguage(const XGL_PIPELINE_SHADER_STAGE shader_type)
1100{
1101 switch (shader_type) {
1102 case XGL_SHADER_STAGE_VERTEX:
1103 return EShLangVertex;
1104
1105 case XGL_SHADER_STAGE_TESS_CONTROL:
1106 return EShLangTessControl;
1107
1108 case XGL_SHADER_STAGE_TESS_EVALUATION:
1109 return EShLangTessEvaluation;
1110
1111 case XGL_SHADER_STAGE_GEOMETRY:
1112 return EShLangGeometry;
1113
1114 case XGL_SHADER_STAGE_FRAGMENT:
1115 return EShLangFragment;
1116
1117 case XGL_SHADER_STAGE_COMPUTE:
1118 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001119
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001120 default:
1121 return EShLangVertex;
1122 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001123}
1124
1125
1126//
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001127// Compile a given string containing GLSL into SPV for use by XGL
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001128// Return value of false means an error was encountered.
1129//
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001130bool XglTestFramework::GLSLtoSPV(const XGL_PIPELINE_SHADER_STAGE shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001131 const char *pshader,
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001132 std::vector<unsigned int> &spv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001133{
1134 glslang::TProgram& program = *new glslang::TProgram;
1135 const char *shaderStrings[1];
1136
1137 // TODO: Do we want to load a special config file depending on the
1138 // shader source? Optional name maybe?
1139 // SetConfigFile(fileName);
1140
1141 ProcessConfigFile();
1142
1143 EShMessages messages = EShMsgDefault;
1144 SetMessageOptions(messages);
1145
1146 EShLanguage stage = FindLanguage(shader_type);
1147 glslang::TShader* shader = new glslang::TShader(stage);
1148
1149 shaderStrings[0] = pshader;
1150 shader->setStrings(shaderStrings, 1);
1151
1152 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1153
Cody Northrop195d6622014-11-03 12:54:37 -07001154 if (! (m_compile_options & EOptionSuppressInfolog)) {
1155 puts(shader->getInfoLog());
1156 puts(shader->getInfoDebugLog());
1157 }
1158
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001159 return false; // something didn't work
1160 }
1161
1162 program.addShader(shader);
1163
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001164
1165 //
1166 // Program-level processing...
1167 //
1168
Cody Northrop195d6622014-11-03 12:54:37 -07001169 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001170
Cody Northrop195d6622014-11-03 12:54:37 -07001171 if (! (m_compile_options & EOptionSuppressInfolog)) {
1172 puts(shader->getInfoLog());
1173 puts(shader->getInfoDebugLog());
1174 }
1175
1176 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001177 }
1178
1179 if (m_compile_options & EOptionDumpReflection) {
1180 program.buildReflection();
1181 program.dumpReflection();
1182 }
1183
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001184 glslang::GlslangToSpv(*program.getIntermediate(stage), spv);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001185
1186 return true;
1187}
1188
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001189
1190
1191XglTestImageRecord::XglTestImageRecord() : // Constructor
1192 m_width( 0 ),
1193 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001194 m_data( NULL ),
Tony Barbour96db8822015-02-25 12:28:39 -07001195 m_presentableImage( NULL ),
1196 m_presentableMemory( NULL),
Chia-I Wu837f9952014-12-15 23:29:34 +08001197 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001198{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001199}
1200
1201XglTestImageRecord::~XglTestImageRecord()
1202{
1203
1204}
1205
1206XglTestImageRecord::XglTestImageRecord(const XglTestImageRecord &copyin) // Copy constructor to handle pass by value.
1207{
1208 m_title = copyin.m_title;
1209 m_width = copyin.m_width;
1210 m_height = copyin.m_height;
1211 m_data_size = copyin.m_data_size;
1212 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
Tony Barbour96db8822015-02-25 12:28:39 -07001213 m_presentableImage = copyin.m_presentableImage;
1214 m_presentableMemory = copyin.m_presentableMemory;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001215}
1216
1217ostream &operator<<(ostream &output, const XglTestImageRecord &XglTestImageRecord)
1218{
1219 output << XglTestImageRecord.m_title << " (" << XglTestImageRecord.m_width <<
1220 "," << XglTestImageRecord.m_height << ")" << endl;
1221 return output;
1222}
1223
1224XglTestImageRecord& XglTestImageRecord::operator=(const XglTestImageRecord &rhs)
1225{
1226 m_title = rhs.m_title;
1227 m_width = rhs.m_width;
1228 m_height = rhs.m_height;
1229 m_data_size = rhs.m_data_size;
1230 m_data = rhs.m_data;
Tony Barbour96db8822015-02-25 12:28:39 -07001231 m_presentableImage = rhs.m_presentableImage;
1232 m_presentableMemory = rhs.m_presentableMemory;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001233 return *this;
1234}
1235
1236int XglTestImageRecord::operator==(const XglTestImageRecord &rhs) const
1237{
1238 if( this->m_data != rhs.m_data) return 0;
1239 return 1;
1240}
1241
1242// This function is required for built-in STL list functions like sort
1243int XglTestImageRecord::operator<(const XglTestImageRecord &rhs) const
1244{
1245 if( this->m_data_size < rhs.m_data_size ) return 1;
1246 return 0;
1247}
1248