blob: 9f13c8a5b40b43ceca9d45615e32f5bbe5292a95 [file] [log] [blame]
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001// VK tests
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06002//
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
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060023#include "vktestframework.h"
24#include "vkrenderframework.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
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060086 vk_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;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600183 VK_RESULT err;
Tony Barbour84d448c2015-04-02 14:02:33 -0600184 int x, y;
185 XglImage displayImage(image->device());
186
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600187 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, VK_LINEAR_TILING);
Tony Barbour84d448c2015-04-02 14:02:33 -0600188 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600189
190 filename.append(basename);
191 filename.append(".ppm");
192
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600193 const VK_IMAGE_SUBRESOURCE sr = {
194 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600195 };
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600196 VK_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
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600199 err = vkGetImageSubresourceInfo( image->image(), &sr,
200 VK_INFO_TYPE_SUBRESOURCE_LAYOUT,
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600201 &data_size, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600202 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600203 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
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600221 if (displayImage.format() == VK_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 }
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600229 else if (displayImage.format() == VK_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{
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600303 VK_RESULT err;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600304
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600305 const VK_IMAGE_SUBRESOURCE sr = {
306 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600307 };
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600308 VK_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 Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600314 err = vkGetImageSubresourceInfo( image->image(), &sr, VK_INFO_TYPE_SUBRESOURCE_LAYOUT,
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600315 &data_size, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600316 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600317 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 Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600322 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600323
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();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600337 ASSERT_VK_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
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600383static vk_testing::Environment *environment;
Tony Barbour96db8822015-02-25 12:28:39 -0700384
385TestFrameworkXglPresent::TestFrameworkXglPresent() :
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700386 m_device(environment->default_device()),
387 m_queue(*m_device.graphics_queues()[0]),
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600388 m_cmdbuf(m_device, vk_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{
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600398 VK_RESULT err;
Tony Barbour96db8822015-02-25 12:28:39 -0700399
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600400 VK_WSI_X11_PRESENT_INFO present = {};
Tony Barbourbdf0a312015-04-01 17:10:07 -0600401 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
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600413 err = vkWsiX11QueuePresent(m_queue.obj(), &present, NULL);
Tony Barbour96db8822015-02-25 12:28:39 -0700414 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{
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600488 VK_RESULT err;
Tony Barbour96db8822015-02-25 12:28:39 -0700489
490 m_display_image = m_images.begin();
491
492 for (int x=0; x < m_images.size(); x++)
493 {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600494 VK_WSI_X11_PRESENTABLE_IMAGE_CREATE_INFO presentable_image_info = {};
495 presentable_image_info.format = VK_FMT_B8G8R8A8_UNORM;
496 presentable_image_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
Tony Barbourbdf0a312015-04-01 17:10:07 -0600497 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
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600503 err = vkWsiX11CreatePresentableImage(m_device.obj(), &presentable_image_info,
Tony Barbour96db8822015-02-25 12:28:39 -0700504 &m_display_image->m_presentableImage, &m_display_image->m_presentableMemory);
505 assert(!err);
506
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600507 vk_testing::Buffer buf;
508 buf.init(m_device, (VK_GPU_SIZE) m_display_image->m_data_size);
Tony Barbour96db8822015-02-25 12:28:39 -0700509 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
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600515 VK_BUFFER_IMAGE_COPY region = {};
Tony Barbour96db8822015-02-25 12:28:39 -0700516 region.imageExtent.height = m_display_image->m_height;
517 region.imageExtent.width = m_display_image->m_width;
518 region.imageExtent.depth = 1;
519
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600520 vkCmdCopyBufferToImage(m_cmdbuf.obj(),
Courtney Goeltzenleuchterb3efe9b2015-03-25 11:25:10 -0600521 buf.obj(),
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600522 m_display_image->m_presentableImage, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
Courtney Goeltzenleuchterb3efe9b2015-03-25 11:25:10 -0600523 1, &region);
Tony Barbour96db8822015-02-25 12:28:39 -0700524 m_cmdbuf.end();
525
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600526 vkQueueAddMemReference(m_queue.obj(), m_display_image->m_presentableMemory);
527 vkQueueAddMemReference(m_queue.obj(), buf.memories()[0]);
Tony Barbour96db8822015-02-25 12:28:39 -0700528
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600529 VK_CMD_BUFFER cmdBufs[1];
Tony Barbour96db8822015-02-25 12:28:39 -0700530 cmdBufs[0] = m_cmdbuf.obj();
531
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600532 vkQueueSubmit(m_queue.obj(), 1, cmdBufs, NULL);
Tony Barbour96db8822015-02-25 12:28:39 -0700533 m_queue.wait();
534
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600535 vkQueueRemoveMemReference(m_queue.obj(), m_display_image->m_presentableMemory);
536 vkQueueRemoveMemReference(m_queue.obj(), buf.memories()[0]);
Tony Barbour96db8822015-02-25 12:28:39 -0700537
538 if (m_display_image->m_width > m_width)
539 m_width = m_display_image->m_width;
540
541 if (m_display_image->m_height > m_height)
542 m_height = m_display_image->m_height;
543
544
545 ++m_display_image;
546
547 }
548
549 m_display_image = m_images.begin();
550}
551
552void TestFrameworkXglPresent::InitPresentFramework(std::list<XglTestImageRecord> &imagesIn)
553{
554 m_images = imagesIn;
555}
556
Tony Barbour2b3ae0f2015-04-02 15:52:36 -0600557void TestFrameworkXglPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -0700558{
559 uint32_t value_mask, value_list[32];
560
561 m_window = xcb_generate_id(environment->m_connection);
562
563 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
564 value_list[0] = environment->m_screen->black_pixel;
565 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
566 XCB_EVENT_MASK_EXPOSURE |
567 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
568
569 xcb_create_window(environment->m_connection,
570 XCB_COPY_FROM_PARENT,
571 m_window, environment->m_screen->root,
572 0, 0, m_width, m_height, 0,
573 XCB_WINDOW_CLASS_INPUT_OUTPUT,
574 environment->m_screen->root_visual,
575 value_mask, value_list);
576
577 /* Magic code that will send notification when window is destroyed */
578 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(environment->m_connection, 1, 12,
579 "WM_PROTOCOLS");
580 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(environment->m_connection, cookie, 0);
581
582 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(environment->m_connection, 0, 16, "WM_DELETE_WINDOW");
583 m_atom_wm_delete_window = xcb_intern_atom_reply(environment->m_connection, cookie2, 0);
584
585 xcb_change_property(environment->m_connection, XCB_PROP_MODE_REPLACE,
586 m_window, (*reply).atom, 4, 32, 1,
587 &(*m_atom_wm_delete_window).atom);
588 free(reply);
589
590 xcb_map_window(environment->m_connection, m_window);
591}
592
593void TestFrameworkXglPresent::TearDown()
594{
Courtney Goeltzenleuchter97b75232015-04-07 17:13:38 -0600595 std::list<XglTestImageRecord>::const_iterator iterator;
596 for (iterator = m_images.begin(); iterator != m_images.end(); ++iterator) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600597 vkDestroyObject(iterator->m_presentableImage);
Courtney Goeltzenleuchter97b75232015-04-07 17:13:38 -0600598 }
Tony Barbour96db8822015-02-25 12:28:39 -0700599 xcb_destroy_window(environment->m_connection, m_window);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600600}
601
602void XglTestFramework::Finish()
603{
604 if (m_images.size() == 0) return;
605
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600606 environment = new vk_testing::Environment();
Tony Barbour96db8822015-02-25 12:28:39 -0700607 ::testing::AddGlobalTestEnvironment(environment);
608 environment->X11SetUp();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600609
Tony Barbour96db8822015-02-25 12:28:39 -0700610 {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600611 TestFrameworkXglPresent vkPresent;
Tony Barbour96db8822015-02-25 12:28:39 -0700612
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600613 vkPresent.InitPresentFramework(m_images);
614 vkPresent.CreatePresentableImages();
615 vkPresent.CreateMyWindow();
616 vkPresent.Run();
617 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -0700618 }
619 environment->TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600620}
621
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600622//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600623// These are the default resources for TBuiltInResources, used for both
624// - parsing this string for the case where the user didn't supply one
625// - dumping out a template for user construction of a config file
626//
627static const char* DefaultConfig =
628 "MaxLights 32\n"
629 "MaxClipPlanes 6\n"
630 "MaxTextureUnits 32\n"
631 "MaxTextureCoords 32\n"
632 "MaxVertexAttribs 64\n"
633 "MaxVertexUniformComponents 4096\n"
634 "MaxVaryingFloats 64\n"
635 "MaxVertexTextureImageUnits 32\n"
636 "MaxCombinedTextureImageUnits 80\n"
637 "MaxTextureImageUnits 32\n"
638 "MaxFragmentUniformComponents 4096\n"
639 "MaxDrawBuffers 32\n"
640 "MaxVertexUniformVectors 128\n"
641 "MaxVaryingVectors 8\n"
642 "MaxFragmentUniformVectors 16\n"
643 "MaxVertexOutputVectors 16\n"
644 "MaxFragmentInputVectors 15\n"
645 "MinProgramTexelOffset -8\n"
646 "MaxProgramTexelOffset 7\n"
647 "MaxClipDistances 8\n"
648 "MaxComputeWorkGroupCountX 65535\n"
649 "MaxComputeWorkGroupCountY 65535\n"
650 "MaxComputeWorkGroupCountZ 65535\n"
651 "MaxComputeWorkGroupSizeX 1024\n"
652 "MaxComputeWorkGroupSizeY 1024\n"
653 "MaxComputeWorkGroupSizeZ 64\n"
654 "MaxComputeUniformComponents 1024\n"
655 "MaxComputeTextureImageUnits 16\n"
656 "MaxComputeImageUniforms 8\n"
657 "MaxComputeAtomicCounters 8\n"
658 "MaxComputeAtomicCounterBuffers 1\n"
659 "MaxVaryingComponents 60\n"
660 "MaxVertexOutputComponents 64\n"
661 "MaxGeometryInputComponents 64\n"
662 "MaxGeometryOutputComponents 128\n"
663 "MaxFragmentInputComponents 128\n"
664 "MaxImageUnits 8\n"
665 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
666 "MaxCombinedShaderOutputResources 8\n"
667 "MaxImageSamples 0\n"
668 "MaxVertexImageUniforms 0\n"
669 "MaxTessControlImageUniforms 0\n"
670 "MaxTessEvaluationImageUniforms 0\n"
671 "MaxGeometryImageUniforms 0\n"
672 "MaxFragmentImageUniforms 8\n"
673 "MaxCombinedImageUniforms 8\n"
674 "MaxGeometryTextureImageUnits 16\n"
675 "MaxGeometryOutputVertices 256\n"
676 "MaxGeometryTotalOutputComponents 1024\n"
677 "MaxGeometryUniformComponents 1024\n"
678 "MaxGeometryVaryingComponents 64\n"
679 "MaxTessControlInputComponents 128\n"
680 "MaxTessControlOutputComponents 128\n"
681 "MaxTessControlTextureImageUnits 16\n"
682 "MaxTessControlUniformComponents 1024\n"
683 "MaxTessControlTotalOutputComponents 4096\n"
684 "MaxTessEvaluationInputComponents 128\n"
685 "MaxTessEvaluationOutputComponents 128\n"
686 "MaxTessEvaluationTextureImageUnits 16\n"
687 "MaxTessEvaluationUniformComponents 1024\n"
688 "MaxTessPatchComponents 120\n"
689 "MaxPatchVertices 32\n"
690 "MaxTessGenLevel 64\n"
691 "MaxViewports 16\n"
692 "MaxVertexAtomicCounters 0\n"
693 "MaxTessControlAtomicCounters 0\n"
694 "MaxTessEvaluationAtomicCounters 0\n"
695 "MaxGeometryAtomicCounters 0\n"
696 "MaxFragmentAtomicCounters 8\n"
697 "MaxCombinedAtomicCounters 8\n"
698 "MaxAtomicCounterBindings 1\n"
699 "MaxVertexAtomicCounterBuffers 0\n"
700 "MaxTessControlAtomicCounterBuffers 0\n"
701 "MaxTessEvaluationAtomicCounterBuffers 0\n"
702 "MaxGeometryAtomicCounterBuffers 0\n"
703 "MaxFragmentAtomicCounterBuffers 1\n"
704 "MaxCombinedAtomicCounterBuffers 1\n"
705 "MaxAtomicCounterBufferSize 16384\n"
706 "MaxTransformFeedbackBuffers 4\n"
707 "MaxTransformFeedbackInterleavedComponents 64\n"
708 "MaxCullDistances 8\n"
709 "MaxCombinedClipAndCullDistances 8\n"
710 "MaxSamples 4\n"
711
712 "nonInductiveForLoops 1\n"
713 "whileLoops 1\n"
714 "doWhileLoops 1\n"
715 "generalUniformIndexing 1\n"
716 "generalAttributeMatrixVectorIndexing 1\n"
717 "generalVaryingIndexing 1\n"
718 "generalSamplerIndexing 1\n"
719 "generalVariableIndexing 1\n"
720 "generalConstantMatrixVectorIndexing 1\n"
721 ;
722
723//
724// *.conf => this is a config file that can set limits/resources
725//
726bool XglTestFramework::SetConfigFile(const std::string& name)
727{
728 if (name.size() < 5)
729 return false;
730
731 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
732 ConfigFile = name;
733 return true;
734 }
735
736 return false;
737}
738
739//
740// Parse either a .conf file provided by the user or the default string above.
741//
742void XglTestFramework::ProcessConfigFile()
743{
744 char** configStrings = 0;
745 char* config = 0;
746 if (ConfigFile.size() > 0) {
747 configStrings = ReadFileData(ConfigFile.c_str());
748 if (configStrings)
749 config = *configStrings;
750 else {
751 printf("Error opening configuration file; will instead use the default configuration\n");
752 }
753 }
754
755 if (config == 0) {
756 config = new char[strlen(DefaultConfig) + 1];
757 strcpy(config, DefaultConfig);
758 }
759
760 const char* delims = " \t\n\r";
761 const char* token = strtok(config, delims);
762 while (token) {
763 const char* valueStr = strtok(0, delims);
764 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
765 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
766 return;
767 }
768 int value = atoi(valueStr);
769
770 if (strcmp(token, "MaxLights") == 0)
771 Resources.maxLights = value;
772 else if (strcmp(token, "MaxClipPlanes") == 0)
773 Resources.maxClipPlanes = value;
774 else if (strcmp(token, "MaxTextureUnits") == 0)
775 Resources.maxTextureUnits = value;
776 else if (strcmp(token, "MaxTextureCoords") == 0)
777 Resources.maxTextureCoords = value;
778 else if (strcmp(token, "MaxVertexAttribs") == 0)
779 Resources.maxVertexAttribs = value;
780 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
781 Resources.maxVertexUniformComponents = value;
782 else if (strcmp(token, "MaxVaryingFloats") == 0)
783 Resources.maxVaryingFloats = value;
784 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
785 Resources.maxVertexTextureImageUnits = value;
786 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
787 Resources.maxCombinedTextureImageUnits = value;
788 else if (strcmp(token, "MaxTextureImageUnits") == 0)
789 Resources.maxTextureImageUnits = value;
790 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
791 Resources.maxFragmentUniformComponents = value;
792 else if (strcmp(token, "MaxDrawBuffers") == 0)
793 Resources.maxDrawBuffers = value;
794 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
795 Resources.maxVertexUniformVectors = value;
796 else if (strcmp(token, "MaxVaryingVectors") == 0)
797 Resources.maxVaryingVectors = value;
798 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
799 Resources.maxFragmentUniformVectors = value;
800 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
801 Resources.maxVertexOutputVectors = value;
802 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
803 Resources.maxFragmentInputVectors = value;
804 else if (strcmp(token, "MinProgramTexelOffset") == 0)
805 Resources.minProgramTexelOffset = value;
806 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
807 Resources.maxProgramTexelOffset = value;
808 else if (strcmp(token, "MaxClipDistances") == 0)
809 Resources.maxClipDistances = value;
810 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
811 Resources.maxComputeWorkGroupCountX = value;
812 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
813 Resources.maxComputeWorkGroupCountY = value;
814 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
815 Resources.maxComputeWorkGroupCountZ = value;
816 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
817 Resources.maxComputeWorkGroupSizeX = value;
818 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
819 Resources.maxComputeWorkGroupSizeY = value;
820 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
821 Resources.maxComputeWorkGroupSizeZ = value;
822 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
823 Resources.maxComputeUniformComponents = value;
824 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
825 Resources.maxComputeTextureImageUnits = value;
826 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
827 Resources.maxComputeImageUniforms = value;
828 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
829 Resources.maxComputeAtomicCounters = value;
830 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
831 Resources.maxComputeAtomicCounterBuffers = value;
832 else if (strcmp(token, "MaxVaryingComponents") == 0)
833 Resources.maxVaryingComponents = value;
834 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
835 Resources.maxVertexOutputComponents = value;
836 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
837 Resources.maxGeometryInputComponents = value;
838 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
839 Resources.maxGeometryOutputComponents = value;
840 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
841 Resources.maxFragmentInputComponents = value;
842 else if (strcmp(token, "MaxImageUnits") == 0)
843 Resources.maxImageUnits = value;
844 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
845 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
846 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
847 Resources.maxCombinedShaderOutputResources = value;
848 else if (strcmp(token, "MaxImageSamples") == 0)
849 Resources.maxImageSamples = value;
850 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
851 Resources.maxVertexImageUniforms = value;
852 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
853 Resources.maxTessControlImageUniforms = value;
854 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
855 Resources.maxTessEvaluationImageUniforms = value;
856 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
857 Resources.maxGeometryImageUniforms = value;
858 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
859 Resources.maxFragmentImageUniforms = value;
860 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
861 Resources.maxCombinedImageUniforms = value;
862 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
863 Resources.maxGeometryTextureImageUnits = value;
864 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
865 Resources.maxGeometryOutputVertices = value;
866 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
867 Resources.maxGeometryTotalOutputComponents = value;
868 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
869 Resources.maxGeometryUniformComponents = value;
870 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
871 Resources.maxGeometryVaryingComponents = value;
872 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
873 Resources.maxTessControlInputComponents = value;
874 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
875 Resources.maxTessControlOutputComponents = value;
876 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
877 Resources.maxTessControlTextureImageUnits = value;
878 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
879 Resources.maxTessControlUniformComponents = value;
880 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
881 Resources.maxTessControlTotalOutputComponents = value;
882 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
883 Resources.maxTessEvaluationInputComponents = value;
884 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
885 Resources.maxTessEvaluationOutputComponents = value;
886 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
887 Resources.maxTessEvaluationTextureImageUnits = value;
888 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
889 Resources.maxTessEvaluationUniformComponents = value;
890 else if (strcmp(token, "MaxTessPatchComponents") == 0)
891 Resources.maxTessPatchComponents = value;
892 else if (strcmp(token, "MaxPatchVertices") == 0)
893 Resources.maxPatchVertices = value;
894 else if (strcmp(token, "MaxTessGenLevel") == 0)
895 Resources.maxTessGenLevel = value;
896 else if (strcmp(token, "MaxViewports") == 0)
897 Resources.maxViewports = value;
898 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
899 Resources.maxVertexAtomicCounters = value;
900 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
901 Resources.maxTessControlAtomicCounters = value;
902 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
903 Resources.maxTessEvaluationAtomicCounters = value;
904 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
905 Resources.maxGeometryAtomicCounters = value;
906 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
907 Resources.maxFragmentAtomicCounters = value;
908 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
909 Resources.maxCombinedAtomicCounters = value;
910 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
911 Resources.maxAtomicCounterBindings = value;
912 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
913 Resources.maxVertexAtomicCounterBuffers = value;
914 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
915 Resources.maxTessControlAtomicCounterBuffers = value;
916 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
917 Resources.maxTessEvaluationAtomicCounterBuffers = value;
918 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
919 Resources.maxGeometryAtomicCounterBuffers = value;
920 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
921 Resources.maxFragmentAtomicCounterBuffers = value;
922 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
923 Resources.maxCombinedAtomicCounterBuffers = value;
924 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
925 Resources.maxAtomicCounterBufferSize = value;
926 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
927 Resources.maxTransformFeedbackBuffers = value;
928 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
929 Resources.maxTransformFeedbackInterleavedComponents = value;
930 else if (strcmp(token, "MaxCullDistances") == 0)
931 Resources.maxCullDistances = value;
932 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
933 Resources.maxCombinedClipAndCullDistances = value;
934 else if (strcmp(token, "MaxSamples") == 0)
935 Resources.maxSamples = value;
936
937 else if (strcmp(token, "nonInductiveForLoops") == 0)
938 Resources.limits.nonInductiveForLoops = (value != 0);
939 else if (strcmp(token, "whileLoops") == 0)
940 Resources.limits.whileLoops = (value != 0);
941 else if (strcmp(token, "doWhileLoops") == 0)
942 Resources.limits.doWhileLoops = (value != 0);
943 else if (strcmp(token, "generalUniformIndexing") == 0)
944 Resources.limits.generalUniformIndexing = (value != 0);
945 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
946 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
947 else if (strcmp(token, "generalVaryingIndexing") == 0)
948 Resources.limits.generalVaryingIndexing = (value != 0);
949 else if (strcmp(token, "generalSamplerIndexing") == 0)
950 Resources.limits.generalSamplerIndexing = (value != 0);
951 else if (strcmp(token, "generalVariableIndexing") == 0)
952 Resources.limits.generalVariableIndexing = (value != 0);
953 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
954 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
955 else
956 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
957
958 token = strtok(0, delims);
959 }
960 if (configStrings)
961 FreeFileData(configStrings);
962}
963
964void XglTestFramework::SetMessageOptions(EShMessages& messages)
965{
966 if (m_compile_options & EOptionRelaxedErrors)
967 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
968 if (m_compile_options & EOptionIntermediate)
969 messages = (EShMessages)(messages | EShMsgAST);
970 if (m_compile_options & EOptionSuppressWarnings)
971 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
972}
973
974//
975// Malloc a string of sufficient size and read a string into it.
976//
977char** XglTestFramework::ReadFileData(const char* fileName)
978{
979 FILE *in;
980 #if defined(_WIN32) && defined(__GNUC__)
981 in = fopen(fileName, "r");
982 int errorCode = in ? 0 : 1;
983 #else
984 int errorCode = fopen_s(&in, fileName, "r");
985 #endif
986
987 char *fdata;
988 int count = 0;
989 const int maxSourceStrings = 5;
990 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
991
992 if (errorCode) {
993 printf("Error: unable to open input file: %s\n", fileName);
994 return 0;
995 }
996
997 while (fgetc(in) != EOF)
998 count++;
999
1000 fseek(in, 0, SEEK_SET);
1001
1002 if (!(fdata = (char*)malloc(count+2))) {
1003 printf("Error allocating memory\n");
1004 return 0;
1005 }
1006 if (fread(fdata,1,count, in)!=count) {
1007 printf("Error reading input file: %s\n", fileName);
1008 return 0;
1009 }
1010 fdata[count] = '\0';
1011 fclose(in);
1012 if (count == 0) {
1013 return_data[0]=(char*)malloc(count+2);
1014 return_data[0][0]='\0';
1015 m_num_shader_strings = 0;
1016 return return_data;
1017 } else
1018 m_num_shader_strings = 1;
1019
1020 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1021 int ptr_len=0,i=0;
1022 while(count>0){
1023 return_data[i]=(char*)malloc(len+2);
1024 memcpy(return_data[i],fdata+ptr_len,len);
1025 return_data[i][len]='\0';
1026 count-=(len);
1027 ptr_len+=(len);
1028 if(count<len){
1029 if(count==0){
1030 m_num_shader_strings=(i+1);
1031 break;
1032 }
1033 len = count;
1034 }
1035 ++i;
1036 }
1037 return return_data;
1038}
1039
1040void XglTestFramework::FreeFileData(char** data)
1041{
1042 for(int i=0;i<m_num_shader_strings;i++)
1043 free(data[i]);
1044}
1045
1046//
1047// Deduce the language from the filename. Files must end in one of the
1048// following extensions:
1049//
1050// .vert = vertex
1051// .tesc = tessellation control
1052// .tese = tessellation evaluation
1053// .geom = geometry
1054// .frag = fragment
1055// .comp = compute
1056//
1057EShLanguage XglTestFramework::FindLanguage(const std::string& name)
1058{
1059 size_t ext = name.rfind('.');
1060 if (ext == std::string::npos) {
1061 return EShLangVertex;
1062 }
1063
1064 std::string suffix = name.substr(ext + 1, std::string::npos);
1065 if (suffix == "vert")
1066 return EShLangVertex;
1067 else if (suffix == "tesc")
1068 return EShLangTessControl;
1069 else if (suffix == "tese")
1070 return EShLangTessEvaluation;
1071 else if (suffix == "geom")
1072 return EShLangGeometry;
1073 else if (suffix == "frag")
1074 return EShLangFragment;
1075 else if (suffix == "comp")
1076 return EShLangCompute;
1077
1078 return EShLangVertex;
1079}
1080
1081//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001082// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001083//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001084EShLanguage XglTestFramework::FindLanguage(const VK_PIPELINE_SHADER_STAGE shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001085{
1086 switch (shader_type) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001087 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001088 return EShLangVertex;
1089
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001090 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001091 return EShLangTessControl;
1092
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001093 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001094 return EShLangTessEvaluation;
1095
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001096 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001097 return EShLangGeometry;
1098
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001099 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001100 return EShLangFragment;
1101
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001102 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001103 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001104
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001105 default:
1106 return EShLangVertex;
1107 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001108}
1109
1110
1111//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001112// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001113// Return value of false means an error was encountered.
1114//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001115bool XglTestFramework::GLSLtoSPV(const VK_PIPELINE_SHADER_STAGE shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001116 const char *pshader,
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001117 std::vector<unsigned int> &spv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001118{
1119 glslang::TProgram& program = *new glslang::TProgram;
1120 const char *shaderStrings[1];
1121
1122 // TODO: Do we want to load a special config file depending on the
1123 // shader source? Optional name maybe?
1124 // SetConfigFile(fileName);
1125
1126 ProcessConfigFile();
1127
1128 EShMessages messages = EShMsgDefault;
1129 SetMessageOptions(messages);
1130
1131 EShLanguage stage = FindLanguage(shader_type);
1132 glslang::TShader* shader = new glslang::TShader(stage);
1133
1134 shaderStrings[0] = pshader;
1135 shader->setStrings(shaderStrings, 1);
1136
1137 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1138
Cody Northrop195d6622014-11-03 12:54:37 -07001139 if (! (m_compile_options & EOptionSuppressInfolog)) {
1140 puts(shader->getInfoLog());
1141 puts(shader->getInfoDebugLog());
1142 }
1143
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001144 return false; // something didn't work
1145 }
1146
1147 program.addShader(shader);
1148
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001149
1150 //
1151 // Program-level processing...
1152 //
1153
Cody Northrop195d6622014-11-03 12:54:37 -07001154 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001155
Cody Northrop195d6622014-11-03 12:54:37 -07001156 if (! (m_compile_options & EOptionSuppressInfolog)) {
1157 puts(shader->getInfoLog());
1158 puts(shader->getInfoDebugLog());
1159 }
1160
1161 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001162 }
1163
1164 if (m_compile_options & EOptionDumpReflection) {
1165 program.buildReflection();
1166 program.dumpReflection();
1167 }
1168
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001169 glslang::GlslangToSpv(*program.getIntermediate(stage), spv);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001170
1171 return true;
1172}
1173
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001174
1175
1176XglTestImageRecord::XglTestImageRecord() : // Constructor
1177 m_width( 0 ),
1178 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001179 m_data( NULL ),
Tony Barbour96db8822015-02-25 12:28:39 -07001180 m_presentableImage( NULL ),
1181 m_presentableMemory( NULL),
Chia-I Wu837f9952014-12-15 23:29:34 +08001182 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001183{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001184}
1185
1186XglTestImageRecord::~XglTestImageRecord()
1187{
1188
1189}
1190
1191XglTestImageRecord::XglTestImageRecord(const XglTestImageRecord &copyin) // Copy constructor to handle pass by value.
1192{
1193 m_title = copyin.m_title;
1194 m_width = copyin.m_width;
1195 m_height = copyin.m_height;
1196 m_data_size = copyin.m_data_size;
1197 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
Tony Barbour96db8822015-02-25 12:28:39 -07001198 m_presentableImage = copyin.m_presentableImage;
1199 m_presentableMemory = copyin.m_presentableMemory;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001200}
1201
1202ostream &operator<<(ostream &output, const XglTestImageRecord &XglTestImageRecord)
1203{
1204 output << XglTestImageRecord.m_title << " (" << XglTestImageRecord.m_width <<
1205 "," << XglTestImageRecord.m_height << ")" << endl;
1206 return output;
1207}
1208
1209XglTestImageRecord& XglTestImageRecord::operator=(const XglTestImageRecord &rhs)
1210{
1211 m_title = rhs.m_title;
1212 m_width = rhs.m_width;
1213 m_height = rhs.m_height;
1214 m_data_size = rhs.m_data_size;
1215 m_data = rhs.m_data;
Tony Barbour96db8822015-02-25 12:28:39 -07001216 m_presentableImage = rhs.m_presentableImage;
1217 m_presentableMemory = rhs.m_presentableMemory;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001218 return *this;
1219}
1220
1221int XglTestImageRecord::operator==(const XglTestImageRecord &rhs) const
1222{
1223 if( this->m_data != rhs.m_data) return 0;
1224 return 1;
1225}
1226
1227// This function is required for built-in STL list functions like sort
1228int XglTestImageRecord::operator<(const XglTestImageRecord &rhs) const
1229{
1230 if( this->m_data_size < rhs.m_data_size ) return 1;
1231 return 0;
1232}
1233