blob: bc2875cc7b1bec791d44091472e888b2a17f9d23 [file] [log] [blame]
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001// VK tests
Courtney Goeltzenleuchterd0d7ccc2014-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 Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060023#include "vktestframework.h"
24#include "vkrenderframework.h"
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -060025#include "GL/freeglut_std.h"
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -060026//#include "ShaderLang.h"
Steve Kcd2c3012015-03-17 09:40:23 -060027#include "GlslangToSpv.h"
Tony Barbour772c5ef2014-12-10 17:00:20 -070028#include <limits.h>
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -060029#include <math.h>
Chia-I Wu3d9ebb22014-12-02 11:54:24 +080030#include <wand/MagickWand.h>
Chia-I Wu5b66aa52015-04-16 22:02:10 +080031#include <xcb/xcb.h>
32#include <vk_wsi_lunarg.h>
Courtney Goeltzenleuchter94192032014-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 Northropacfb0492015-03-17 15:55:58 -060048 EOptionSpv = 0x800,
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -060049 EOptionDefaultDesktop = 0x1000,
50};
51
Chia-I Wu5b66aa52015-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;
73 std::list<VkTestImageRecord> m_images;
74
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 Goeltzenleuchter94192032014-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600117
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600118// Set up environment for GLSL compiler
119// Must be done once per process
120void TestEnvironment::SetUp()
121{
Cody Northropacfb0492015-03-17 15:55:58 -0600122 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600123 glslang::InitializeProcess();
Chia-I Wu1c9869e2014-12-28 14:27:28 +0800124
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600125 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600126}
127
128void TestEnvironment::TearDown()
129{
130 glslang::FinalizeProcess();
131}
132
Tony Barbour01999182015-04-09 12:58:51 -0600133VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600134 m_compile_options( 0 ),
135 m_num_shader_strings( 0 )
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600136{
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600137
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600138}
139
Tony Barbour01999182015-04-09 12:58:51 -0600140VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600141{
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600142
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600143}
144
145// Define all the static elements
Tony Barbour01999182015-04-09 12:58:51 -0600146bool VkTestFramework::m_show_images = false;
147bool VkTestFramework::m_save_images = false;
148bool VkTestFramework::m_compare_images = false;
Tony Barbour3a5cda02015-04-02 15:48:24 -0600149#ifdef _WIN32
Tony Barbour01999182015-04-09 12:58:51 -0600150bool VkTestFramework::m_use_spv = false;
Tony Barbour3a5cda02015-04-02 15:48:24 -0600151#else
Tony Barbour01999182015-04-09 12:58:51 -0600152bool VkTestFramework::m_use_spv = true;
Tony Barbour3a5cda02015-04-02 15:48:24 -0600153#endif
Tony Barbour01999182015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600158int m_display_image_idx = 0;
159
Tony Barbour01999182015-04-09 12:58:51 -0600160void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchterd0d7ccc2014-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 Northropacfb0492015-03-17 15:55:58 -0600174 if (strncmp("--use-SPV", argv[i], 13) == 0) {
175 m_use_spv = true;
Courtney Goeltzenleuchter54d02cb2014-10-09 09:13:56 -0600176 continue;
177 }
178
Cody Northropacfb0492015-03-17 15:55:58 -0600179 if (strncmp("--no-SPV", argv[i], 13) == 0) {
180 m_use_spv = false;
Courtney Goeltzenleuchter59d21fe2014-10-31 14:13:33 -0600181 continue;
182 }
183
Tony Barbour32f368c2014-10-30 14:29:04 -0600184 if (strncmp("--compare-images", argv[i], 16) == 0) {
185 m_compare_images = true;
186 continue;
187 }
188
Courtney Goeltzenleuchterd0d7ccc2014-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 Barbour0e4235d2014-12-11 09:52:49 -0700193 if (strncmp("--help", argv[i], 6) == 0 || strncmp("-h", argv[i], 2) == 0) {
Courtney Goeltzenleuchterb7f26e02014-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 Barbour0e4235d2014-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 Goeltzenleuchterb7f26e02014-12-02 13:13:10 -0700206 "\t\tSignal test failure if different.\n");
Cody Northropacfb0492015-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 Barbour772c5ef2014-12-10 17:00:20 -0700211 exit(0);
Courtney Goeltzenleuchterb7f26e02014-12-02 13:13:10 -0700212 }
213
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600214 argv[n] = argv[i];
215 n++;
216 }
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600217}
218
Tony Barbour01999182015-04-09 12:58:51 -0600219void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600220{
221 string filename;
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600222 VkResult err;
Tony Barbouredc49d92015-04-02 14:02:33 -0600223 int x, y;
Tony Barbour01999182015-04-09 12:58:51 -0600224 VkImageObj displayImage(image->device());
Tony Barbouredc49d92015-04-02 14:02:33 -0600225
Tony Barbour8205d902015-04-16 15:59:00 -0600226 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, VK_IMAGE_TILING_LINEAR);
Tony Barbouredc49d92015-04-02 14:02:33 -0600227 displayImage.CopyImage(*image);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600228
229 filename.append(basename);
230 filename.append(".ppm");
231
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600232 const VkImageSubresource sr = {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600233 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600234 };
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600235 VkSubresourceLayout sr_layout;
Chia-I Wu54ed0792014-12-27 14:14:50 +0800236 size_t data_size = sizeof(sr_layout);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600237
Mike Stroyan230e6252015-04-17 12:36:38 -0600238 err = vkGetImageSubresourceInfo(image->device()->device(), image->image(), &sr,
Tony Barbour8205d902015-04-16 15:59:00 -0600239 VK_SUBRESOURCE_INFO_TYPE_LAYOUT,
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600240 &data_size, &sr_layout);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600241 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600242 ASSERT_EQ(data_size, sizeof(sr_layout));
243
Tony Barbouredc49d92015-04-02 14:02:33 -0600244 char *ptr;
245 ptr = (char *) displayImage.map();
Courtney Goeltzenleuchterd0d7ccc2014-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 Barbouredc49d92015-04-02 14:02:33 -0600252 file << displayImage.width() << "\n";
253 file << displayImage.height() << "\n";
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600254 file << 255 << "\n";
255
Tony Barbouredc49d92015-04-02 14:02:33 -0600256 for (y = 0; y < displayImage.height(); y++) {
Tony Barboure2668672015-02-25 11:25:11 -0700257 const int *row = (const int *) ptr;
258 int swapped;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600259
Tony Barbour8205d902015-04-16 15:59:00 -0600260 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboure2668672015-02-25 11:25:11 -0700261 {
Tony Barbouredc49d92015-04-02 14:02:33 -0600262 for (x = 0; x < displayImage.width(); x++) {
Tony Barboure2668672015-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 Barbour8205d902015-04-16 15:59:00 -0600268 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboure2668672015-02-25 11:25:11 -0700269 {
Tony Barbouredc49d92015-04-02 14:02:33 -0600270 for (x = 0; x < displayImage.width(); x++) {
Tony Barboure2668672015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600278 }
279
280 ptr += sr_layout.rowPitch;
281 }
282
283 file.close();
Tony Barbouredc49d92015-04-02 14:02:33 -0600284 displayImage.unmap();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600285}
286
Tony Barbour01999182015-04-09 12:58:51 -0600287void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour32f368c2014-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 Barbour772c5ef2014-12-10 17:00:20 -0700294 char testimage[256],golden[PATH_MAX+256],golddir[PATH_MAX] = "./golden";
Tony Barbour32f368c2014-10-30 14:29:04 -0600295 double differenz;
296
Tony Barbour772c5ef2014-12-10 17:00:20 -0700297 if (getenv("RENDERTEST_GOLDEN_DIR"))
298 {
299 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
300 }
301
Tony Barbour32f368c2014-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 Barbour772c5ef2014-12-10 17:00:20 -0700311 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour32f368c2014-10-30 14:29:04 -0600312 status=MagickReadImage(magick_wand_2,golden);
313 ASSERT_TRUE(status) << "Unable to open file: " << golden;
314
Tony Barbour32f368c2014-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 Goeltzenleuchterdfa97b82014-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 Barbour32f368c2014-10-30 14:29:04 -0600338}
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600339
Tony Barbour01999182015-04-09 12:58:51 -0600340void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600341{
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600342 VkResult err;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600343
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600344 const VkImageSubresource sr = {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600345 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600346 };
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600347 VkSubresourceLayout sr_layout;
Chia-I Wu54ed0792014-12-27 14:14:50 +0800348 size_t data_size = sizeof(sr_layout);
Tony Barbour01999182015-04-09 12:58:51 -0600349 VkTestImageRecord record;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600350
351 if (!m_show_images) return;
352
Mike Stroyan230e6252015-04-17 12:36:38 -0600353 err = vkGetImageSubresourceInfo( image->device()->device(), image->image(), &sr, VK_SUBRESOURCE_INFO_TYPE_LAYOUT,
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600354 &data_size, &sr_layout);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600355 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600356 ASSERT_EQ(data_size, sizeof(sr_layout));
357
Tony Barbouref20d322015-02-25 12:28:39 -0700358 char *ptr;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600359
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -0600360 err = image->MapMemory( (void **) &ptr );
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600361 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600362
363 ptr += sr_layout.offset;
364
Courtney Goeltzenleuchterd0d7ccc2014-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600375 err = image->UnmapMemory();
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600376 ASSERT_VK_SUCCESS( err );
Tony Barbouref20d322015-02-25 12:28:39 -0700377
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600378}
379
Tony Barbour01999182015-04-09 12:58:51 -0600380void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour32f368c2014-10-30 14:29:04 -0600381{
Courtney Goeltzenleuchtercd5ed1e2015-04-02 14:17:44 -0600382 for (int32_t i = 0; i < images.size(); i++) {
383 RecordImage(images[i]);
Tony Barbour32f368c2014-10-30 14:29:04 -0600384 }
385}
386
Tony Barbour01999182015-04-09 12:58:51 -0600387void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600388{
389 const ::testing::TestInfo* const test_info =
390 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour32f368c2014-10-30 14:29:04 -0600391 ostringstream filestream;
392 string filename;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600393
Tony Barbour32f368c2014-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 Barboura48b0812014-11-18 17:02:36 -0700399 m_frameNum = 2;
400 filename = filestream.str();
Tony Barbour32f368c2014-10-30 14:29:04 -0600401 }
402 else {
403 filestream << test_info->name() << "-" << m_frameNum;
404 m_frameNum++;
Tony Barboura48b0812014-11-18 17:02:36 -0700405 filename = filestream.str();
Tony Barbour32f368c2014-10-30 14:29:04 -0600406 }
407
Tony Barbour32f368c2014-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600415 }
416
417 if (m_show_images) {
Courtney Goeltzenleuchtere5409342014-10-08 14:26:40 -0600418 Show(test_info->name(), image);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600419 }
420}
421
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800422TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
423 m_device(device),
Courtney Goeltzenleuchterdd745fd2015-03-05 16:47:18 -0700424 m_queue(*m_device.graphics_queues()[0]),
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600425 m_cmdbuf(m_device, vk_testing::CmdBuffer::create_info(m_device.graphics_queue_node_index_))
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600426{
Tony Barbouref20d322015-02-25 12:28:39 -0700427 m_quit = false;
428 m_pause = false;
429 m_width = 0;
430 m_height = 0;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600431}
432
Tony Barbour01999182015-04-09 12:58:51 -0600433void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600434{
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600435 VkResult err;
Tony Barbouref20d322015-02-25 12:28:39 -0700436
Chia-I Wu5b66aa52015-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 Barbouref20d322015-02-25 12:28:39 -0700441
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800442 xcb_change_property (m_connection,
Tony Barbouref20d322015-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 Wu5b66aa52015-04-16 22:02:10 +0800451 err = vkQueuePresentWSI(m_queue.obj(), &present);
Tony Barbouref20d322015-02-25 12:28:39 -0700452 assert(!err);
453
454 m_queue.wait();
455
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600456}
457
Tony Barbour01999182015-04-09 12:58:51 -0600458void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600459{
Tony Barbour3a5cda02015-04-02 15:48:24 -0600460 uint8_t event_code = event->response_type & 0x7f;
Tony Barbouref20d322015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600469 }
470 break;
Tony Barbouref20d322015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600475
Tony Barbouref20d322015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600501 break;
502 }
Tony Barbouref20d322015-02-25 12:28:39 -0700503}
504
Tony Barbour01999182015-04-09 12:58:51 -0600505void TestFrameworkVkPresent::Run()
Tony Barbouref20d322015-02-25 12:28:39 -0700506{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800507 xcb_flush(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700508
509 while (! m_quit) {
510 xcb_generic_event_t *event;
511
512 if (m_pause) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800513 event = xcb_wait_for_event(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700514 } else {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800515 event = xcb_poll_for_event(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700516 }
517 if (event) {
518 HandleEvent(event);
519 free(event);
520 }
521 }
522}
523
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800524void TestFrameworkVkPresent::CreateSwapChain()
Tony Barbouref20d322015-02-25 12:28:39 -0700525{
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600526 VkResult err;
Tony Barbouref20d322015-02-25 12:28:39 -0700527
Chia-I Wu5b66aa52015-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 Barbouref20d322015-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 Barbouref20d322015-02-25 12:28:39 -0700556 void *dest_ptr;
557
Chia-I Wu5b66aa52015-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 Barbouref20d322015-02-25 12:28:39 -0700560
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600561 vk_testing::Buffer buf;
Tony Barbour8205d902015-04-16 15:59:00 -0600562 buf.init(m_device, (VkDeviceSize) m_display_image->m_data_size);
Tony Barbouref20d322015-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 Goeltzenleuchter382489d2015-04-10 08:34:15 -0600569 VkBufferImageCopy region = {};
Tony Barbouref20d322015-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 Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600574 vkCmdCopyBufferToImage(m_cmdbuf.obj(),
Courtney Goeltzenleuchter51cbf302015-03-25 11:25:10 -0600575 buf.obj(),
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600576 m_display_image->m_presentableImage, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
Courtney Goeltzenleuchter51cbf302015-03-25 11:25:10 -0600577 1, &region);
Tony Barbouref20d322015-02-25 12:28:39 -0700578 m_cmdbuf.end();
579
Courtney Goeltzenleuchter46962942015-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 Barbouref20d322015-02-25 12:28:39 -0700582
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600583 VkCmdBuffer cmdBufs[1];
Tony Barbouref20d322015-02-25 12:28:39 -0700584 cmdBufs[0] = m_cmdbuf.obj();
585
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600586 vkQueueSubmit(m_queue.obj(), 1, cmdBufs, NULL);
Tony Barbouref20d322015-02-25 12:28:39 -0700587 m_queue.wait();
588
Courtney Goeltzenleuchter46962942015-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 Barbouref20d322015-02-25 12:28:39 -0700591
Tony Barbouref20d322015-02-25 12:28:39 -0700592 ++m_display_image;
Tony Barbouref20d322015-02-25 12:28:39 -0700593 }
594
595 m_display_image = m_images.begin();
596}
597
Tony Barbour01999182015-04-09 12:58:51 -0600598void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn)
Tony Barbouref20d322015-02-25 12:28:39 -0700599{
600 m_images = imagesIn;
601}
602
Tony Barbour01999182015-04-09 12:58:51 -0600603void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbouref20d322015-02-25 12:28:39 -0700604{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800605 const xcb_setup_t *setup;
606 xcb_screen_iterator_t iter;
607 int scr;
Tony Barbouref20d322015-02-25 12:28:39 -0700608 uint32_t value_mask, value_list[32];
609
Chia-I Wu5b66aa52015-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 Barbouref20d322015-02-25 12:28:39 -0700628
629 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800630 value_list[0] = m_screen->black_pixel;
Tony Barbouref20d322015-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 Wu5b66aa52015-04-16 22:02:10 +0800635 xcb_create_window(m_connection,
Tony Barbouref20d322015-02-25 12:28:39 -0700636 XCB_COPY_FROM_PARENT,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800637 m_window, m_screen->root,
Tony Barbouref20d322015-02-25 12:28:39 -0700638 0, 0, m_width, m_height, 0,
639 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800640 m_screen->root_visual,
Tony Barbouref20d322015-02-25 12:28:39 -0700641 value_mask, value_list);
642
643 /* Magic code that will send notification when window is destroyed */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800644 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbouref20d322015-02-25 12:28:39 -0700645 "WM_PROTOCOLS");
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800646 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbouref20d322015-02-25 12:28:39 -0700647
Chia-I Wu5b66aa52015-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 Barbouref20d322015-02-25 12:28:39 -0700650
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800651 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbouref20d322015-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 Wu5b66aa52015-04-16 22:02:10 +0800656 xcb_map_window(m_connection, m_window);
Tony Barbouref20d322015-02-25 12:28:39 -0700657}
658
Tony Barbour01999182015-04-09 12:58:51 -0600659void TestFrameworkVkPresent::TearDown()
Tony Barbouref20d322015-02-25 12:28:39 -0700660{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800661 vkDestroySwapChainWSI(m_swap_chain);
662 xcb_destroy_window(m_connection, m_window);
663 xcb_disconnect(m_connection);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600664}
665
Tony Barbour01999182015-04-09 12:58:51 -0600666void VkTestFramework::Finish()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600667{
668 if (m_images.size() == 0) return;
669
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800670 vk_testing::Environment env;
671 env.SetUp();
Tony Barbouref20d322015-02-25 12:28:39 -0700672 {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800673 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbouref20d322015-02-25 12:28:39 -0700674
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600675 vkPresent.InitPresentFramework(m_images);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600676 vkPresent.CreateMyWindow();
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800677 vkPresent.CreateSwapChain();
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600678 vkPresent.Run();
679 vkPresent.TearDown();
Tony Barbouref20d322015-02-25 12:28:39 -0700680 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800681 env.TearDown();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600682}
683
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600684//
Courtney Goeltzenleuchter94192032014-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 Barbour01999182015-04-09 12:58:51 -0600788bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter94192032014-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 Barbour01999182015-04-09 12:58:51 -0600804void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter94192032014-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 Barbour01999182015-04-09 12:58:51 -06001026void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter94192032014-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 Barbour01999182015-04-09 12:58:51 -06001039char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter94192032014-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 Barbour01999182015-04-09 12:58:51 -06001102void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter94192032014-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 Barbour01999182015-04-09 12:58:51 -06001119EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter94192032014-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 Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001144// Convert VK shader type to compiler's
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001145//
Tony Barbour8205d902015-04-16 15:59:00 -06001146EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001147{
1148 switch (shader_type) {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001149 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001150 return EShLangVertex;
1151
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001152 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001153 return EShLangTessControl;
1154
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001155 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001156 return EShLangTessEvaluation;
1157
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001158 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001159 return EShLangGeometry;
1160
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001161 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001162 return EShLangFragment;
1163
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001164 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001165 return EShLangCompute;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001166
Chia-I Wubbdeacc2014-12-15 23:50:11 +08001167 default:
1168 return EShLangVertex;
1169 }
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001170}
1171
1172
1173//
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001174// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001175// Return value of false means an error was encountered.
1176//
Tony Barbour8205d902015-04-16 15:59:00 -06001177bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001178 const char *pshader,
Cody Northropacfb0492015-03-17 15:55:58 -06001179 std::vector<unsigned int> &spv)
Courtney Goeltzenleuchter94192032014-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 Northropad306f02014-11-03 12:54:37 -07001201 if (! (m_compile_options & EOptionSuppressInfolog)) {
1202 puts(shader->getInfoLog());
1203 puts(shader->getInfoDebugLog());
1204 }
1205
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001206 return false; // something didn't work
1207 }
1208
1209 program.addShader(shader);
1210
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001211
1212 //
1213 // Program-level processing...
1214 //
1215
Cody Northropad306f02014-11-03 12:54:37 -07001216 if (! program.link(messages)) {
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001217
Cody Northropad306f02014-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 Goeltzenleuchter94192032014-10-03 09:53:32 -06001224 }
1225
1226 if (m_compile_options & EOptionDumpReflection) {
1227 program.buildReflection();
1228 program.dumpReflection();
1229 }
1230
Cody Northropacfb0492015-03-17 15:55:58 -06001231 glslang::GlslangToSpv(*program.getIntermediate(stage), spv);
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001232
1233 return true;
1234}
1235
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001236
1237
Tony Barbour01999182015-04-09 12:58:51 -06001238VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001239 m_width( 0 ),
1240 m_height( 0 ),
Chia-I Wub2c2dea2014-12-15 23:29:34 +08001241 m_data( NULL ),
Tony Barbouref20d322015-02-25 12:28:39 -07001242 m_presentableImage( NULL ),
1243 m_presentableMemory( NULL),
Chia-I Wub2c2dea2014-12-15 23:29:34 +08001244 m_data_size( 0 )
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001245{
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001246}
1247
Tony Barbour01999182015-04-09 12:58:51 -06001248VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001249{
1250
1251}
1252
Tony Barbour01999182015-04-09 12:58:51 -06001253VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchterd0d7ccc2014-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 Barbouref20d322015-02-25 12:28:39 -07001260 m_presentableImage = copyin.m_presentableImage;
1261 m_presentableMemory = copyin.m_presentableMemory;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001262}
1263
Tony Barbour01999182015-04-09 12:58:51 -06001264ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001265{
Tony Barbour01999182015-04-09 12:58:51 -06001266 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1267 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001268 return output;
1269}
1270
Tony Barbour01999182015-04-09 12:58:51 -06001271VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchterd0d7ccc2014-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 Barbouref20d322015-02-25 12:28:39 -07001278 m_presentableImage = rhs.m_presentableImage;
1279 m_presentableMemory = rhs.m_presentableMemory;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001280 return *this;
1281}
1282
Tony Barbour01999182015-04-09 12:58:51 -06001283int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchterd0d7ccc2014-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 Barbour01999182015-04-09 12:58:51 -06001290int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001291{
1292 if( this->m_data_size < rhs.m_data_size ) return 1;
1293 return 0;
1294}
1295