blob: 17c4c8f880c6b3a644db722d9ddc8d478f2529cf [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;
Courtney Goeltzenleuchterec69b9c2015-04-22 10:09:35 -060073 std::list<VkTestImageRecord> m_images;
Chia-I Wu5b66aa52015-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 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 Barbour94310562015-04-22 15:10:33 -0600225 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbouredc49d92015-04-02 14:02:33 -0600226
Tony Barbour94310562015-04-22 15:10:33 -0600227 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, VK_IMAGE_TILING_LINEAR, reqs);
Tony Barbouredc49d92015-04-02 14:02:33 -0600228 displayImage.CopyImage(*image);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600229
230 filename.append(basename);
231 filename.append(".ppm");
232
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600233 const VkImageSubresource sr = {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600234 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600235 };
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600236 VkSubresourceLayout sr_layout;
Chia-I Wu54ed0792014-12-27 14:14:50 +0800237 size_t data_size = sizeof(sr_layout);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600238
Mike Stroyan230e6252015-04-17 12:36:38 -0600239 err = vkGetImageSubresourceInfo(image->device()->device(), image->image(), &sr,
Tony Barbour8205d902015-04-16 15:59:00 -0600240 VK_SUBRESOURCE_INFO_TYPE_LAYOUT,
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600241 &data_size, &sr_layout);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600242 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600243 ASSERT_EQ(data_size, sizeof(sr_layout));
244
Tony Barbouredc49d92015-04-02 14:02:33 -0600245 char *ptr;
246 ptr = (char *) displayImage.map();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600247 ptr += sr_layout.offset;
248
249 ofstream file (filename.c_str());
250 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
251
252 file << "P6\n";
Tony Barbouredc49d92015-04-02 14:02:33 -0600253 file << displayImage.width() << "\n";
254 file << displayImage.height() << "\n";
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600255 file << 255 << "\n";
256
Tony Barbouredc49d92015-04-02 14:02:33 -0600257 for (y = 0; y < displayImage.height(); y++) {
Tony Barboure2668672015-02-25 11:25:11 -0700258 const int *row = (const int *) ptr;
259 int swapped;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600260
Tony Barbour8205d902015-04-16 15:59:00 -0600261 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboure2668672015-02-25 11:25:11 -0700262 {
Tony Barbouredc49d92015-04-02 14:02:33 -0600263 for (x = 0; x < displayImage.width(); x++) {
Tony Barboure2668672015-02-25 11:25:11 -0700264 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
265 file.write((char *) &swapped, 3);
266 row++;
267 }
268 }
Tony Barbour8205d902015-04-16 15:59:00 -0600269 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboure2668672015-02-25 11:25:11 -0700270 {
Tony Barbouredc49d92015-04-02 14:02:33 -0600271 for (x = 0; x < displayImage.width(); x++) {
Tony Barboure2668672015-02-25 11:25:11 -0700272 file.write((char *) row, 3);
273 row++;
274 }
275 }
276 else {
277 printf("Unrecognized image format - will not write image files");
278 break;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600279 }
280
281 ptr += sr_layout.rowPitch;
282 }
283
284 file.close();
Tony Barbouredc49d92015-04-02 14:02:33 -0600285 displayImage.unmap();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600286}
287
Tony Barbour01999182015-04-09 12:58:51 -0600288void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour32f368c2014-10-30 14:29:04 -0600289{
290
291 MagickWand *magick_wand_1;
292 MagickWand *magick_wand_2;
293 MagickWand *compare_wand;
294 MagickBooleanType status;
Tony Barbour772c5ef2014-12-10 17:00:20 -0700295 char testimage[256],golden[PATH_MAX+256],golddir[PATH_MAX] = "./golden";
Tony Barbour32f368c2014-10-30 14:29:04 -0600296 double differenz;
297
Tony Barbour772c5ef2014-12-10 17:00:20 -0700298 if (getenv("RENDERTEST_GOLDEN_DIR"))
299 {
300 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
301 }
302
Tony Barbour32f368c2014-10-30 14:29:04 -0600303 MagickWandGenesis();
304 magick_wand_1=NewMagickWand();
305 sprintf(testimage,"%s.ppm",basename);
306 status=MagickReadImage(magick_wand_1,testimage);
307 ASSERT_TRUE(status) << "Unable to open file: " << testimage;
308
309
310 MagickWandGenesis();
311 magick_wand_2=NewMagickWand();
Tony Barbour772c5ef2014-12-10 17:00:20 -0700312 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour32f368c2014-10-30 14:29:04 -0600313 status=MagickReadImage(magick_wand_2,golden);
314 ASSERT_TRUE(status) << "Unable to open file: " << golden;
315
Tony Barbour32f368c2014-10-30 14:29:04 -0600316 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
317 if (differenz != 0.0)
318 {
319 char difference[256];
320
321 sprintf(difference,"%s-diff.ppm",basename);
322 status = MagickWriteImage(compare_wand, difference);
323 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
324 }
325 DestroyMagickWand(compare_wand);
326
327 DestroyMagickWand(magick_wand_1);
328 DestroyMagickWand(magick_wand_2);
329 MagickWandTerminus();
Courtney Goeltzenleuchterdfa97b82014-12-05 15:41:02 -0700330
331 if (differenz == 0.0)
332 {
333 /*
334 * If test image and golden image match, we do not need to
335 * keep around the test image.
336 */
337 remove(testimage);
338 }
Tony Barbour32f368c2014-10-30 14:29:04 -0600339}
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600340
Tony Barbour01999182015-04-09 12:58:51 -0600341void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600342{
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600343 VkResult err;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600344
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600345 const VkImageSubresource sr = {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600346 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600347 };
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600348 VkSubresourceLayout sr_layout;
Chia-I Wu54ed0792014-12-27 14:14:50 +0800349 size_t data_size = sizeof(sr_layout);
Tony Barbour01999182015-04-09 12:58:51 -0600350 VkTestImageRecord record;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600351
352 if (!m_show_images) return;
353
Mike Stroyan230e6252015-04-17 12:36:38 -0600354 err = vkGetImageSubresourceInfo( image->device()->device(), image->image(), &sr, VK_SUBRESOURCE_INFO_TYPE_LAYOUT,
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600355 &data_size, &sr_layout);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600356 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600357 ASSERT_EQ(data_size, sizeof(sr_layout));
358
Tony Barbouref20d322015-02-25 12:28:39 -0700359 char *ptr;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600360
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -0600361 err = image->MapMemory( (void **) &ptr );
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600362 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600363
364 ptr += sr_layout.offset;
365
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600366 record.m_title.append(comment);
367 record.m_width = image->width();
368 record.m_height = image->height();
369 // TODO: Need to make this more robust to handle different image formats
370 record.m_data_size = image->width()*image->height()*4;
371 record.m_data = malloc(record.m_data_size);
372 memcpy(record.m_data, ptr, record.m_data_size);
373 m_images.push_back(record);
374 m_display_image = --m_images.end();
375
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600376 err = image->UnmapMemory();
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600377 ASSERT_VK_SUCCESS( err );
Tony Barbouref20d322015-02-25 12:28:39 -0700378
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600379}
380
Tony Barbour01999182015-04-09 12:58:51 -0600381void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour32f368c2014-10-30 14:29:04 -0600382{
Courtney Goeltzenleuchtercd5ed1e2015-04-02 14:17:44 -0600383 for (int32_t i = 0; i < images.size(); i++) {
384 RecordImage(images[i]);
Tony Barbour32f368c2014-10-30 14:29:04 -0600385 }
386}
387
Tony Barbour01999182015-04-09 12:58:51 -0600388void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600389{
390 const ::testing::TestInfo* const test_info =
391 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour32f368c2014-10-30 14:29:04 -0600392 ostringstream filestream;
393 string filename;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600394
Tony Barbour32f368c2014-10-30 14:29:04 -0600395 m_width = 40;
396
397 if (strcmp(test_info->name(), m_testName.c_str())) {
398 filestream << test_info->name();
399 m_testName.assign(test_info->name());
Tony Barboura48b0812014-11-18 17:02:36 -0700400 m_frameNum = 2;
401 filename = filestream.str();
Tony Barbour32f368c2014-10-30 14:29:04 -0600402 }
403 else {
404 filestream << test_info->name() << "-" << m_frameNum;
405 m_frameNum++;
Tony Barboura48b0812014-11-18 17:02:36 -0700406 filename = filestream.str();
Tony Barbour32f368c2014-10-30 14:29:04 -0600407 }
408
Tony Barbour32f368c2014-10-30 14:29:04 -0600409 // ToDo - scrub string for bad characters
410
411 if (m_save_images || m_compare_images) {
412 WritePPM(filename.c_str(), image);
413 if (m_compare_images) {
414 Compare(filename.c_str(), image);
415 }
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600416 }
417
418 if (m_show_images) {
Courtney Goeltzenleuchtere5409342014-10-08 14:26:40 -0600419 Show(test_info->name(), image);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600420 }
421}
422
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800423TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
424 m_device(device),
Courtney Goeltzenleuchterdd745fd2015-03-05 16:47:18 -0700425 m_queue(*m_device.graphics_queues()[0]),
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600426 m_cmdbuf(m_device, vk_testing::CmdBuffer::create_info(m_device.graphics_queue_node_index_))
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600427{
Tony Barbouref20d322015-02-25 12:28:39 -0700428 m_quit = false;
429 m_pause = false;
430 m_width = 0;
431 m_height = 0;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600432}
433
Tony Barbour01999182015-04-09 12:58:51 -0600434void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600435{
Tony Barbour22a30862015-04-22 09:02:32 -0600436 VkResult U_ASSERT_ONLY err;
Tony Barbouref20d322015-02-25 12:28:39 -0700437
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800438 VkPresentInfoWSI present = {};
439 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_WSI;
440 present.image = m_display_image->m_presentableImage;
441 present.flipInterval = 1;
Tony Barbouref20d322015-02-25 12:28:39 -0700442
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800443 xcb_change_property (m_connection,
Tony Barbouref20d322015-02-25 12:28:39 -0700444 XCB_PROP_MODE_REPLACE,
445 m_window,
446 XCB_ATOM_WM_NAME,
447 XCB_ATOM_STRING,
448 8,
449 m_display_image->m_title.size(),
450 m_display_image->m_title.c_str());
451
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800452 err = vkQueuePresentWSI(m_queue.obj(), &present);
Tony Barbouref20d322015-02-25 12:28:39 -0700453 assert(!err);
454
455 m_queue.wait();
456
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600457}
458
Tony Barbour01999182015-04-09 12:58:51 -0600459void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600460{
Tony Barbour3a5cda02015-04-02 15:48:24 -0600461 uint8_t event_code = event->response_type & 0x7f;
Tony Barbouref20d322015-02-25 12:28:39 -0700462 switch (event_code) {
463 case XCB_EXPOSE:
464 Display(); // TODO: handle resize
465 break;
466 case XCB_CLIENT_MESSAGE:
467 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
468 (m_atom_wm_delete_window)->atom) {
469 m_quit = true;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600470 }
471 break;
Tony Barbouref20d322015-02-25 12:28:39 -0700472 case XCB_KEY_RELEASE:
473 {
474 const xcb_key_release_event_t *key =
475 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600476
Tony Barbouref20d322015-02-25 12:28:39 -0700477 switch (key->detail) {
478 case 0x9: // Escape
479 m_quit = true;
480 break;
481 case 0x71: // left arrow key
482 if (m_display_image == m_images.begin()) {
483 m_display_image = --m_images.end();
484 } else {
485 --m_display_image;
486 }
487 break;
488 case 0x72: // right arrow key
489 ++m_display_image;
490 if (m_display_image == m_images.end()) {
491 m_display_image = m_images.begin();
492 }
493 break;
494 case 0x41:
495 m_pause = !m_pause;
496 break;
497 }
498 Display();
499 }
500 break;
501 default:
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600502 break;
503 }
Tony Barbouref20d322015-02-25 12:28:39 -0700504}
505
Tony Barbour01999182015-04-09 12:58:51 -0600506void TestFrameworkVkPresent::Run()
Tony Barbouref20d322015-02-25 12:28:39 -0700507{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800508 xcb_flush(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700509
510 while (! m_quit) {
511 xcb_generic_event_t *event;
512
513 if (m_pause) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800514 event = xcb_wait_for_event(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700515 } else {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800516 event = xcb_poll_for_event(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700517 }
518 if (event) {
519 HandleEvent(event);
520 free(event);
521 }
522 }
523}
524
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800525void TestFrameworkVkPresent::CreateSwapChain()
Tony Barbouref20d322015-02-25 12:28:39 -0700526{
Tony Barbour22a30862015-04-22 09:02:32 -0600527 VkResult U_ASSERT_ONLY err;
Tony Barbouref20d322015-02-25 12:28:39 -0700528
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800529 VkSwapChainCreateInfoWSI swap_chain = {};
530 swap_chain.sType = VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI;
531 swap_chain.pNativeWindowSystemHandle = (void *) m_connection;
532 swap_chain.pNativeWindowHandle = (void *) (intptr_t) m_window;
533 swap_chain.imageCount = m_images.size();
534 swap_chain.imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
535 swap_chain.imageExtent.width = m_width;
536 swap_chain.imageExtent.height = m_height;
537 swap_chain.imageArraySize = 1;
538 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT;
539 swap_chain.swapModeFlags = VK_SWAP_MODE_FLIP_BIT_WSI |
540 VK_SWAP_MODE_BLIT_BIT_WSI;
541
542 err = vkCreateSwapChainWSI(m_device.obj(), &swap_chain, &m_swap_chain);
543 assert(!err);
544
545 size_t size = sizeof(VkSwapChainImageInfoWSI) * m_images.size();
546 std::vector<VkSwapChainImageInfoWSI> persistent_images;
547 persistent_images.resize(m_images.size());
548 err = vkGetSwapChainInfoWSI(m_swap_chain,
549 VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI,
550 &size, &persistent_images[0]);
551 assert(!err && size == sizeof(VkSwapChainImageInfoWSI) * m_images.size());
552
Tony Barbouref20d322015-02-25 12:28:39 -0700553 m_display_image = m_images.begin();
554
555 for (int x=0; x < m_images.size(); x++)
556 {
Tony Barbouref20d322015-02-25 12:28:39 -0700557 void *dest_ptr;
558
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800559 m_display_image->m_presentableImage = persistent_images[x].image;
560 m_display_image->m_presentableMemory = persistent_images[x].memory;
Tony Barbouref20d322015-02-25 12:28:39 -0700561
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600562 vk_testing::Buffer buf;
Tony Barbour8205d902015-04-16 15:59:00 -0600563 buf.init(m_device, (VkDeviceSize) m_display_image->m_data_size);
Tony Barbouref20d322015-02-25 12:28:39 -0700564 dest_ptr = buf.map();
565 memcpy(dest_ptr,m_display_image->m_data, m_display_image->m_data_size);
566 buf.unmap();
567
568 m_cmdbuf.begin();
569
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600570 VkBufferImageCopy region = {};
Tony Barbouref20d322015-02-25 12:28:39 -0700571 region.imageExtent.height = m_display_image->m_height;
572 region.imageExtent.width = m_display_image->m_width;
573 region.imageExtent.depth = 1;
574
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600575 vkCmdCopyBufferToImage(m_cmdbuf.obj(),
Courtney Goeltzenleuchter51cbf302015-03-25 11:25:10 -0600576 buf.obj(),
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600577 m_display_image->m_presentableImage, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
Courtney Goeltzenleuchter51cbf302015-03-25 11:25:10 -0600578 1, &region);
Tony Barbouref20d322015-02-25 12:28:39 -0700579 m_cmdbuf.end();
580
Courtney Goeltzenleuchter46962942015-04-16 13:38:46 -0600581 vkQueueAddMemReferences(m_queue.obj(), 1, &m_display_image->m_presentableMemory);
582 vkQueueAddMemReferences(m_queue.obj(), buf.memories().size(), &buf.memories()[0]);
Tony Barbouref20d322015-02-25 12:28:39 -0700583
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600584 VkCmdBuffer cmdBufs[1];
Tony Barbouref20d322015-02-25 12:28:39 -0700585 cmdBufs[0] = m_cmdbuf.obj();
586
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600587 vkQueueSubmit(m_queue.obj(), 1, cmdBufs, NULL);
Tony Barbouref20d322015-02-25 12:28:39 -0700588 m_queue.wait();
589
Courtney Goeltzenleuchter46962942015-04-16 13:38:46 -0600590 vkQueueRemoveMemReferences(m_queue.obj(), 1, &m_display_image->m_presentableMemory);
591 vkQueueRemoveMemReferences(m_queue.obj(), buf.memories().size(), &buf.memories()[0]);
Tony Barbouref20d322015-02-25 12:28:39 -0700592
Tony Barbouref20d322015-02-25 12:28:39 -0700593 ++m_display_image;
Tony Barbouref20d322015-02-25 12:28:39 -0700594 }
595
596 m_display_image = m_images.begin();
597}
598
Tony Barbour01999182015-04-09 12:58:51 -0600599void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn)
Tony Barbouref20d322015-02-25 12:28:39 -0700600{
601 m_images = imagesIn;
602}
603
Tony Barbour01999182015-04-09 12:58:51 -0600604void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbouref20d322015-02-25 12:28:39 -0700605{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800606 const xcb_setup_t *setup;
607 xcb_screen_iterator_t iter;
608 int scr;
Tony Barbouref20d322015-02-25 12:28:39 -0700609 uint32_t value_mask, value_list[32];
610
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800611 m_connection = xcb_connect(NULL, &scr);
612
613 setup = xcb_get_setup(m_connection);
614 iter = xcb_setup_roots_iterator(setup);
615 while (scr-- > 0)
616 xcb_screen_next(&iter);
617
618 m_screen = iter.data;
619
620 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
621 it != m_images.end(); it++) {
622 if (m_width < it->m_width)
623 m_width = it->m_width;
624 if (m_height < it->m_height)
625 m_height = it->m_height;
626 }
627
628 m_window = xcb_generate_id(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700629
630 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800631 value_list[0] = m_screen->black_pixel;
Tony Barbouref20d322015-02-25 12:28:39 -0700632 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
633 XCB_EVENT_MASK_EXPOSURE |
634 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
635
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800636 xcb_create_window(m_connection,
Tony Barbouref20d322015-02-25 12:28:39 -0700637 XCB_COPY_FROM_PARENT,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800638 m_window, m_screen->root,
Tony Barbouref20d322015-02-25 12:28:39 -0700639 0, 0, m_width, m_height, 0,
640 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800641 m_screen->root_visual,
Tony Barbouref20d322015-02-25 12:28:39 -0700642 value_mask, value_list);
643
644 /* Magic code that will send notification when window is destroyed */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800645 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbouref20d322015-02-25 12:28:39 -0700646 "WM_PROTOCOLS");
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800647 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbouref20d322015-02-25 12:28:39 -0700648
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800649 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
650 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbouref20d322015-02-25 12:28:39 -0700651
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800652 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbouref20d322015-02-25 12:28:39 -0700653 m_window, (*reply).atom, 4, 32, 1,
654 &(*m_atom_wm_delete_window).atom);
655 free(reply);
656
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800657 xcb_map_window(m_connection, m_window);
Tony Barbouref20d322015-02-25 12:28:39 -0700658}
659
Tony Barbour01999182015-04-09 12:58:51 -0600660void TestFrameworkVkPresent::TearDown()
Tony Barbouref20d322015-02-25 12:28:39 -0700661{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800662 vkDestroySwapChainWSI(m_swap_chain);
663 xcb_destroy_window(m_connection, m_window);
664 xcb_disconnect(m_connection);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600665}
666
Tony Barbour01999182015-04-09 12:58:51 -0600667void VkTestFramework::Finish()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600668{
669 if (m_images.size() == 0) return;
670
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800671 vk_testing::Environment env;
672 env.SetUp();
Tony Barbouref20d322015-02-25 12:28:39 -0700673 {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800674 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbouref20d322015-02-25 12:28:39 -0700675
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600676 vkPresent.InitPresentFramework(m_images);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600677 vkPresent.CreateMyWindow();
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800678 vkPresent.CreateSwapChain();
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600679 vkPresent.Run();
680 vkPresent.TearDown();
Tony Barbouref20d322015-02-25 12:28:39 -0700681 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800682 env.TearDown();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600683}
684
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600685//
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600686// These are the default resources for TBuiltInResources, used for both
687// - parsing this string for the case where the user didn't supply one
688// - dumping out a template for user construction of a config file
689//
690static const char* DefaultConfig =
691 "MaxLights 32\n"
692 "MaxClipPlanes 6\n"
693 "MaxTextureUnits 32\n"
694 "MaxTextureCoords 32\n"
695 "MaxVertexAttribs 64\n"
696 "MaxVertexUniformComponents 4096\n"
697 "MaxVaryingFloats 64\n"
698 "MaxVertexTextureImageUnits 32\n"
699 "MaxCombinedTextureImageUnits 80\n"
700 "MaxTextureImageUnits 32\n"
701 "MaxFragmentUniformComponents 4096\n"
702 "MaxDrawBuffers 32\n"
703 "MaxVertexUniformVectors 128\n"
704 "MaxVaryingVectors 8\n"
705 "MaxFragmentUniformVectors 16\n"
706 "MaxVertexOutputVectors 16\n"
707 "MaxFragmentInputVectors 15\n"
708 "MinProgramTexelOffset -8\n"
709 "MaxProgramTexelOffset 7\n"
710 "MaxClipDistances 8\n"
711 "MaxComputeWorkGroupCountX 65535\n"
712 "MaxComputeWorkGroupCountY 65535\n"
713 "MaxComputeWorkGroupCountZ 65535\n"
714 "MaxComputeWorkGroupSizeX 1024\n"
715 "MaxComputeWorkGroupSizeY 1024\n"
716 "MaxComputeWorkGroupSizeZ 64\n"
717 "MaxComputeUniformComponents 1024\n"
718 "MaxComputeTextureImageUnits 16\n"
719 "MaxComputeImageUniforms 8\n"
720 "MaxComputeAtomicCounters 8\n"
721 "MaxComputeAtomicCounterBuffers 1\n"
722 "MaxVaryingComponents 60\n"
723 "MaxVertexOutputComponents 64\n"
724 "MaxGeometryInputComponents 64\n"
725 "MaxGeometryOutputComponents 128\n"
726 "MaxFragmentInputComponents 128\n"
727 "MaxImageUnits 8\n"
728 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
729 "MaxCombinedShaderOutputResources 8\n"
730 "MaxImageSamples 0\n"
731 "MaxVertexImageUniforms 0\n"
732 "MaxTessControlImageUniforms 0\n"
733 "MaxTessEvaluationImageUniforms 0\n"
734 "MaxGeometryImageUniforms 0\n"
735 "MaxFragmentImageUniforms 8\n"
736 "MaxCombinedImageUniforms 8\n"
737 "MaxGeometryTextureImageUnits 16\n"
738 "MaxGeometryOutputVertices 256\n"
739 "MaxGeometryTotalOutputComponents 1024\n"
740 "MaxGeometryUniformComponents 1024\n"
741 "MaxGeometryVaryingComponents 64\n"
742 "MaxTessControlInputComponents 128\n"
743 "MaxTessControlOutputComponents 128\n"
744 "MaxTessControlTextureImageUnits 16\n"
745 "MaxTessControlUniformComponents 1024\n"
746 "MaxTessControlTotalOutputComponents 4096\n"
747 "MaxTessEvaluationInputComponents 128\n"
748 "MaxTessEvaluationOutputComponents 128\n"
749 "MaxTessEvaluationTextureImageUnits 16\n"
750 "MaxTessEvaluationUniformComponents 1024\n"
751 "MaxTessPatchComponents 120\n"
752 "MaxPatchVertices 32\n"
753 "MaxTessGenLevel 64\n"
754 "MaxViewports 16\n"
755 "MaxVertexAtomicCounters 0\n"
756 "MaxTessControlAtomicCounters 0\n"
757 "MaxTessEvaluationAtomicCounters 0\n"
758 "MaxGeometryAtomicCounters 0\n"
759 "MaxFragmentAtomicCounters 8\n"
760 "MaxCombinedAtomicCounters 8\n"
761 "MaxAtomicCounterBindings 1\n"
762 "MaxVertexAtomicCounterBuffers 0\n"
763 "MaxTessControlAtomicCounterBuffers 0\n"
764 "MaxTessEvaluationAtomicCounterBuffers 0\n"
765 "MaxGeometryAtomicCounterBuffers 0\n"
766 "MaxFragmentAtomicCounterBuffers 1\n"
767 "MaxCombinedAtomicCounterBuffers 1\n"
768 "MaxAtomicCounterBufferSize 16384\n"
769 "MaxTransformFeedbackBuffers 4\n"
770 "MaxTransformFeedbackInterleavedComponents 64\n"
771 "MaxCullDistances 8\n"
772 "MaxCombinedClipAndCullDistances 8\n"
773 "MaxSamples 4\n"
774
775 "nonInductiveForLoops 1\n"
776 "whileLoops 1\n"
777 "doWhileLoops 1\n"
778 "generalUniformIndexing 1\n"
779 "generalAttributeMatrixVectorIndexing 1\n"
780 "generalVaryingIndexing 1\n"
781 "generalSamplerIndexing 1\n"
782 "generalVariableIndexing 1\n"
783 "generalConstantMatrixVectorIndexing 1\n"
784 ;
785
786//
787// *.conf => this is a config file that can set limits/resources
788//
Tony Barbour01999182015-04-09 12:58:51 -0600789bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600790{
791 if (name.size() < 5)
792 return false;
793
794 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
795 ConfigFile = name;
796 return true;
797 }
798
799 return false;
800}
801
802//
803// Parse either a .conf file provided by the user or the default string above.
804//
Tony Barbour01999182015-04-09 12:58:51 -0600805void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600806{
807 char** configStrings = 0;
808 char* config = 0;
809 if (ConfigFile.size() > 0) {
810 configStrings = ReadFileData(ConfigFile.c_str());
811 if (configStrings)
812 config = *configStrings;
813 else {
814 printf("Error opening configuration file; will instead use the default configuration\n");
815 }
816 }
817
818 if (config == 0) {
819 config = new char[strlen(DefaultConfig) + 1];
820 strcpy(config, DefaultConfig);
821 }
822
823 const char* delims = " \t\n\r";
824 const char* token = strtok(config, delims);
825 while (token) {
826 const char* valueStr = strtok(0, delims);
827 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
828 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
829 return;
830 }
831 int value = atoi(valueStr);
832
833 if (strcmp(token, "MaxLights") == 0)
834 Resources.maxLights = value;
835 else if (strcmp(token, "MaxClipPlanes") == 0)
836 Resources.maxClipPlanes = value;
837 else if (strcmp(token, "MaxTextureUnits") == 0)
838 Resources.maxTextureUnits = value;
839 else if (strcmp(token, "MaxTextureCoords") == 0)
840 Resources.maxTextureCoords = value;
841 else if (strcmp(token, "MaxVertexAttribs") == 0)
842 Resources.maxVertexAttribs = value;
843 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
844 Resources.maxVertexUniformComponents = value;
845 else if (strcmp(token, "MaxVaryingFloats") == 0)
846 Resources.maxVaryingFloats = value;
847 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
848 Resources.maxVertexTextureImageUnits = value;
849 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
850 Resources.maxCombinedTextureImageUnits = value;
851 else if (strcmp(token, "MaxTextureImageUnits") == 0)
852 Resources.maxTextureImageUnits = value;
853 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
854 Resources.maxFragmentUniformComponents = value;
855 else if (strcmp(token, "MaxDrawBuffers") == 0)
856 Resources.maxDrawBuffers = value;
857 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
858 Resources.maxVertexUniformVectors = value;
859 else if (strcmp(token, "MaxVaryingVectors") == 0)
860 Resources.maxVaryingVectors = value;
861 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
862 Resources.maxFragmentUniformVectors = value;
863 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
864 Resources.maxVertexOutputVectors = value;
865 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
866 Resources.maxFragmentInputVectors = value;
867 else if (strcmp(token, "MinProgramTexelOffset") == 0)
868 Resources.minProgramTexelOffset = value;
869 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
870 Resources.maxProgramTexelOffset = value;
871 else if (strcmp(token, "MaxClipDistances") == 0)
872 Resources.maxClipDistances = value;
873 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
874 Resources.maxComputeWorkGroupCountX = value;
875 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
876 Resources.maxComputeWorkGroupCountY = value;
877 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
878 Resources.maxComputeWorkGroupCountZ = value;
879 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
880 Resources.maxComputeWorkGroupSizeX = value;
881 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
882 Resources.maxComputeWorkGroupSizeY = value;
883 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
884 Resources.maxComputeWorkGroupSizeZ = value;
885 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
886 Resources.maxComputeUniformComponents = value;
887 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
888 Resources.maxComputeTextureImageUnits = value;
889 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
890 Resources.maxComputeImageUniforms = value;
891 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
892 Resources.maxComputeAtomicCounters = value;
893 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
894 Resources.maxComputeAtomicCounterBuffers = value;
895 else if (strcmp(token, "MaxVaryingComponents") == 0)
896 Resources.maxVaryingComponents = value;
897 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
898 Resources.maxVertexOutputComponents = value;
899 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
900 Resources.maxGeometryInputComponents = value;
901 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
902 Resources.maxGeometryOutputComponents = value;
903 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
904 Resources.maxFragmentInputComponents = value;
905 else if (strcmp(token, "MaxImageUnits") == 0)
906 Resources.maxImageUnits = value;
907 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
908 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
909 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
910 Resources.maxCombinedShaderOutputResources = value;
911 else if (strcmp(token, "MaxImageSamples") == 0)
912 Resources.maxImageSamples = value;
913 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
914 Resources.maxVertexImageUniforms = value;
915 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
916 Resources.maxTessControlImageUniforms = value;
917 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
918 Resources.maxTessEvaluationImageUniforms = value;
919 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
920 Resources.maxGeometryImageUniforms = value;
921 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
922 Resources.maxFragmentImageUniforms = value;
923 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
924 Resources.maxCombinedImageUniforms = value;
925 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
926 Resources.maxGeometryTextureImageUnits = value;
927 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
928 Resources.maxGeometryOutputVertices = value;
929 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
930 Resources.maxGeometryTotalOutputComponents = value;
931 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
932 Resources.maxGeometryUniformComponents = value;
933 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
934 Resources.maxGeometryVaryingComponents = value;
935 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
936 Resources.maxTessControlInputComponents = value;
937 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
938 Resources.maxTessControlOutputComponents = value;
939 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
940 Resources.maxTessControlTextureImageUnits = value;
941 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
942 Resources.maxTessControlUniformComponents = value;
943 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
944 Resources.maxTessControlTotalOutputComponents = value;
945 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
946 Resources.maxTessEvaluationInputComponents = value;
947 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
948 Resources.maxTessEvaluationOutputComponents = value;
949 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
950 Resources.maxTessEvaluationTextureImageUnits = value;
951 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
952 Resources.maxTessEvaluationUniformComponents = value;
953 else if (strcmp(token, "MaxTessPatchComponents") == 0)
954 Resources.maxTessPatchComponents = value;
955 else if (strcmp(token, "MaxPatchVertices") == 0)
956 Resources.maxPatchVertices = value;
957 else if (strcmp(token, "MaxTessGenLevel") == 0)
958 Resources.maxTessGenLevel = value;
959 else if (strcmp(token, "MaxViewports") == 0)
960 Resources.maxViewports = value;
961 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
962 Resources.maxVertexAtomicCounters = value;
963 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
964 Resources.maxTessControlAtomicCounters = value;
965 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
966 Resources.maxTessEvaluationAtomicCounters = value;
967 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
968 Resources.maxGeometryAtomicCounters = value;
969 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
970 Resources.maxFragmentAtomicCounters = value;
971 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
972 Resources.maxCombinedAtomicCounters = value;
973 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
974 Resources.maxAtomicCounterBindings = value;
975 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
976 Resources.maxVertexAtomicCounterBuffers = value;
977 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
978 Resources.maxTessControlAtomicCounterBuffers = value;
979 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
980 Resources.maxTessEvaluationAtomicCounterBuffers = value;
981 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
982 Resources.maxGeometryAtomicCounterBuffers = value;
983 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
984 Resources.maxFragmentAtomicCounterBuffers = value;
985 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
986 Resources.maxCombinedAtomicCounterBuffers = value;
987 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
988 Resources.maxAtomicCounterBufferSize = value;
989 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
990 Resources.maxTransformFeedbackBuffers = value;
991 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
992 Resources.maxTransformFeedbackInterleavedComponents = value;
993 else if (strcmp(token, "MaxCullDistances") == 0)
994 Resources.maxCullDistances = value;
995 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
996 Resources.maxCombinedClipAndCullDistances = value;
997 else if (strcmp(token, "MaxSamples") == 0)
998 Resources.maxSamples = value;
999
1000 else if (strcmp(token, "nonInductiveForLoops") == 0)
1001 Resources.limits.nonInductiveForLoops = (value != 0);
1002 else if (strcmp(token, "whileLoops") == 0)
1003 Resources.limits.whileLoops = (value != 0);
1004 else if (strcmp(token, "doWhileLoops") == 0)
1005 Resources.limits.doWhileLoops = (value != 0);
1006 else if (strcmp(token, "generalUniformIndexing") == 0)
1007 Resources.limits.generalUniformIndexing = (value != 0);
1008 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1009 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1010 else if (strcmp(token, "generalVaryingIndexing") == 0)
1011 Resources.limits.generalVaryingIndexing = (value != 0);
1012 else if (strcmp(token, "generalSamplerIndexing") == 0)
1013 Resources.limits.generalSamplerIndexing = (value != 0);
1014 else if (strcmp(token, "generalVariableIndexing") == 0)
1015 Resources.limits.generalVariableIndexing = (value != 0);
1016 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1017 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1018 else
1019 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1020
1021 token = strtok(0, delims);
1022 }
1023 if (configStrings)
1024 FreeFileData(configStrings);
1025}
1026
Tony Barbour01999182015-04-09 12:58:51 -06001027void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001028{
1029 if (m_compile_options & EOptionRelaxedErrors)
1030 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1031 if (m_compile_options & EOptionIntermediate)
1032 messages = (EShMessages)(messages | EShMsgAST);
1033 if (m_compile_options & EOptionSuppressWarnings)
1034 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1035}
1036
1037//
1038// Malloc a string of sufficient size and read a string into it.
1039//
Tony Barbour01999182015-04-09 12:58:51 -06001040char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001041{
1042 FILE *in;
1043 #if defined(_WIN32) && defined(__GNUC__)
1044 in = fopen(fileName, "r");
1045 int errorCode = in ? 0 : 1;
1046 #else
1047 int errorCode = fopen_s(&in, fileName, "r");
1048 #endif
1049
1050 char *fdata;
1051 int count = 0;
1052 const int maxSourceStrings = 5;
1053 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1054
1055 if (errorCode) {
1056 printf("Error: unable to open input file: %s\n", fileName);
1057 return 0;
1058 }
1059
1060 while (fgetc(in) != EOF)
1061 count++;
1062
1063 fseek(in, 0, SEEK_SET);
1064
1065 if (!(fdata = (char*)malloc(count+2))) {
1066 printf("Error allocating memory\n");
1067 return 0;
1068 }
1069 if (fread(fdata,1,count, in)!=count) {
1070 printf("Error reading input file: %s\n", fileName);
1071 return 0;
1072 }
1073 fdata[count] = '\0';
1074 fclose(in);
1075 if (count == 0) {
1076 return_data[0]=(char*)malloc(count+2);
1077 return_data[0][0]='\0';
1078 m_num_shader_strings = 0;
1079 return return_data;
1080 } else
1081 m_num_shader_strings = 1;
1082
1083 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1084 int ptr_len=0,i=0;
1085 while(count>0){
1086 return_data[i]=(char*)malloc(len+2);
1087 memcpy(return_data[i],fdata+ptr_len,len);
1088 return_data[i][len]='\0';
1089 count-=(len);
1090 ptr_len+=(len);
1091 if(count<len){
1092 if(count==0){
1093 m_num_shader_strings=(i+1);
1094 break;
1095 }
1096 len = count;
1097 }
1098 ++i;
1099 }
1100 return return_data;
1101}
1102
Tony Barbour01999182015-04-09 12:58:51 -06001103void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001104{
1105 for(int i=0;i<m_num_shader_strings;i++)
1106 free(data[i]);
1107}
1108
1109//
1110// Deduce the language from the filename. Files must end in one of the
1111// following extensions:
1112//
1113// .vert = vertex
1114// .tesc = tessellation control
1115// .tese = tessellation evaluation
1116// .geom = geometry
1117// .frag = fragment
1118// .comp = compute
1119//
Tony Barbour01999182015-04-09 12:58:51 -06001120EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001121{
1122 size_t ext = name.rfind('.');
1123 if (ext == std::string::npos) {
1124 return EShLangVertex;
1125 }
1126
1127 std::string suffix = name.substr(ext + 1, std::string::npos);
1128 if (suffix == "vert")
1129 return EShLangVertex;
1130 else if (suffix == "tesc")
1131 return EShLangTessControl;
1132 else if (suffix == "tese")
1133 return EShLangTessEvaluation;
1134 else if (suffix == "geom")
1135 return EShLangGeometry;
1136 else if (suffix == "frag")
1137 return EShLangFragment;
1138 else if (suffix == "comp")
1139 return EShLangCompute;
1140
1141 return EShLangVertex;
1142}
1143
1144//
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001145// Convert VK shader type to compiler's
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001146//
Tony Barbour8205d902015-04-16 15:59:00 -06001147EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001148{
1149 switch (shader_type) {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001150 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001151 return EShLangVertex;
1152
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001153 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001154 return EShLangTessControl;
1155
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001156 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001157 return EShLangTessEvaluation;
1158
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001159 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001160 return EShLangGeometry;
1161
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001162 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001163 return EShLangFragment;
1164
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001165 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001166 return EShLangCompute;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001167
Chia-I Wubbdeacc2014-12-15 23:50:11 +08001168 default:
1169 return EShLangVertex;
1170 }
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001171}
1172
1173
1174//
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001175// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001176// Return value of false means an error was encountered.
1177//
Tony Barbour8205d902015-04-16 15:59:00 -06001178bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001179 const char *pshader,
Cody Northropacfb0492015-03-17 15:55:58 -06001180 std::vector<unsigned int> &spv)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001181{
1182 glslang::TProgram& program = *new glslang::TProgram;
1183 const char *shaderStrings[1];
1184
1185 // TODO: Do we want to load a special config file depending on the
1186 // shader source? Optional name maybe?
1187 // SetConfigFile(fileName);
1188
1189 ProcessConfigFile();
1190
1191 EShMessages messages = EShMsgDefault;
1192 SetMessageOptions(messages);
1193
1194 EShLanguage stage = FindLanguage(shader_type);
1195 glslang::TShader* shader = new glslang::TShader(stage);
1196
1197 shaderStrings[0] = pshader;
1198 shader->setStrings(shaderStrings, 1);
1199
1200 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1201
Cody Northropad306f02014-11-03 12:54:37 -07001202 if (! (m_compile_options & EOptionSuppressInfolog)) {
1203 puts(shader->getInfoLog());
1204 puts(shader->getInfoDebugLog());
1205 }
1206
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001207 return false; // something didn't work
1208 }
1209
1210 program.addShader(shader);
1211
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001212
1213 //
1214 // Program-level processing...
1215 //
1216
Cody Northropad306f02014-11-03 12:54:37 -07001217 if (! program.link(messages)) {
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001218
Cody Northropad306f02014-11-03 12:54:37 -07001219 if (! (m_compile_options & EOptionSuppressInfolog)) {
1220 puts(shader->getInfoLog());
1221 puts(shader->getInfoDebugLog());
1222 }
1223
1224 return false;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001225 }
1226
1227 if (m_compile_options & EOptionDumpReflection) {
1228 program.buildReflection();
1229 program.dumpReflection();
1230 }
1231
Cody Northropacfb0492015-03-17 15:55:58 -06001232 glslang::GlslangToSpv(*program.getIntermediate(stage), spv);
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001233
1234 return true;
1235}
1236
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001237
1238
Tony Barbour01999182015-04-09 12:58:51 -06001239VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001240 m_width( 0 ),
1241 m_height( 0 ),
Chia-I Wub2c2dea2014-12-15 23:29:34 +08001242 m_data( NULL ),
Tony Barbouref20d322015-02-25 12:28:39 -07001243 m_presentableImage( NULL ),
1244 m_presentableMemory( NULL),
Chia-I Wub2c2dea2014-12-15 23:29:34 +08001245 m_data_size( 0 )
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001246{
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001247}
1248
Tony Barbour01999182015-04-09 12:58:51 -06001249VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001250{
1251
1252}
1253
Tony Barbour01999182015-04-09 12:58:51 -06001254VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001255{
1256 m_title = copyin.m_title;
1257 m_width = copyin.m_width;
1258 m_height = copyin.m_height;
1259 m_data_size = copyin.m_data_size;
1260 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
Tony Barbouref20d322015-02-25 12:28:39 -07001261 m_presentableImage = copyin.m_presentableImage;
1262 m_presentableMemory = copyin.m_presentableMemory;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001263}
1264
Tony Barbour01999182015-04-09 12:58:51 -06001265ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001266{
Tony Barbour01999182015-04-09 12:58:51 -06001267 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1268 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001269 return output;
1270}
1271
Tony Barbour01999182015-04-09 12:58:51 -06001272VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001273{
1274 m_title = rhs.m_title;
1275 m_width = rhs.m_width;
1276 m_height = rhs.m_height;
1277 m_data_size = rhs.m_data_size;
1278 m_data = rhs.m_data;
Tony Barbouref20d322015-02-25 12:28:39 -07001279 m_presentableImage = rhs.m_presentableImage;
1280 m_presentableMemory = rhs.m_presentableMemory;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001281 return *this;
1282}
1283
Tony Barbour01999182015-04-09 12:58:51 -06001284int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001285{
1286 if( this->m_data != rhs.m_data) return 0;
1287 return 1;
1288}
1289
1290// This function is required for built-in STL list functions like sort
Tony Barbour01999182015-04-09 12:58:51 -06001291int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001292{
1293 if( this->m_data_size < rhs.m_data_size ) return 1;
1294 return 0;
1295}
1296