blob: cb79abbeaf6bc3c80a92dd7471face7f9fabd3fd [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>
Chia-I Wuf8693382015-04-16 22:02:10 +080031#include <xcb/xcb.h>
32#include <vk_wsi_lunarg.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060033
34// Command-line options
35enum TOptions {
36 EOptionNone = 0x000,
37 EOptionIntermediate = 0x001,
38 EOptionSuppressInfolog = 0x002,
39 EOptionMemoryLeakMode = 0x004,
40 EOptionRelaxedErrors = 0x008,
41 EOptionGiveWarnings = 0x010,
42 EOptionLinkProgram = 0x020,
43 EOptionMultiThreaded = 0x040,
44 EOptionDumpConfig = 0x080,
45 EOptionDumpReflection = 0x100,
46 EOptionSuppressWarnings = 0x200,
47 EOptionDumpVersions = 0x400,
Cody Northrop3bfd27c2015-03-17 15:55:58 -060048 EOptionSpv = 0x800,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060049 EOptionDefaultDesktop = 0x1000,
50};
51
Chia-I Wuf8693382015-04-16 22:02:10 +080052class TestFrameworkVkPresent
53{
54public:
55 TestFrameworkVkPresent(vk_testing::Device &device);
56
57 void Run();
58 void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn);
59 void CreateMyWindow();
60 void CreateSwapChain();
61 void TearDown();
62
63protected:
64 vk_testing::Device &m_device;
65 vk_testing::Queue &m_queue;
66 vk_testing::CmdBuffer m_cmdbuf;
67
68private:
69 xcb_connection_t *m_connection;
70 xcb_screen_t *m_screen;
71 xcb_window_t m_window;
72 xcb_intern_atom_reply_t *m_atom_wm_delete_window;
Courtney Goeltzenleuchterd6079ec2015-04-22 10:09:35 -060073 std::list<VkTestImageRecord> m_images;
Chia-I Wuf8693382015-04-16 22:02:10 +080074
75 VkSwapChainWSI m_swap_chain;
76
77 bool m_quit;
78 bool m_pause;
79
80 uint32_t m_width;
81 uint32_t m_height;
82
83 std::list<VkTestImageRecord>::iterator m_display_image;
84
85 void Display();
86 void HandleEvent(xcb_generic_event_t *event);
87};
88
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060089#ifndef _WIN32
90
91#include <errno.h>
92
93int fopen_s(
94 FILE** pFile,
95 const char* filename,
96 const char* mode
97)
98{
99 if (!pFile || !filename || !mode) {
100 return EINVAL;
101 }
102
103 FILE* f = fopen(filename, mode);
104 if (! f) {
105 if (errno != 0) {
106 return errno;
107 } else {
108 return ENOENT;
109 }
110 }
111 *pFile = f;
112
113 return 0;
114}
115
116#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600117
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600118// Set up environment for GLSL compiler
119// Must be done once per process
120void TestEnvironment::SetUp()
121{
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600122 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600123 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800124
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600125 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600126}
127
128void TestEnvironment::TearDown()
129{
130 glslang::FinalizeProcess();
131}
132
Tony Barbour6918cd52015-04-09 12:58:51 -0600133VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600134 m_compile_options( 0 ),
135 m_num_shader_strings( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600136{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600137
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600138}
139
Tony Barbour6918cd52015-04-09 12:58:51 -0600140VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600141{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600142
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600143}
144
145// Define all the static elements
Tony Barbour6918cd52015-04-09 12:58:51 -0600146bool VkTestFramework::m_show_images = false;
147bool VkTestFramework::m_save_images = false;
148bool VkTestFramework::m_compare_images = false;
Tony Barbour0dd968a2015-04-02 15:48:24 -0600149#ifdef _WIN32
Tony Barbour6918cd52015-04-09 12:58:51 -0600150bool VkTestFramework::m_use_spv = false;
Tony Barbour0dd968a2015-04-02 15:48:24 -0600151#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600152bool VkTestFramework::m_use_spv = true;
Tony Barbour0dd968a2015-04-02 15:48:24 -0600153#endif
Tony Barbour6918cd52015-04-09 12:58:51 -0600154int VkTestFramework::m_width = 0;
155int VkTestFramework::m_height = 0;
156std::list<VkTestImageRecord> VkTestFramework::m_images;
157std::list<VkTestImageRecord>::iterator VkTestFramework::m_display_image;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600158int m_display_image_idx = 0;
159
Tony Barbour6918cd52015-04-09 12:58:51 -0600160void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600161{
162 int i, n;
163
164 for (i=0, n=0; i< *argc; i++) {
165 if (strncmp("--show-images", argv[i], 13) == 0) {
166 m_show_images = true;
167 continue;
168 }
169 if (strncmp("--save-images", argv[i], 13) == 0) {
170 m_save_images = true;
171 continue;
172 }
173
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600174 if (strncmp("--use-SPV", argv[i], 13) == 0) {
175 m_use_spv = true;
Courtney Goeltzenleuchterb666dc62014-10-09 09:13:56 -0600176 continue;
177 }
178
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600179 if (strncmp("--no-SPV", argv[i], 13) == 0) {
180 m_use_spv = false;
Courtney Goeltzenleuchterc44e3ee2014-10-31 14:13:33 -0600181 continue;
182 }
183
Tony Barbour247bf372014-10-30 14:29:04 -0600184 if (strncmp("--compare-images", argv[i], 16) == 0) {
185 m_compare_images = true;
186 continue;
187 }
188
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600189 /*
190 * Since the above "consume" inputs, update argv
191 * so that it contains the trimmed list of args for glutInit
192 */
Tony Barboura98d3932014-12-11 09:52:49 -0700193 if (strncmp("--help", argv[i], 6) == 0 || strncmp("-h", argv[i], 2) == 0) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700194 printf("\nOther options:\n");
195 printf("\t--show-images\n"
196 "\t\tDisplay test images in viewer after tests complete.\n");
197 printf("\t--save-images\n"
198 "\t\tSave tests images as ppm files in current working directory.\n"
199 "\t\tUsed to generate golden images for compare-images.\n");
200 printf("\t--compare-images\n"
201 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barboura98d3932014-12-11 09:52:49 -0700202 "\t\tAlso saves the generated test image in current working\n"
203 "\t\t\tdirectory but only if the image is different from the golden\n"
204 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
205 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700206 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600207 printf("\t--use-SPV\n"
208 "\t\tUse SPV code path (default).\n");
209 printf("\t--no-SPV\n"
210 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700211 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700212 }
213
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600214 argv[n] = argv[i];
215 n++;
216 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600217}
218
Tony Barbour6918cd52015-04-09 12:58:51 -0600219void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600220{
221 string filename;
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600222 VkResult err;
Tony Barbour84d448c2015-04-02 14:02:33 -0600223 int x, y;
Tony Barbour6918cd52015-04-09 12:58:51 -0600224 VkImageObj displayImage(image->device());
Tony Barbour84d448c2015-04-02 14:02:33 -0600225
Tony Barbourd1c35722015-04-16 15:59:00 -0600226 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, VK_IMAGE_TILING_LINEAR);
Tony Barbour84d448c2015-04-02 14:02:33 -0600227 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600228
229 filename.append(basename);
230 filename.append(".ppm");
231
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600232 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600233 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600234 };
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600235 VkSubresourceLayout sr_layout;
Chia-I Wu99ff89d2014-12-27 14:14:50 +0800236 size_t data_size = sizeof(sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600237
Mike Stroyanb050c682015-04-17 12:36:38 -0600238 err = vkGetImageSubresourceInfo(image->device()->device(), image->image(), &sr,
Tony Barbourd1c35722015-04-16 15:59:00 -0600239 VK_SUBRESOURCE_INFO_TYPE_LAYOUT,
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600240 &data_size, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600241 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600242 ASSERT_EQ(data_size, sizeof(sr_layout));
243
Tony Barbour84d448c2015-04-02 14:02:33 -0600244 char *ptr;
245 ptr = (char *) displayImage.map();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600246 ptr += sr_layout.offset;
247
248 ofstream file (filename.c_str());
249 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
250
251 file << "P6\n";
Tony Barbour84d448c2015-04-02 14:02:33 -0600252 file << displayImage.width() << "\n";
253 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600254 file << 255 << "\n";
255
Tony Barbour84d448c2015-04-02 14:02:33 -0600256 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700257 const int *row = (const int *) ptr;
258 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600259
Tony Barbourd1c35722015-04-16 15:59:00 -0600260 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700261 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600262 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700263 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
264 file.write((char *) &swapped, 3);
265 row++;
266 }
267 }
Tony Barbourd1c35722015-04-16 15:59:00 -0600268 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700269 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600270 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700271 file.write((char *) row, 3);
272 row++;
273 }
274 }
275 else {
276 printf("Unrecognized image format - will not write image files");
277 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600278 }
279
280 ptr += sr_layout.rowPitch;
281 }
282
283 file.close();
Tony Barbour84d448c2015-04-02 14:02:33 -0600284 displayImage.unmap();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600285}
286
Tony Barbour6918cd52015-04-09 12:58:51 -0600287void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour247bf372014-10-30 14:29:04 -0600288{
289
290 MagickWand *magick_wand_1;
291 MagickWand *magick_wand_2;
292 MagickWand *compare_wand;
293 MagickBooleanType status;
Tony Barbour4ab45422014-12-10 17:00:20 -0700294 char testimage[256],golden[PATH_MAX+256],golddir[PATH_MAX] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600295 double differenz;
296
Tony Barbour4ab45422014-12-10 17:00:20 -0700297 if (getenv("RENDERTEST_GOLDEN_DIR"))
298 {
299 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
300 }
301
Tony Barbour247bf372014-10-30 14:29:04 -0600302 MagickWandGenesis();
303 magick_wand_1=NewMagickWand();
304 sprintf(testimage,"%s.ppm",basename);
305 status=MagickReadImage(magick_wand_1,testimage);
306 ASSERT_TRUE(status) << "Unable to open file: " << testimage;
307
308
309 MagickWandGenesis();
310 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700311 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600312 status=MagickReadImage(magick_wand_2,golden);
313 ASSERT_TRUE(status) << "Unable to open file: " << golden;
314
Tony Barbour247bf372014-10-30 14:29:04 -0600315 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
316 if (differenz != 0.0)
317 {
318 char difference[256];
319
320 sprintf(difference,"%s-diff.ppm",basename);
321 status = MagickWriteImage(compare_wand, difference);
322 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
323 }
324 DestroyMagickWand(compare_wand);
325
326 DestroyMagickWand(magick_wand_1);
327 DestroyMagickWand(magick_wand_2);
328 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700329
330 if (differenz == 0.0)
331 {
332 /*
333 * If test image and golden image match, we do not need to
334 * keep around the test image.
335 */
336 remove(testimage);
337 }
Tony Barbour247bf372014-10-30 14:29:04 -0600338}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600339
Tony Barbour6918cd52015-04-09 12:58:51 -0600340void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600341{
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600342 VkResult err;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600343
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600344 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600345 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600346 };
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600347 VkSubresourceLayout sr_layout;
Chia-I Wu99ff89d2014-12-27 14:14:50 +0800348 size_t data_size = sizeof(sr_layout);
Tony Barbour6918cd52015-04-09 12:58:51 -0600349 VkTestImageRecord record;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600350
351 if (!m_show_images) return;
352
Mike Stroyanb050c682015-04-17 12:36:38 -0600353 err = vkGetImageSubresourceInfo( image->device()->device(), image->image(), &sr, VK_SUBRESOURCE_INFO_TYPE_LAYOUT,
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600354 &data_size, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600355 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600356 ASSERT_EQ(data_size, sizeof(sr_layout));
357
Tony Barbour96db8822015-02-25 12:28:39 -0700358 char *ptr;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600359
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600360 err = image->MapMemory( (void **) &ptr );
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600361 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600362
363 ptr += sr_layout.offset;
364
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600365 record.m_title.append(comment);
366 record.m_width = image->width();
367 record.m_height = image->height();
368 // TODO: Need to make this more robust to handle different image formats
369 record.m_data_size = image->width()*image->height()*4;
370 record.m_data = malloc(record.m_data_size);
371 memcpy(record.m_data, ptr, record.m_data_size);
372 m_images.push_back(record);
373 m_display_image = --m_images.end();
374
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600375 err = image->UnmapMemory();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600376 ASSERT_VK_SUCCESS( err );
Tony Barbour96db8822015-02-25 12:28:39 -0700377
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600378}
379
Tony Barbour6918cd52015-04-09 12:58:51 -0600380void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600381{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600382 for (int32_t i = 0; i < images.size(); i++) {
383 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600384 }
385}
386
Tony Barbour6918cd52015-04-09 12:58:51 -0600387void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600388{
389 const ::testing::TestInfo* const test_info =
390 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600391 ostringstream filestream;
392 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600393
Tony Barbour247bf372014-10-30 14:29:04 -0600394 m_width = 40;
395
396 if (strcmp(test_info->name(), m_testName.c_str())) {
397 filestream << test_info->name();
398 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700399 m_frameNum = 2;
400 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600401 }
402 else {
403 filestream << test_info->name() << "-" << m_frameNum;
404 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700405 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600406 }
407
Tony Barbour247bf372014-10-30 14:29:04 -0600408 // ToDo - scrub string for bad characters
409
410 if (m_save_images || m_compare_images) {
411 WritePPM(filename.c_str(), image);
412 if (m_compare_images) {
413 Compare(filename.c_str(), image);
414 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600415 }
416
417 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600418 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600419 }
420}
421
Chia-I Wuf8693382015-04-16 22:02:10 +0800422TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
423 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700424 m_queue(*m_device.graphics_queues()[0]),
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600425 m_cmdbuf(m_device, vk_testing::CmdBuffer::create_info(m_device.graphics_queue_node_index_))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600426{
Tony Barbour96db8822015-02-25 12:28:39 -0700427 m_quit = false;
428 m_pause = false;
429 m_width = 0;
430 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600431}
432
Tony Barbour6918cd52015-04-09 12:58:51 -0600433void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600434{
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600435 VkResult err;
Tony Barbour96db8822015-02-25 12:28:39 -0700436
Chia-I Wuf8693382015-04-16 22:02:10 +0800437 VkPresentInfoWSI present = {};
438 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_WSI;
439 present.image = m_display_image->m_presentableImage;
440 present.flipInterval = 1;
Tony Barbour96db8822015-02-25 12:28:39 -0700441
Chia-I Wuf8693382015-04-16 22:02:10 +0800442 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700443 XCB_PROP_MODE_REPLACE,
444 m_window,
445 XCB_ATOM_WM_NAME,
446 XCB_ATOM_STRING,
447 8,
448 m_display_image->m_title.size(),
449 m_display_image->m_title.c_str());
450
Chia-I Wuf8693382015-04-16 22:02:10 +0800451 err = vkQueuePresentWSI(m_queue.obj(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700452 assert(!err);
453
454 m_queue.wait();
455
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600456}
457
Tony Barbour6918cd52015-04-09 12:58:51 -0600458void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600459{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600460 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700461 switch (event_code) {
462 case XCB_EXPOSE:
463 Display(); // TODO: handle resize
464 break;
465 case XCB_CLIENT_MESSAGE:
466 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
467 (m_atom_wm_delete_window)->atom) {
468 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600469 }
470 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700471 case XCB_KEY_RELEASE:
472 {
473 const xcb_key_release_event_t *key =
474 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600475
Tony Barbour96db8822015-02-25 12:28:39 -0700476 switch (key->detail) {
477 case 0x9: // Escape
478 m_quit = true;
479 break;
480 case 0x71: // left arrow key
481 if (m_display_image == m_images.begin()) {
482 m_display_image = --m_images.end();
483 } else {
484 --m_display_image;
485 }
486 break;
487 case 0x72: // right arrow key
488 ++m_display_image;
489 if (m_display_image == m_images.end()) {
490 m_display_image = m_images.begin();
491 }
492 break;
493 case 0x41:
494 m_pause = !m_pause;
495 break;
496 }
497 Display();
498 }
499 break;
500 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600501 break;
502 }
Tony Barbour96db8822015-02-25 12:28:39 -0700503}
504
Tony Barbour6918cd52015-04-09 12:58:51 -0600505void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700506{
Chia-I Wuf8693382015-04-16 22:02:10 +0800507 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700508
509 while (! m_quit) {
510 xcb_generic_event_t *event;
511
512 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800513 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700514 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800515 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700516 }
517 if (event) {
518 HandleEvent(event);
519 free(event);
520 }
521 }
522}
523
Chia-I Wuf8693382015-04-16 22:02:10 +0800524void TestFrameworkVkPresent::CreateSwapChain()
Tony Barbour96db8822015-02-25 12:28:39 -0700525{
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600526 VkResult err;
Tony Barbour96db8822015-02-25 12:28:39 -0700527
Chia-I Wuf8693382015-04-16 22:02:10 +0800528 VkSwapChainCreateInfoWSI swap_chain = {};
529 swap_chain.sType = VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI;
530 swap_chain.pNativeWindowSystemHandle = (void *) m_connection;
531 swap_chain.pNativeWindowHandle = (void *) (intptr_t) m_window;
532 swap_chain.imageCount = m_images.size();
533 swap_chain.imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
534 swap_chain.imageExtent.width = m_width;
535 swap_chain.imageExtent.height = m_height;
536 swap_chain.imageArraySize = 1;
537 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT;
538 swap_chain.swapModeFlags = VK_SWAP_MODE_FLIP_BIT_WSI |
539 VK_SWAP_MODE_BLIT_BIT_WSI;
540
541 err = vkCreateSwapChainWSI(m_device.obj(), &swap_chain, &m_swap_chain);
542 assert(!err);
543
544 size_t size = sizeof(VkSwapChainImageInfoWSI) * m_images.size();
545 std::vector<VkSwapChainImageInfoWSI> persistent_images;
546 persistent_images.resize(m_images.size());
547 err = vkGetSwapChainInfoWSI(m_swap_chain,
548 VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI,
549 &size, &persistent_images[0]);
550 assert(!err && size == sizeof(VkSwapChainImageInfoWSI) * m_images.size());
551
Tony Barbour96db8822015-02-25 12:28:39 -0700552 m_display_image = m_images.begin();
553
554 for (int x=0; x < m_images.size(); x++)
555 {
Tony Barbour96db8822015-02-25 12:28:39 -0700556 void *dest_ptr;
557
Chia-I Wuf8693382015-04-16 22:02:10 +0800558 m_display_image->m_presentableImage = persistent_images[x].image;
559 m_display_image->m_presentableMemory = persistent_images[x].memory;
Tony Barbour96db8822015-02-25 12:28:39 -0700560
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600561 vk_testing::Buffer buf;
Tony Barbourd1c35722015-04-16 15:59:00 -0600562 buf.init(m_device, (VkDeviceSize) m_display_image->m_data_size);
Tony Barbour96db8822015-02-25 12:28:39 -0700563 dest_ptr = buf.map();
564 memcpy(dest_ptr,m_display_image->m_data, m_display_image->m_data_size);
565 buf.unmap();
566
567 m_cmdbuf.begin();
568
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600569 VkBufferImageCopy region = {};
Tony Barbour96db8822015-02-25 12:28:39 -0700570 region.imageExtent.height = m_display_image->m_height;
571 region.imageExtent.width = m_display_image->m_width;
572 region.imageExtent.depth = 1;
573
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600574 vkCmdCopyBufferToImage(m_cmdbuf.obj(),
Courtney Goeltzenleuchterb3efe9b2015-03-25 11:25:10 -0600575 buf.obj(),
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600576 m_display_image->m_presentableImage, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
Courtney Goeltzenleuchterb3efe9b2015-03-25 11:25:10 -0600577 1, &region);
Tony Barbour96db8822015-02-25 12:28:39 -0700578 m_cmdbuf.end();
579
Courtney Goeltzenleuchterf68ad722015-04-16 13:38:46 -0600580 vkQueueAddMemReferences(m_queue.obj(), 1, &m_display_image->m_presentableMemory);
581 vkQueueAddMemReferences(m_queue.obj(), buf.memories().size(), &buf.memories()[0]);
Tony Barbour96db8822015-02-25 12:28:39 -0700582
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600583 VkCmdBuffer cmdBufs[1];
Tony Barbour96db8822015-02-25 12:28:39 -0700584 cmdBufs[0] = m_cmdbuf.obj();
585
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600586 vkQueueSubmit(m_queue.obj(), 1, cmdBufs, NULL);
Tony Barbour96db8822015-02-25 12:28:39 -0700587 m_queue.wait();
588
Courtney Goeltzenleuchterf68ad722015-04-16 13:38:46 -0600589 vkQueueRemoveMemReferences(m_queue.obj(), 1, &m_display_image->m_presentableMemory);
590 vkQueueRemoveMemReferences(m_queue.obj(), buf.memories().size(), &buf.memories()[0]);
Tony Barbour96db8822015-02-25 12:28:39 -0700591
Tony Barbour96db8822015-02-25 12:28:39 -0700592 ++m_display_image;
Tony Barbour96db8822015-02-25 12:28:39 -0700593 }
594
595 m_display_image = m_images.begin();
596}
597
Tony Barbour6918cd52015-04-09 12:58:51 -0600598void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn)
Tony Barbour96db8822015-02-25 12:28:39 -0700599{
600 m_images = imagesIn;
601}
602
Tony Barbour6918cd52015-04-09 12:58:51 -0600603void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -0700604{
Chia-I Wuf8693382015-04-16 22:02:10 +0800605 const xcb_setup_t *setup;
606 xcb_screen_iterator_t iter;
607 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -0700608 uint32_t value_mask, value_list[32];
609
Chia-I Wuf8693382015-04-16 22:02:10 +0800610 m_connection = xcb_connect(NULL, &scr);
611
612 setup = xcb_get_setup(m_connection);
613 iter = xcb_setup_roots_iterator(setup);
614 while (scr-- > 0)
615 xcb_screen_next(&iter);
616
617 m_screen = iter.data;
618
619 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
620 it != m_images.end(); it++) {
621 if (m_width < it->m_width)
622 m_width = it->m_width;
623 if (m_height < it->m_height)
624 m_height = it->m_height;
625 }
626
627 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700628
629 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +0800630 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -0700631 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
632 XCB_EVENT_MASK_EXPOSURE |
633 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
634
Chia-I Wuf8693382015-04-16 22:02:10 +0800635 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700636 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800637 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -0700638 0, 0, m_width, m_height, 0,
639 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800640 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -0700641 value_mask, value_list);
642
643 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +0800644 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -0700645 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +0800646 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -0700647
Chia-I Wuf8693382015-04-16 22:02:10 +0800648 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
649 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -0700650
Chia-I Wuf8693382015-04-16 22:02:10 +0800651 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -0700652 m_window, (*reply).atom, 4, 32, 1,
653 &(*m_atom_wm_delete_window).atom);
654 free(reply);
655
Chia-I Wuf8693382015-04-16 22:02:10 +0800656 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -0700657}
658
Tony Barbour6918cd52015-04-09 12:58:51 -0600659void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -0700660{
Chia-I Wuf8693382015-04-16 22:02:10 +0800661 vkDestroySwapChainWSI(m_swap_chain);
662 xcb_destroy_window(m_connection, m_window);
663 xcb_disconnect(m_connection);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600664}
665
Tony Barbour6918cd52015-04-09 12:58:51 -0600666void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600667{
668 if (m_images.size() == 0) return;
669
Chia-I Wuf8693382015-04-16 22:02:10 +0800670 vk_testing::Environment env;
671 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -0700672 {
Chia-I Wuf8693382015-04-16 22:02:10 +0800673 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -0700674
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600675 vkPresent.InitPresentFramework(m_images);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600676 vkPresent.CreateMyWindow();
Chia-I Wuf8693382015-04-16 22:02:10 +0800677 vkPresent.CreateSwapChain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600678 vkPresent.Run();
679 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -0700680 }
Chia-I Wuf8693382015-04-16 22:02:10 +0800681 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600682}
683
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600684//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600685// These are the default resources for TBuiltInResources, used for both
686// - parsing this string for the case where the user didn't supply one
687// - dumping out a template for user construction of a config file
688//
689static const char* DefaultConfig =
690 "MaxLights 32\n"
691 "MaxClipPlanes 6\n"
692 "MaxTextureUnits 32\n"
693 "MaxTextureCoords 32\n"
694 "MaxVertexAttribs 64\n"
695 "MaxVertexUniformComponents 4096\n"
696 "MaxVaryingFloats 64\n"
697 "MaxVertexTextureImageUnits 32\n"
698 "MaxCombinedTextureImageUnits 80\n"
699 "MaxTextureImageUnits 32\n"
700 "MaxFragmentUniformComponents 4096\n"
701 "MaxDrawBuffers 32\n"
702 "MaxVertexUniformVectors 128\n"
703 "MaxVaryingVectors 8\n"
704 "MaxFragmentUniformVectors 16\n"
705 "MaxVertexOutputVectors 16\n"
706 "MaxFragmentInputVectors 15\n"
707 "MinProgramTexelOffset -8\n"
708 "MaxProgramTexelOffset 7\n"
709 "MaxClipDistances 8\n"
710 "MaxComputeWorkGroupCountX 65535\n"
711 "MaxComputeWorkGroupCountY 65535\n"
712 "MaxComputeWorkGroupCountZ 65535\n"
713 "MaxComputeWorkGroupSizeX 1024\n"
714 "MaxComputeWorkGroupSizeY 1024\n"
715 "MaxComputeWorkGroupSizeZ 64\n"
716 "MaxComputeUniformComponents 1024\n"
717 "MaxComputeTextureImageUnits 16\n"
718 "MaxComputeImageUniforms 8\n"
719 "MaxComputeAtomicCounters 8\n"
720 "MaxComputeAtomicCounterBuffers 1\n"
721 "MaxVaryingComponents 60\n"
722 "MaxVertexOutputComponents 64\n"
723 "MaxGeometryInputComponents 64\n"
724 "MaxGeometryOutputComponents 128\n"
725 "MaxFragmentInputComponents 128\n"
726 "MaxImageUnits 8\n"
727 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
728 "MaxCombinedShaderOutputResources 8\n"
729 "MaxImageSamples 0\n"
730 "MaxVertexImageUniforms 0\n"
731 "MaxTessControlImageUniforms 0\n"
732 "MaxTessEvaluationImageUniforms 0\n"
733 "MaxGeometryImageUniforms 0\n"
734 "MaxFragmentImageUniforms 8\n"
735 "MaxCombinedImageUniforms 8\n"
736 "MaxGeometryTextureImageUnits 16\n"
737 "MaxGeometryOutputVertices 256\n"
738 "MaxGeometryTotalOutputComponents 1024\n"
739 "MaxGeometryUniformComponents 1024\n"
740 "MaxGeometryVaryingComponents 64\n"
741 "MaxTessControlInputComponents 128\n"
742 "MaxTessControlOutputComponents 128\n"
743 "MaxTessControlTextureImageUnits 16\n"
744 "MaxTessControlUniformComponents 1024\n"
745 "MaxTessControlTotalOutputComponents 4096\n"
746 "MaxTessEvaluationInputComponents 128\n"
747 "MaxTessEvaluationOutputComponents 128\n"
748 "MaxTessEvaluationTextureImageUnits 16\n"
749 "MaxTessEvaluationUniformComponents 1024\n"
750 "MaxTessPatchComponents 120\n"
751 "MaxPatchVertices 32\n"
752 "MaxTessGenLevel 64\n"
753 "MaxViewports 16\n"
754 "MaxVertexAtomicCounters 0\n"
755 "MaxTessControlAtomicCounters 0\n"
756 "MaxTessEvaluationAtomicCounters 0\n"
757 "MaxGeometryAtomicCounters 0\n"
758 "MaxFragmentAtomicCounters 8\n"
759 "MaxCombinedAtomicCounters 8\n"
760 "MaxAtomicCounterBindings 1\n"
761 "MaxVertexAtomicCounterBuffers 0\n"
762 "MaxTessControlAtomicCounterBuffers 0\n"
763 "MaxTessEvaluationAtomicCounterBuffers 0\n"
764 "MaxGeometryAtomicCounterBuffers 0\n"
765 "MaxFragmentAtomicCounterBuffers 1\n"
766 "MaxCombinedAtomicCounterBuffers 1\n"
767 "MaxAtomicCounterBufferSize 16384\n"
768 "MaxTransformFeedbackBuffers 4\n"
769 "MaxTransformFeedbackInterleavedComponents 64\n"
770 "MaxCullDistances 8\n"
771 "MaxCombinedClipAndCullDistances 8\n"
772 "MaxSamples 4\n"
773
774 "nonInductiveForLoops 1\n"
775 "whileLoops 1\n"
776 "doWhileLoops 1\n"
777 "generalUniformIndexing 1\n"
778 "generalAttributeMatrixVectorIndexing 1\n"
779 "generalVaryingIndexing 1\n"
780 "generalSamplerIndexing 1\n"
781 "generalVariableIndexing 1\n"
782 "generalConstantMatrixVectorIndexing 1\n"
783 ;
784
785//
786// *.conf => this is a config file that can set limits/resources
787//
Tony Barbour6918cd52015-04-09 12:58:51 -0600788bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600789{
790 if (name.size() < 5)
791 return false;
792
793 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
794 ConfigFile = name;
795 return true;
796 }
797
798 return false;
799}
800
801//
802// Parse either a .conf file provided by the user or the default string above.
803//
Tony Barbour6918cd52015-04-09 12:58:51 -0600804void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600805{
806 char** configStrings = 0;
807 char* config = 0;
808 if (ConfigFile.size() > 0) {
809 configStrings = ReadFileData(ConfigFile.c_str());
810 if (configStrings)
811 config = *configStrings;
812 else {
813 printf("Error opening configuration file; will instead use the default configuration\n");
814 }
815 }
816
817 if (config == 0) {
818 config = new char[strlen(DefaultConfig) + 1];
819 strcpy(config, DefaultConfig);
820 }
821
822 const char* delims = " \t\n\r";
823 const char* token = strtok(config, delims);
824 while (token) {
825 const char* valueStr = strtok(0, delims);
826 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
827 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
828 return;
829 }
830 int value = atoi(valueStr);
831
832 if (strcmp(token, "MaxLights") == 0)
833 Resources.maxLights = value;
834 else if (strcmp(token, "MaxClipPlanes") == 0)
835 Resources.maxClipPlanes = value;
836 else if (strcmp(token, "MaxTextureUnits") == 0)
837 Resources.maxTextureUnits = value;
838 else if (strcmp(token, "MaxTextureCoords") == 0)
839 Resources.maxTextureCoords = value;
840 else if (strcmp(token, "MaxVertexAttribs") == 0)
841 Resources.maxVertexAttribs = value;
842 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
843 Resources.maxVertexUniformComponents = value;
844 else if (strcmp(token, "MaxVaryingFloats") == 0)
845 Resources.maxVaryingFloats = value;
846 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
847 Resources.maxVertexTextureImageUnits = value;
848 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
849 Resources.maxCombinedTextureImageUnits = value;
850 else if (strcmp(token, "MaxTextureImageUnits") == 0)
851 Resources.maxTextureImageUnits = value;
852 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
853 Resources.maxFragmentUniformComponents = value;
854 else if (strcmp(token, "MaxDrawBuffers") == 0)
855 Resources.maxDrawBuffers = value;
856 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
857 Resources.maxVertexUniformVectors = value;
858 else if (strcmp(token, "MaxVaryingVectors") == 0)
859 Resources.maxVaryingVectors = value;
860 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
861 Resources.maxFragmentUniformVectors = value;
862 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
863 Resources.maxVertexOutputVectors = value;
864 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
865 Resources.maxFragmentInputVectors = value;
866 else if (strcmp(token, "MinProgramTexelOffset") == 0)
867 Resources.minProgramTexelOffset = value;
868 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
869 Resources.maxProgramTexelOffset = value;
870 else if (strcmp(token, "MaxClipDistances") == 0)
871 Resources.maxClipDistances = value;
872 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
873 Resources.maxComputeWorkGroupCountX = value;
874 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
875 Resources.maxComputeWorkGroupCountY = value;
876 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
877 Resources.maxComputeWorkGroupCountZ = value;
878 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
879 Resources.maxComputeWorkGroupSizeX = value;
880 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
881 Resources.maxComputeWorkGroupSizeY = value;
882 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
883 Resources.maxComputeWorkGroupSizeZ = value;
884 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
885 Resources.maxComputeUniformComponents = value;
886 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
887 Resources.maxComputeTextureImageUnits = value;
888 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
889 Resources.maxComputeImageUniforms = value;
890 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
891 Resources.maxComputeAtomicCounters = value;
892 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
893 Resources.maxComputeAtomicCounterBuffers = value;
894 else if (strcmp(token, "MaxVaryingComponents") == 0)
895 Resources.maxVaryingComponents = value;
896 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
897 Resources.maxVertexOutputComponents = value;
898 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
899 Resources.maxGeometryInputComponents = value;
900 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
901 Resources.maxGeometryOutputComponents = value;
902 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
903 Resources.maxFragmentInputComponents = value;
904 else if (strcmp(token, "MaxImageUnits") == 0)
905 Resources.maxImageUnits = value;
906 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
907 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
908 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
909 Resources.maxCombinedShaderOutputResources = value;
910 else if (strcmp(token, "MaxImageSamples") == 0)
911 Resources.maxImageSamples = value;
912 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
913 Resources.maxVertexImageUniforms = value;
914 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
915 Resources.maxTessControlImageUniforms = value;
916 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
917 Resources.maxTessEvaluationImageUniforms = value;
918 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
919 Resources.maxGeometryImageUniforms = value;
920 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
921 Resources.maxFragmentImageUniforms = value;
922 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
923 Resources.maxCombinedImageUniforms = value;
924 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
925 Resources.maxGeometryTextureImageUnits = value;
926 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
927 Resources.maxGeometryOutputVertices = value;
928 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
929 Resources.maxGeometryTotalOutputComponents = value;
930 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
931 Resources.maxGeometryUniformComponents = value;
932 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
933 Resources.maxGeometryVaryingComponents = value;
934 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
935 Resources.maxTessControlInputComponents = value;
936 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
937 Resources.maxTessControlOutputComponents = value;
938 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
939 Resources.maxTessControlTextureImageUnits = value;
940 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
941 Resources.maxTessControlUniformComponents = value;
942 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
943 Resources.maxTessControlTotalOutputComponents = value;
944 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
945 Resources.maxTessEvaluationInputComponents = value;
946 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
947 Resources.maxTessEvaluationOutputComponents = value;
948 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
949 Resources.maxTessEvaluationTextureImageUnits = value;
950 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
951 Resources.maxTessEvaluationUniformComponents = value;
952 else if (strcmp(token, "MaxTessPatchComponents") == 0)
953 Resources.maxTessPatchComponents = value;
954 else if (strcmp(token, "MaxPatchVertices") == 0)
955 Resources.maxPatchVertices = value;
956 else if (strcmp(token, "MaxTessGenLevel") == 0)
957 Resources.maxTessGenLevel = value;
958 else if (strcmp(token, "MaxViewports") == 0)
959 Resources.maxViewports = value;
960 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
961 Resources.maxVertexAtomicCounters = value;
962 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
963 Resources.maxTessControlAtomicCounters = value;
964 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
965 Resources.maxTessEvaluationAtomicCounters = value;
966 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
967 Resources.maxGeometryAtomicCounters = value;
968 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
969 Resources.maxFragmentAtomicCounters = value;
970 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
971 Resources.maxCombinedAtomicCounters = value;
972 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
973 Resources.maxAtomicCounterBindings = value;
974 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
975 Resources.maxVertexAtomicCounterBuffers = value;
976 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
977 Resources.maxTessControlAtomicCounterBuffers = value;
978 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
979 Resources.maxTessEvaluationAtomicCounterBuffers = value;
980 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
981 Resources.maxGeometryAtomicCounterBuffers = value;
982 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
983 Resources.maxFragmentAtomicCounterBuffers = value;
984 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
985 Resources.maxCombinedAtomicCounterBuffers = value;
986 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
987 Resources.maxAtomicCounterBufferSize = value;
988 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
989 Resources.maxTransformFeedbackBuffers = value;
990 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
991 Resources.maxTransformFeedbackInterleavedComponents = value;
992 else if (strcmp(token, "MaxCullDistances") == 0)
993 Resources.maxCullDistances = value;
994 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
995 Resources.maxCombinedClipAndCullDistances = value;
996 else if (strcmp(token, "MaxSamples") == 0)
997 Resources.maxSamples = value;
998
999 else if (strcmp(token, "nonInductiveForLoops") == 0)
1000 Resources.limits.nonInductiveForLoops = (value != 0);
1001 else if (strcmp(token, "whileLoops") == 0)
1002 Resources.limits.whileLoops = (value != 0);
1003 else if (strcmp(token, "doWhileLoops") == 0)
1004 Resources.limits.doWhileLoops = (value != 0);
1005 else if (strcmp(token, "generalUniformIndexing") == 0)
1006 Resources.limits.generalUniformIndexing = (value != 0);
1007 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1008 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1009 else if (strcmp(token, "generalVaryingIndexing") == 0)
1010 Resources.limits.generalVaryingIndexing = (value != 0);
1011 else if (strcmp(token, "generalSamplerIndexing") == 0)
1012 Resources.limits.generalSamplerIndexing = (value != 0);
1013 else if (strcmp(token, "generalVariableIndexing") == 0)
1014 Resources.limits.generalVariableIndexing = (value != 0);
1015 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1016 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1017 else
1018 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1019
1020 token = strtok(0, delims);
1021 }
1022 if (configStrings)
1023 FreeFileData(configStrings);
1024}
1025
Tony Barbour6918cd52015-04-09 12:58:51 -06001026void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001027{
1028 if (m_compile_options & EOptionRelaxedErrors)
1029 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1030 if (m_compile_options & EOptionIntermediate)
1031 messages = (EShMessages)(messages | EShMsgAST);
1032 if (m_compile_options & EOptionSuppressWarnings)
1033 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1034}
1035
1036//
1037// Malloc a string of sufficient size and read a string into it.
1038//
Tony Barbour6918cd52015-04-09 12:58:51 -06001039char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001040{
1041 FILE *in;
1042 #if defined(_WIN32) && defined(__GNUC__)
1043 in = fopen(fileName, "r");
1044 int errorCode = in ? 0 : 1;
1045 #else
1046 int errorCode = fopen_s(&in, fileName, "r");
1047 #endif
1048
1049 char *fdata;
1050 int count = 0;
1051 const int maxSourceStrings = 5;
1052 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1053
1054 if (errorCode) {
1055 printf("Error: unable to open input file: %s\n", fileName);
1056 return 0;
1057 }
1058
1059 while (fgetc(in) != EOF)
1060 count++;
1061
1062 fseek(in, 0, SEEK_SET);
1063
1064 if (!(fdata = (char*)malloc(count+2))) {
1065 printf("Error allocating memory\n");
1066 return 0;
1067 }
1068 if (fread(fdata,1,count, in)!=count) {
1069 printf("Error reading input file: %s\n", fileName);
1070 return 0;
1071 }
1072 fdata[count] = '\0';
1073 fclose(in);
1074 if (count == 0) {
1075 return_data[0]=(char*)malloc(count+2);
1076 return_data[0][0]='\0';
1077 m_num_shader_strings = 0;
1078 return return_data;
1079 } else
1080 m_num_shader_strings = 1;
1081
1082 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1083 int ptr_len=0,i=0;
1084 while(count>0){
1085 return_data[i]=(char*)malloc(len+2);
1086 memcpy(return_data[i],fdata+ptr_len,len);
1087 return_data[i][len]='\0';
1088 count-=(len);
1089 ptr_len+=(len);
1090 if(count<len){
1091 if(count==0){
1092 m_num_shader_strings=(i+1);
1093 break;
1094 }
1095 len = count;
1096 }
1097 ++i;
1098 }
1099 return return_data;
1100}
1101
Tony Barbour6918cd52015-04-09 12:58:51 -06001102void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001103{
1104 for(int i=0;i<m_num_shader_strings;i++)
1105 free(data[i]);
1106}
1107
1108//
1109// Deduce the language from the filename. Files must end in one of the
1110// following extensions:
1111//
1112// .vert = vertex
1113// .tesc = tessellation control
1114// .tese = tessellation evaluation
1115// .geom = geometry
1116// .frag = fragment
1117// .comp = compute
1118//
Tony Barbour6918cd52015-04-09 12:58:51 -06001119EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001120{
1121 size_t ext = name.rfind('.');
1122 if (ext == std::string::npos) {
1123 return EShLangVertex;
1124 }
1125
1126 std::string suffix = name.substr(ext + 1, std::string::npos);
1127 if (suffix == "vert")
1128 return EShLangVertex;
1129 else if (suffix == "tesc")
1130 return EShLangTessControl;
1131 else if (suffix == "tese")
1132 return EShLangTessEvaluation;
1133 else if (suffix == "geom")
1134 return EShLangGeometry;
1135 else if (suffix == "frag")
1136 return EShLangFragment;
1137 else if (suffix == "comp")
1138 return EShLangCompute;
1139
1140 return EShLangVertex;
1141}
1142
1143//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001144// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001145//
Tony Barbourd1c35722015-04-16 15:59:00 -06001146EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001147{
1148 switch (shader_type) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001149 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001150 return EShLangVertex;
1151
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001152 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001153 return EShLangTessControl;
1154
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001155 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001156 return EShLangTessEvaluation;
1157
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001158 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001159 return EShLangGeometry;
1160
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001161 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001162 return EShLangFragment;
1163
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001164 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001165 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001166
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001167 default:
1168 return EShLangVertex;
1169 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001170}
1171
1172
1173//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001174// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001175// Return value of false means an error was encountered.
1176//
Tony Barbourd1c35722015-04-16 15:59:00 -06001177bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001178 const char *pshader,
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001179 std::vector<unsigned int> &spv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001180{
1181 glslang::TProgram& program = *new glslang::TProgram;
1182 const char *shaderStrings[1];
1183
1184 // TODO: Do we want to load a special config file depending on the
1185 // shader source? Optional name maybe?
1186 // SetConfigFile(fileName);
1187
1188 ProcessConfigFile();
1189
1190 EShMessages messages = EShMsgDefault;
1191 SetMessageOptions(messages);
1192
1193 EShLanguage stage = FindLanguage(shader_type);
1194 glslang::TShader* shader = new glslang::TShader(stage);
1195
1196 shaderStrings[0] = pshader;
1197 shader->setStrings(shaderStrings, 1);
1198
1199 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1200
Cody Northrop195d6622014-11-03 12:54:37 -07001201 if (! (m_compile_options & EOptionSuppressInfolog)) {
1202 puts(shader->getInfoLog());
1203 puts(shader->getInfoDebugLog());
1204 }
1205
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001206 return false; // something didn't work
1207 }
1208
1209 program.addShader(shader);
1210
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001211
1212 //
1213 // Program-level processing...
1214 //
1215
Cody Northrop195d6622014-11-03 12:54:37 -07001216 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001217
Cody Northrop195d6622014-11-03 12:54:37 -07001218 if (! (m_compile_options & EOptionSuppressInfolog)) {
1219 puts(shader->getInfoLog());
1220 puts(shader->getInfoDebugLog());
1221 }
1222
1223 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001224 }
1225
1226 if (m_compile_options & EOptionDumpReflection) {
1227 program.buildReflection();
1228 program.dumpReflection();
1229 }
1230
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001231 glslang::GlslangToSpv(*program.getIntermediate(stage), spv);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001232
1233 return true;
1234}
1235
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001236
1237
Tony Barbour6918cd52015-04-09 12:58:51 -06001238VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001239 m_width( 0 ),
1240 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001241 m_data( NULL ),
Tony Barbour96db8822015-02-25 12:28:39 -07001242 m_presentableImage( NULL ),
1243 m_presentableMemory( NULL),
Chia-I Wu837f9952014-12-15 23:29:34 +08001244 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001245{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001246}
1247
Tony Barbour6918cd52015-04-09 12:58:51 -06001248VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001249{
1250
1251}
1252
Tony Barbour6918cd52015-04-09 12:58:51 -06001253VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001254{
1255 m_title = copyin.m_title;
1256 m_width = copyin.m_width;
1257 m_height = copyin.m_height;
1258 m_data_size = copyin.m_data_size;
1259 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
Tony Barbour96db8822015-02-25 12:28:39 -07001260 m_presentableImage = copyin.m_presentableImage;
1261 m_presentableMemory = copyin.m_presentableMemory;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001262}
1263
Tony Barbour6918cd52015-04-09 12:58:51 -06001264ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001265{
Tony Barbour6918cd52015-04-09 12:58:51 -06001266 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1267 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001268 return output;
1269}
1270
Tony Barbour6918cd52015-04-09 12:58:51 -06001271VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001272{
1273 m_title = rhs.m_title;
1274 m_width = rhs.m_width;
1275 m_height = rhs.m_height;
1276 m_data_size = rhs.m_data_size;
1277 m_data = rhs.m_data;
Tony Barbour96db8822015-02-25 12:28:39 -07001278 m_presentableImage = rhs.m_presentableImage;
1279 m_presentableMemory = rhs.m_presentableMemory;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001280 return *this;
1281}
1282
Tony Barbour6918cd52015-04-09 12:58:51 -06001283int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001284{
1285 if( this->m_data != rhs.m_data) return 0;
1286 return 1;
1287}
1288
1289// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001290int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001291{
1292 if( this->m_data_size < rhs.m_data_size ) return 1;
1293 return 0;
1294}
1295