blob: 5a9935f56356e81671b3496a0e0e39711c513590 [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
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600341void XglTestFramework::RecordImages(vector<XglImage *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600342{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600343 for (int32_t i = 0; i < images.size(); i++) {
344 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600345 }
346}
347
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600348void XglTestFramework::RecordImage(XglImage * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600349{
350 const ::testing::TestInfo* const test_info =
351 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600352 ostringstream filestream;
353 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600354
Tony Barbour247bf372014-10-30 14:29:04 -0600355 m_width = 40;
356
357 if (strcmp(test_info->name(), m_testName.c_str())) {
358 filestream << test_info->name();
359 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700360 m_frameNum = 2;
361 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600362 }
363 else {
364 filestream << test_info->name() << "-" << m_frameNum;
365 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700366 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600367 }
368
Tony Barbour247bf372014-10-30 14:29:04 -0600369 // ToDo - scrub string for bad characters
370
371 if (m_save_images || m_compare_images) {
372 WritePPM(filename.c_str(), image);
373 if (m_compare_images) {
374 Compare(filename.c_str(), image);
375 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600376 }
377
378 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600379 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600380 }
381}
382
Tony Barbour96db8822015-02-25 12:28:39 -0700383static xgl_testing::Environment *environment;
384
385TestFrameworkXglPresent::TestFrameworkXglPresent() :
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700386 m_device(environment->default_device()),
387 m_queue(*m_device.graphics_queues()[0]),
388 m_cmdbuf(m_device, xgl_testing::CmdBuffer::create_info(m_device.graphics_queue_node_index_))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600389{
Tony Barbour96db8822015-02-25 12:28:39 -0700390 m_quit = false;
391 m_pause = false;
392 m_width = 0;
393 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600394}
395
Tony Barbour96db8822015-02-25 12:28:39 -0700396void TestFrameworkXglPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600397{
Tony Barbour96db8822015-02-25 12:28:39 -0700398 XGL_RESULT err;
399
Tony Barbourbdf0a312015-04-01 17:10:07 -0600400 XGL_WSI_X11_PRESENT_INFO present = {};
401 present.destWindow = m_window;
402 present.srcImage = m_display_image->m_presentableImage;
Tony Barbour96db8822015-02-25 12:28:39 -0700403
404 xcb_change_property (environment->m_connection,
405 XCB_PROP_MODE_REPLACE,
406 m_window,
407 XCB_ATOM_WM_NAME,
408 XCB_ATOM_STRING,
409 8,
410 m_display_image->m_title.size(),
411 m_display_image->m_title.c_str());
412
413 err = xglWsiX11QueuePresent(m_queue.obj(), &present, NULL);
414 assert(!err);
415
416 m_queue.wait();
417
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600418}
419
Tony Barbour96db8822015-02-25 12:28:39 -0700420void TestFrameworkXglPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600421{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600422 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700423 switch (event_code) {
424 case XCB_EXPOSE:
425 Display(); // TODO: handle resize
426 break;
427 case XCB_CLIENT_MESSAGE:
428 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
429 (m_atom_wm_delete_window)->atom) {
430 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600431 }
432 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700433 case XCB_KEY_RELEASE:
434 {
435 const xcb_key_release_event_t *key =
436 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600437
Tony Barbour96db8822015-02-25 12:28:39 -0700438 switch (key->detail) {
439 case 0x9: // Escape
440 m_quit = true;
441 break;
442 case 0x71: // left arrow key
443 if (m_display_image == m_images.begin()) {
444 m_display_image = --m_images.end();
445 } else {
446 --m_display_image;
447 }
448 break;
449 case 0x72: // right arrow key
450 ++m_display_image;
451 if (m_display_image == m_images.end()) {
452 m_display_image = m_images.begin();
453 }
454 break;
455 case 0x41:
456 m_pause = !m_pause;
457 break;
458 }
459 Display();
460 }
461 break;
462 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600463 break;
464 }
Tony Barbour96db8822015-02-25 12:28:39 -0700465}
466
467void TestFrameworkXglPresent::Run()
468{
469 xcb_flush(environment->m_connection);
470
471 while (! m_quit) {
472 xcb_generic_event_t *event;
473
474 if (m_pause) {
475 event = xcb_wait_for_event(environment->m_connection);
476 } else {
477 event = xcb_poll_for_event(environment->m_connection);
478 }
479 if (event) {
480 HandleEvent(event);
481 free(event);
482 }
483 }
484}
485
486void TestFrameworkXglPresent::CreatePresentableImages()
487{
488 XGL_RESULT err;
489
490 m_display_image = m_images.begin();
491
492 for (int x=0; x < m_images.size(); x++)
493 {
Tony Barbourbdf0a312015-04-01 17:10:07 -0600494 XGL_WSI_X11_PRESENTABLE_IMAGE_CREATE_INFO presentable_image_info = {};
495 presentable_image_info.format = XGL_FMT_B8G8R8A8_UNORM;
496 presentable_image_info.usage = XGL_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
497 presentable_image_info.extent.width = m_display_image->m_width;
498 presentable_image_info.extent.height = m_display_image->m_height;
499 presentable_image_info.flags = 0;
Tony Barbour96db8822015-02-25 12:28:39 -0700500
501 void *dest_ptr;
502
503 err = xglWsiX11CreatePresentableImage(m_device.obj(), &presentable_image_info,
504 &m_display_image->m_presentableImage, &m_display_image->m_presentableMemory);
505 assert(!err);
506
507 xgl_testing::Buffer buf;
508 buf.init(m_device, (XGL_GPU_SIZE) m_display_image->m_data_size);
509 dest_ptr = buf.map();
510 memcpy(dest_ptr,m_display_image->m_data, m_display_image->m_data_size);
511 buf.unmap();
512
513 m_cmdbuf.begin();
514
515 XGL_BUFFER_IMAGE_COPY region = {};
516 region.imageExtent.height = m_display_image->m_height;
517 region.imageExtent.width = m_display_image->m_width;
518 region.imageExtent.depth = 1;
519
Courtney Goeltzenleuchterb3efe9b2015-03-25 11:25:10 -0600520 xglCmdCopyBufferToImage(m_cmdbuf.obj(),
521 buf.obj(),
522 m_display_image->m_presentableImage, XGL_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
523 1, &region);
Tony Barbour96db8822015-02-25 12:28:39 -0700524 m_cmdbuf.end();
525
526 uint32_t numMemRefs=2;
527 XGL_MEMORY_REF memRefs[2];
528 memRefs[0].flags = 0;
529 memRefs[0].mem = m_display_image->m_presentableMemory;
530 memRefs[1].flags = 0;
531 memRefs[1].mem = buf.memories()[0];
532
533 XGL_CMD_BUFFER cmdBufs[1];
534 cmdBufs[0] = m_cmdbuf.obj();
535
536 xglQueueSubmit(m_queue.obj(), 1, cmdBufs, numMemRefs, memRefs, NULL);
537 m_queue.wait();
538
539
540 if (m_display_image->m_width > m_width)
541 m_width = m_display_image->m_width;
542
543 if (m_display_image->m_height > m_height)
544 m_height = m_display_image->m_height;
545
546
547 ++m_display_image;
548
549 }
550
551 m_display_image = m_images.begin();
552}
553
554void TestFrameworkXglPresent::InitPresentFramework(std::list<XglTestImageRecord> &imagesIn)
555{
556 m_images = imagesIn;
557}
558
Tony Barbour2b3ae0f2015-04-02 15:52:36 -0600559void TestFrameworkXglPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -0700560{
561 uint32_t value_mask, value_list[32];
562
563 m_window = xcb_generate_id(environment->m_connection);
564
565 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
566 value_list[0] = environment->m_screen->black_pixel;
567 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
568 XCB_EVENT_MASK_EXPOSURE |
569 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
570
571 xcb_create_window(environment->m_connection,
572 XCB_COPY_FROM_PARENT,
573 m_window, environment->m_screen->root,
574 0, 0, m_width, m_height, 0,
575 XCB_WINDOW_CLASS_INPUT_OUTPUT,
576 environment->m_screen->root_visual,
577 value_mask, value_list);
578
579 /* Magic code that will send notification when window is destroyed */
580 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(environment->m_connection, 1, 12,
581 "WM_PROTOCOLS");
582 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(environment->m_connection, cookie, 0);
583
584 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(environment->m_connection, 0, 16, "WM_DELETE_WINDOW");
585 m_atom_wm_delete_window = xcb_intern_atom_reply(environment->m_connection, cookie2, 0);
586
587 xcb_change_property(environment->m_connection, XCB_PROP_MODE_REPLACE,
588 m_window, (*reply).atom, 4, 32, 1,
589 &(*m_atom_wm_delete_window).atom);
590 free(reply);
591
592 xcb_map_window(environment->m_connection, m_window);
593}
594
595void TestFrameworkXglPresent::TearDown()
596{
597 xcb_destroy_window(environment->m_connection, m_window);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600598}
599
600void XglTestFramework::Finish()
601{
602 if (m_images.size() == 0) return;
603
Tony Barbour96db8822015-02-25 12:28:39 -0700604 environment = new xgl_testing::Environment();
605 ::testing::AddGlobalTestEnvironment(environment);
606 environment->X11SetUp();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600607
Tony Barbour96db8822015-02-25 12:28:39 -0700608 {
609 TestFrameworkXglPresent xglPresent;
610
611 xglPresent.InitPresentFramework(m_images);
612 xglPresent.CreatePresentableImages();
Tony Barbour2b3ae0f2015-04-02 15:52:36 -0600613 xglPresent.CreateMyWindow();
Tony Barbour96db8822015-02-25 12:28:39 -0700614 xglPresent.Run();
615 xglPresent.TearDown();
616 }
617 environment->TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600618}
619
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600620//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600621// These are the default resources for TBuiltInResources, used for both
622// - parsing this string for the case where the user didn't supply one
623// - dumping out a template for user construction of a config file
624//
625static const char* DefaultConfig =
626 "MaxLights 32\n"
627 "MaxClipPlanes 6\n"
628 "MaxTextureUnits 32\n"
629 "MaxTextureCoords 32\n"
630 "MaxVertexAttribs 64\n"
631 "MaxVertexUniformComponents 4096\n"
632 "MaxVaryingFloats 64\n"
633 "MaxVertexTextureImageUnits 32\n"
634 "MaxCombinedTextureImageUnits 80\n"
635 "MaxTextureImageUnits 32\n"
636 "MaxFragmentUniformComponents 4096\n"
637 "MaxDrawBuffers 32\n"
638 "MaxVertexUniformVectors 128\n"
639 "MaxVaryingVectors 8\n"
640 "MaxFragmentUniformVectors 16\n"
641 "MaxVertexOutputVectors 16\n"
642 "MaxFragmentInputVectors 15\n"
643 "MinProgramTexelOffset -8\n"
644 "MaxProgramTexelOffset 7\n"
645 "MaxClipDistances 8\n"
646 "MaxComputeWorkGroupCountX 65535\n"
647 "MaxComputeWorkGroupCountY 65535\n"
648 "MaxComputeWorkGroupCountZ 65535\n"
649 "MaxComputeWorkGroupSizeX 1024\n"
650 "MaxComputeWorkGroupSizeY 1024\n"
651 "MaxComputeWorkGroupSizeZ 64\n"
652 "MaxComputeUniformComponents 1024\n"
653 "MaxComputeTextureImageUnits 16\n"
654 "MaxComputeImageUniforms 8\n"
655 "MaxComputeAtomicCounters 8\n"
656 "MaxComputeAtomicCounterBuffers 1\n"
657 "MaxVaryingComponents 60\n"
658 "MaxVertexOutputComponents 64\n"
659 "MaxGeometryInputComponents 64\n"
660 "MaxGeometryOutputComponents 128\n"
661 "MaxFragmentInputComponents 128\n"
662 "MaxImageUnits 8\n"
663 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
664 "MaxCombinedShaderOutputResources 8\n"
665 "MaxImageSamples 0\n"
666 "MaxVertexImageUniforms 0\n"
667 "MaxTessControlImageUniforms 0\n"
668 "MaxTessEvaluationImageUniforms 0\n"
669 "MaxGeometryImageUniforms 0\n"
670 "MaxFragmentImageUniforms 8\n"
671 "MaxCombinedImageUniforms 8\n"
672 "MaxGeometryTextureImageUnits 16\n"
673 "MaxGeometryOutputVertices 256\n"
674 "MaxGeometryTotalOutputComponents 1024\n"
675 "MaxGeometryUniformComponents 1024\n"
676 "MaxGeometryVaryingComponents 64\n"
677 "MaxTessControlInputComponents 128\n"
678 "MaxTessControlOutputComponents 128\n"
679 "MaxTessControlTextureImageUnits 16\n"
680 "MaxTessControlUniformComponents 1024\n"
681 "MaxTessControlTotalOutputComponents 4096\n"
682 "MaxTessEvaluationInputComponents 128\n"
683 "MaxTessEvaluationOutputComponents 128\n"
684 "MaxTessEvaluationTextureImageUnits 16\n"
685 "MaxTessEvaluationUniformComponents 1024\n"
686 "MaxTessPatchComponents 120\n"
687 "MaxPatchVertices 32\n"
688 "MaxTessGenLevel 64\n"
689 "MaxViewports 16\n"
690 "MaxVertexAtomicCounters 0\n"
691 "MaxTessControlAtomicCounters 0\n"
692 "MaxTessEvaluationAtomicCounters 0\n"
693 "MaxGeometryAtomicCounters 0\n"
694 "MaxFragmentAtomicCounters 8\n"
695 "MaxCombinedAtomicCounters 8\n"
696 "MaxAtomicCounterBindings 1\n"
697 "MaxVertexAtomicCounterBuffers 0\n"
698 "MaxTessControlAtomicCounterBuffers 0\n"
699 "MaxTessEvaluationAtomicCounterBuffers 0\n"
700 "MaxGeometryAtomicCounterBuffers 0\n"
701 "MaxFragmentAtomicCounterBuffers 1\n"
702 "MaxCombinedAtomicCounterBuffers 1\n"
703 "MaxAtomicCounterBufferSize 16384\n"
704 "MaxTransformFeedbackBuffers 4\n"
705 "MaxTransformFeedbackInterleavedComponents 64\n"
706 "MaxCullDistances 8\n"
707 "MaxCombinedClipAndCullDistances 8\n"
708 "MaxSamples 4\n"
709
710 "nonInductiveForLoops 1\n"
711 "whileLoops 1\n"
712 "doWhileLoops 1\n"
713 "generalUniformIndexing 1\n"
714 "generalAttributeMatrixVectorIndexing 1\n"
715 "generalVaryingIndexing 1\n"
716 "generalSamplerIndexing 1\n"
717 "generalVariableIndexing 1\n"
718 "generalConstantMatrixVectorIndexing 1\n"
719 ;
720
721//
722// *.conf => this is a config file that can set limits/resources
723//
724bool XglTestFramework::SetConfigFile(const std::string& name)
725{
726 if (name.size() < 5)
727 return false;
728
729 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
730 ConfigFile = name;
731 return true;
732 }
733
734 return false;
735}
736
737//
738// Parse either a .conf file provided by the user or the default string above.
739//
740void XglTestFramework::ProcessConfigFile()
741{
742 char** configStrings = 0;
743 char* config = 0;
744 if (ConfigFile.size() > 0) {
745 configStrings = ReadFileData(ConfigFile.c_str());
746 if (configStrings)
747 config = *configStrings;
748 else {
749 printf("Error opening configuration file; will instead use the default configuration\n");
750 }
751 }
752
753 if (config == 0) {
754 config = new char[strlen(DefaultConfig) + 1];
755 strcpy(config, DefaultConfig);
756 }
757
758 const char* delims = " \t\n\r";
759 const char* token = strtok(config, delims);
760 while (token) {
761 const char* valueStr = strtok(0, delims);
762 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
763 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
764 return;
765 }
766 int value = atoi(valueStr);
767
768 if (strcmp(token, "MaxLights") == 0)
769 Resources.maxLights = value;
770 else if (strcmp(token, "MaxClipPlanes") == 0)
771 Resources.maxClipPlanes = value;
772 else if (strcmp(token, "MaxTextureUnits") == 0)
773 Resources.maxTextureUnits = value;
774 else if (strcmp(token, "MaxTextureCoords") == 0)
775 Resources.maxTextureCoords = value;
776 else if (strcmp(token, "MaxVertexAttribs") == 0)
777 Resources.maxVertexAttribs = value;
778 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
779 Resources.maxVertexUniformComponents = value;
780 else if (strcmp(token, "MaxVaryingFloats") == 0)
781 Resources.maxVaryingFloats = value;
782 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
783 Resources.maxVertexTextureImageUnits = value;
784 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
785 Resources.maxCombinedTextureImageUnits = value;
786 else if (strcmp(token, "MaxTextureImageUnits") == 0)
787 Resources.maxTextureImageUnits = value;
788 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
789 Resources.maxFragmentUniformComponents = value;
790 else if (strcmp(token, "MaxDrawBuffers") == 0)
791 Resources.maxDrawBuffers = value;
792 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
793 Resources.maxVertexUniformVectors = value;
794 else if (strcmp(token, "MaxVaryingVectors") == 0)
795 Resources.maxVaryingVectors = value;
796 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
797 Resources.maxFragmentUniformVectors = value;
798 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
799 Resources.maxVertexOutputVectors = value;
800 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
801 Resources.maxFragmentInputVectors = value;
802 else if (strcmp(token, "MinProgramTexelOffset") == 0)
803 Resources.minProgramTexelOffset = value;
804 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
805 Resources.maxProgramTexelOffset = value;
806 else if (strcmp(token, "MaxClipDistances") == 0)
807 Resources.maxClipDistances = value;
808 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
809 Resources.maxComputeWorkGroupCountX = value;
810 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
811 Resources.maxComputeWorkGroupCountY = value;
812 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
813 Resources.maxComputeWorkGroupCountZ = value;
814 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
815 Resources.maxComputeWorkGroupSizeX = value;
816 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
817 Resources.maxComputeWorkGroupSizeY = value;
818 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
819 Resources.maxComputeWorkGroupSizeZ = value;
820 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
821 Resources.maxComputeUniformComponents = value;
822 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
823 Resources.maxComputeTextureImageUnits = value;
824 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
825 Resources.maxComputeImageUniforms = value;
826 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
827 Resources.maxComputeAtomicCounters = value;
828 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
829 Resources.maxComputeAtomicCounterBuffers = value;
830 else if (strcmp(token, "MaxVaryingComponents") == 0)
831 Resources.maxVaryingComponents = value;
832 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
833 Resources.maxVertexOutputComponents = value;
834 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
835 Resources.maxGeometryInputComponents = value;
836 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
837 Resources.maxGeometryOutputComponents = value;
838 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
839 Resources.maxFragmentInputComponents = value;
840 else if (strcmp(token, "MaxImageUnits") == 0)
841 Resources.maxImageUnits = value;
842 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
843 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
844 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
845 Resources.maxCombinedShaderOutputResources = value;
846 else if (strcmp(token, "MaxImageSamples") == 0)
847 Resources.maxImageSamples = value;
848 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
849 Resources.maxVertexImageUniforms = value;
850 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
851 Resources.maxTessControlImageUniforms = value;
852 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
853 Resources.maxTessEvaluationImageUniforms = value;
854 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
855 Resources.maxGeometryImageUniforms = value;
856 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
857 Resources.maxFragmentImageUniforms = value;
858 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
859 Resources.maxCombinedImageUniforms = value;
860 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
861 Resources.maxGeometryTextureImageUnits = value;
862 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
863 Resources.maxGeometryOutputVertices = value;
864 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
865 Resources.maxGeometryTotalOutputComponents = value;
866 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
867 Resources.maxGeometryUniformComponents = value;
868 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
869 Resources.maxGeometryVaryingComponents = value;
870 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
871 Resources.maxTessControlInputComponents = value;
872 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
873 Resources.maxTessControlOutputComponents = value;
874 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
875 Resources.maxTessControlTextureImageUnits = value;
876 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
877 Resources.maxTessControlUniformComponents = value;
878 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
879 Resources.maxTessControlTotalOutputComponents = value;
880 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
881 Resources.maxTessEvaluationInputComponents = value;
882 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
883 Resources.maxTessEvaluationOutputComponents = value;
884 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
885 Resources.maxTessEvaluationTextureImageUnits = value;
886 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
887 Resources.maxTessEvaluationUniformComponents = value;
888 else if (strcmp(token, "MaxTessPatchComponents") == 0)
889 Resources.maxTessPatchComponents = value;
890 else if (strcmp(token, "MaxPatchVertices") == 0)
891 Resources.maxPatchVertices = value;
892 else if (strcmp(token, "MaxTessGenLevel") == 0)
893 Resources.maxTessGenLevel = value;
894 else if (strcmp(token, "MaxViewports") == 0)
895 Resources.maxViewports = value;
896 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
897 Resources.maxVertexAtomicCounters = value;
898 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
899 Resources.maxTessControlAtomicCounters = value;
900 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
901 Resources.maxTessEvaluationAtomicCounters = value;
902 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
903 Resources.maxGeometryAtomicCounters = value;
904 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
905 Resources.maxFragmentAtomicCounters = value;
906 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
907 Resources.maxCombinedAtomicCounters = value;
908 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
909 Resources.maxAtomicCounterBindings = value;
910 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
911 Resources.maxVertexAtomicCounterBuffers = value;
912 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
913 Resources.maxTessControlAtomicCounterBuffers = value;
914 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
915 Resources.maxTessEvaluationAtomicCounterBuffers = value;
916 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
917 Resources.maxGeometryAtomicCounterBuffers = value;
918 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
919 Resources.maxFragmentAtomicCounterBuffers = value;
920 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
921 Resources.maxCombinedAtomicCounterBuffers = value;
922 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
923 Resources.maxAtomicCounterBufferSize = value;
924 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
925 Resources.maxTransformFeedbackBuffers = value;
926 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
927 Resources.maxTransformFeedbackInterleavedComponents = value;
928 else if (strcmp(token, "MaxCullDistances") == 0)
929 Resources.maxCullDistances = value;
930 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
931 Resources.maxCombinedClipAndCullDistances = value;
932 else if (strcmp(token, "MaxSamples") == 0)
933 Resources.maxSamples = value;
934
935 else if (strcmp(token, "nonInductiveForLoops") == 0)
936 Resources.limits.nonInductiveForLoops = (value != 0);
937 else if (strcmp(token, "whileLoops") == 0)
938 Resources.limits.whileLoops = (value != 0);
939 else if (strcmp(token, "doWhileLoops") == 0)
940 Resources.limits.doWhileLoops = (value != 0);
941 else if (strcmp(token, "generalUniformIndexing") == 0)
942 Resources.limits.generalUniformIndexing = (value != 0);
943 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
944 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
945 else if (strcmp(token, "generalVaryingIndexing") == 0)
946 Resources.limits.generalVaryingIndexing = (value != 0);
947 else if (strcmp(token, "generalSamplerIndexing") == 0)
948 Resources.limits.generalSamplerIndexing = (value != 0);
949 else if (strcmp(token, "generalVariableIndexing") == 0)
950 Resources.limits.generalVariableIndexing = (value != 0);
951 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
952 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
953 else
954 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
955
956 token = strtok(0, delims);
957 }
958 if (configStrings)
959 FreeFileData(configStrings);
960}
961
962void XglTestFramework::SetMessageOptions(EShMessages& messages)
963{
964 if (m_compile_options & EOptionRelaxedErrors)
965 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
966 if (m_compile_options & EOptionIntermediate)
967 messages = (EShMessages)(messages | EShMsgAST);
968 if (m_compile_options & EOptionSuppressWarnings)
969 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
970}
971
972//
973// Malloc a string of sufficient size and read a string into it.
974//
975char** XglTestFramework::ReadFileData(const char* fileName)
976{
977 FILE *in;
978 #if defined(_WIN32) && defined(__GNUC__)
979 in = fopen(fileName, "r");
980 int errorCode = in ? 0 : 1;
981 #else
982 int errorCode = fopen_s(&in, fileName, "r");
983 #endif
984
985 char *fdata;
986 int count = 0;
987 const int maxSourceStrings = 5;
988 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
989
990 if (errorCode) {
991 printf("Error: unable to open input file: %s\n", fileName);
992 return 0;
993 }
994
995 while (fgetc(in) != EOF)
996 count++;
997
998 fseek(in, 0, SEEK_SET);
999
1000 if (!(fdata = (char*)malloc(count+2))) {
1001 printf("Error allocating memory\n");
1002 return 0;
1003 }
1004 if (fread(fdata,1,count, in)!=count) {
1005 printf("Error reading input file: %s\n", fileName);
1006 return 0;
1007 }
1008 fdata[count] = '\0';
1009 fclose(in);
1010 if (count == 0) {
1011 return_data[0]=(char*)malloc(count+2);
1012 return_data[0][0]='\0';
1013 m_num_shader_strings = 0;
1014 return return_data;
1015 } else
1016 m_num_shader_strings = 1;
1017
1018 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1019 int ptr_len=0,i=0;
1020 while(count>0){
1021 return_data[i]=(char*)malloc(len+2);
1022 memcpy(return_data[i],fdata+ptr_len,len);
1023 return_data[i][len]='\0';
1024 count-=(len);
1025 ptr_len+=(len);
1026 if(count<len){
1027 if(count==0){
1028 m_num_shader_strings=(i+1);
1029 break;
1030 }
1031 len = count;
1032 }
1033 ++i;
1034 }
1035 return return_data;
1036}
1037
1038void XglTestFramework::FreeFileData(char** data)
1039{
1040 for(int i=0;i<m_num_shader_strings;i++)
1041 free(data[i]);
1042}
1043
1044//
1045// Deduce the language from the filename. Files must end in one of the
1046// following extensions:
1047//
1048// .vert = vertex
1049// .tesc = tessellation control
1050// .tese = tessellation evaluation
1051// .geom = geometry
1052// .frag = fragment
1053// .comp = compute
1054//
1055EShLanguage XglTestFramework::FindLanguage(const std::string& name)
1056{
1057 size_t ext = name.rfind('.');
1058 if (ext == std::string::npos) {
1059 return EShLangVertex;
1060 }
1061
1062 std::string suffix = name.substr(ext + 1, std::string::npos);
1063 if (suffix == "vert")
1064 return EShLangVertex;
1065 else if (suffix == "tesc")
1066 return EShLangTessControl;
1067 else if (suffix == "tese")
1068 return EShLangTessEvaluation;
1069 else if (suffix == "geom")
1070 return EShLangGeometry;
1071 else if (suffix == "frag")
1072 return EShLangFragment;
1073 else if (suffix == "comp")
1074 return EShLangCompute;
1075
1076 return EShLangVertex;
1077}
1078
1079//
1080// Convert XGL shader type to compiler's
1081//
1082EShLanguage XglTestFramework::FindLanguage(const XGL_PIPELINE_SHADER_STAGE shader_type)
1083{
1084 switch (shader_type) {
1085 case XGL_SHADER_STAGE_VERTEX:
1086 return EShLangVertex;
1087
1088 case XGL_SHADER_STAGE_TESS_CONTROL:
1089 return EShLangTessControl;
1090
1091 case XGL_SHADER_STAGE_TESS_EVALUATION:
1092 return EShLangTessEvaluation;
1093
1094 case XGL_SHADER_STAGE_GEOMETRY:
1095 return EShLangGeometry;
1096
1097 case XGL_SHADER_STAGE_FRAGMENT:
1098 return EShLangFragment;
1099
1100 case XGL_SHADER_STAGE_COMPUTE:
1101 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001102
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001103 default:
1104 return EShLangVertex;
1105 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001106}
1107
1108
1109//
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001110// Compile a given string containing GLSL into SPV for use by XGL
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001111// Return value of false means an error was encountered.
1112//
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001113bool XglTestFramework::GLSLtoSPV(const XGL_PIPELINE_SHADER_STAGE shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001114 const char *pshader,
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001115 std::vector<unsigned int> &spv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001116{
1117 glslang::TProgram& program = *new glslang::TProgram;
1118 const char *shaderStrings[1];
1119
1120 // TODO: Do we want to load a special config file depending on the
1121 // shader source? Optional name maybe?
1122 // SetConfigFile(fileName);
1123
1124 ProcessConfigFile();
1125
1126 EShMessages messages = EShMsgDefault;
1127 SetMessageOptions(messages);
1128
1129 EShLanguage stage = FindLanguage(shader_type);
1130 glslang::TShader* shader = new glslang::TShader(stage);
1131
1132 shaderStrings[0] = pshader;
1133 shader->setStrings(shaderStrings, 1);
1134
1135 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1136
Cody Northrop195d6622014-11-03 12:54:37 -07001137 if (! (m_compile_options & EOptionSuppressInfolog)) {
1138 puts(shader->getInfoLog());
1139 puts(shader->getInfoDebugLog());
1140 }
1141
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001142 return false; // something didn't work
1143 }
1144
1145 program.addShader(shader);
1146
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001147
1148 //
1149 // Program-level processing...
1150 //
1151
Cody Northrop195d6622014-11-03 12:54:37 -07001152 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001153
Cody Northrop195d6622014-11-03 12:54:37 -07001154 if (! (m_compile_options & EOptionSuppressInfolog)) {
1155 puts(shader->getInfoLog());
1156 puts(shader->getInfoDebugLog());
1157 }
1158
1159 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001160 }
1161
1162 if (m_compile_options & EOptionDumpReflection) {
1163 program.buildReflection();
1164 program.dumpReflection();
1165 }
1166
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001167 glslang::GlslangToSpv(*program.getIntermediate(stage), spv);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001168
1169 return true;
1170}
1171
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001172
1173
1174XglTestImageRecord::XglTestImageRecord() : // Constructor
1175 m_width( 0 ),
1176 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001177 m_data( NULL ),
Tony Barbour96db8822015-02-25 12:28:39 -07001178 m_presentableImage( NULL ),
1179 m_presentableMemory( NULL),
Chia-I Wu837f9952014-12-15 23:29:34 +08001180 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001181{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001182}
1183
1184XglTestImageRecord::~XglTestImageRecord()
1185{
1186
1187}
1188
1189XglTestImageRecord::XglTestImageRecord(const XglTestImageRecord &copyin) // Copy constructor to handle pass by value.
1190{
1191 m_title = copyin.m_title;
1192 m_width = copyin.m_width;
1193 m_height = copyin.m_height;
1194 m_data_size = copyin.m_data_size;
1195 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
Tony Barbour96db8822015-02-25 12:28:39 -07001196 m_presentableImage = copyin.m_presentableImage;
1197 m_presentableMemory = copyin.m_presentableMemory;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001198}
1199
1200ostream &operator<<(ostream &output, const XglTestImageRecord &XglTestImageRecord)
1201{
1202 output << XglTestImageRecord.m_title << " (" << XglTestImageRecord.m_width <<
1203 "," << XglTestImageRecord.m_height << ")" << endl;
1204 return output;
1205}
1206
1207XglTestImageRecord& XglTestImageRecord::operator=(const XglTestImageRecord &rhs)
1208{
1209 m_title = rhs.m_title;
1210 m_width = rhs.m_width;
1211 m_height = rhs.m_height;
1212 m_data_size = rhs.m_data_size;
1213 m_data = rhs.m_data;
Tony Barbour96db8822015-02-25 12:28:39 -07001214 m_presentableImage = rhs.m_presentableImage;
1215 m_presentableMemory = rhs.m_presentableMemory;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001216 return *this;
1217}
1218
1219int XglTestImageRecord::operator==(const XglTestImageRecord &rhs) const
1220{
1221 if( this->m_data != rhs.m_data) return 0;
1222 return 1;
1223}
1224
1225// This function is required for built-in STL list functions like sort
1226int XglTestImageRecord::operator<(const XglTestImageRecord &rhs) const
1227{
1228 if( this->m_data_size < rhs.m_data_size ) return 1;
1229 return 0;
1230}
1231