blob: 5792ecfbcf6daca34007fdfb6c5bb3a6cba87891 [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 Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600344 VkSubresourceLayout sr_layout;
345 char *ptr;
346 VkTestImageRecord record;
347 size_t data_size = sizeof(sr_layout);
348 VkImageObj displayImage(image->device());
349 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
350
351 if (!m_show_images) return;
352
353 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, VK_IMAGE_TILING_LINEAR, reqs);
354 displayImage.CopyImage(*image);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600355
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600356 const VkImageSubresource sr = {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600357 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600358 };
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600359
Courtney Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600360 err = vkGetImageSubresourceInfo(displayImage.device()->device(), displayImage.image(), &sr,
361 VK_SUBRESOURCE_INFO_TYPE_LAYOUT,
362 &data_size, &sr_layout);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600363 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600364 ASSERT_EQ(data_size, sizeof(sr_layout));
365
Courtney Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600366 err = displayImage.MapMemory( (void **) &ptr );
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600367 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600368
369 ptr += sr_layout.offset;
370
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600371 record.m_title.append(comment);
Courtney Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600372 record.m_width = displayImage.width();
373 record.m_height = displayImage.height();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600374 // TODO: Need to make this more robust to handle different image formats
Courtney Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600375 record.m_data_size = displayImage.width()*displayImage.height()*4;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600376 record.m_data = malloc(record.m_data_size);
377 memcpy(record.m_data, ptr, record.m_data_size);
378 m_images.push_back(record);
379 m_display_image = --m_images.end();
380
Courtney Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600381 err = displayImage.UnmapMemory();
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600382 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600383}
384
Tony Barbour01999182015-04-09 12:58:51 -0600385void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour32f368c2014-10-30 14:29:04 -0600386{
Courtney Goeltzenleuchtercd5ed1e2015-04-02 14:17:44 -0600387 for (int32_t i = 0; i < images.size(); i++) {
388 RecordImage(images[i]);
Tony Barbour32f368c2014-10-30 14:29:04 -0600389 }
390}
391
Tony Barbour01999182015-04-09 12:58:51 -0600392void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600393{
394 const ::testing::TestInfo* const test_info =
395 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour32f368c2014-10-30 14:29:04 -0600396 ostringstream filestream;
397 string filename;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600398
Tony Barbour32f368c2014-10-30 14:29:04 -0600399 m_width = 40;
400
401 if (strcmp(test_info->name(), m_testName.c_str())) {
402 filestream << test_info->name();
403 m_testName.assign(test_info->name());
Tony Barboura48b0812014-11-18 17:02:36 -0700404 m_frameNum = 2;
405 filename = filestream.str();
Tony Barbour32f368c2014-10-30 14:29:04 -0600406 }
407 else {
408 filestream << test_info->name() << "-" << m_frameNum;
409 m_frameNum++;
Tony Barboura48b0812014-11-18 17:02:36 -0700410 filename = filestream.str();
Tony Barbour32f368c2014-10-30 14:29:04 -0600411 }
412
Tony Barbour32f368c2014-10-30 14:29:04 -0600413 // ToDo - scrub string for bad characters
414
415 if (m_save_images || m_compare_images) {
416 WritePPM(filename.c_str(), image);
417 if (m_compare_images) {
418 Compare(filename.c_str(), image);
419 }
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600420 }
421
422 if (m_show_images) {
Courtney Goeltzenleuchtere5409342014-10-08 14:26:40 -0600423 Show(test_info->name(), image);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600424 }
425}
426
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800427TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
428 m_device(device),
Courtney Goeltzenleuchterdd745fd2015-03-05 16:47:18 -0700429 m_queue(*m_device.graphics_queues()[0]),
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600430 m_cmdbuf(m_device, vk_testing::CmdBuffer::create_info(m_device.graphics_queue_node_index_))
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600431{
Tony Barbouref20d322015-02-25 12:28:39 -0700432 m_quit = false;
433 m_pause = false;
434 m_width = 0;
435 m_height = 0;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600436}
437
Tony Barbour01999182015-04-09 12:58:51 -0600438void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600439{
Tony Barbour22a30862015-04-22 09:02:32 -0600440 VkResult U_ASSERT_ONLY err;
Tony Barbouref20d322015-02-25 12:28:39 -0700441
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800442 VkPresentInfoWSI present = {};
443 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_WSI;
444 present.image = m_display_image->m_presentableImage;
445 present.flipInterval = 1;
Tony Barbouref20d322015-02-25 12:28:39 -0700446
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800447 xcb_change_property (m_connection,
Tony Barbouref20d322015-02-25 12:28:39 -0700448 XCB_PROP_MODE_REPLACE,
449 m_window,
450 XCB_ATOM_WM_NAME,
451 XCB_ATOM_STRING,
452 8,
453 m_display_image->m_title.size(),
454 m_display_image->m_title.c_str());
455
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800456 err = vkQueuePresentWSI(m_queue.obj(), &present);
Tony Barbouref20d322015-02-25 12:28:39 -0700457 assert(!err);
458
459 m_queue.wait();
460
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600461}
462
Tony Barbour01999182015-04-09 12:58:51 -0600463void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600464{
Tony Barbour3a5cda02015-04-02 15:48:24 -0600465 uint8_t event_code = event->response_type & 0x7f;
Tony Barbouref20d322015-02-25 12:28:39 -0700466 switch (event_code) {
467 case XCB_EXPOSE:
468 Display(); // TODO: handle resize
469 break;
470 case XCB_CLIENT_MESSAGE:
471 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
472 (m_atom_wm_delete_window)->atom) {
473 m_quit = true;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600474 }
475 break;
Tony Barbouref20d322015-02-25 12:28:39 -0700476 case XCB_KEY_RELEASE:
477 {
478 const xcb_key_release_event_t *key =
479 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600480
Tony Barbouref20d322015-02-25 12:28:39 -0700481 switch (key->detail) {
482 case 0x9: // Escape
483 m_quit = true;
484 break;
485 case 0x71: // left arrow key
486 if (m_display_image == m_images.begin()) {
487 m_display_image = --m_images.end();
488 } else {
489 --m_display_image;
490 }
491 break;
492 case 0x72: // right arrow key
493 ++m_display_image;
494 if (m_display_image == m_images.end()) {
495 m_display_image = m_images.begin();
496 }
497 break;
498 case 0x41:
499 m_pause = !m_pause;
500 break;
501 }
502 Display();
503 }
504 break;
505 default:
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600506 break;
507 }
Tony Barbouref20d322015-02-25 12:28:39 -0700508}
509
Tony Barbour01999182015-04-09 12:58:51 -0600510void TestFrameworkVkPresent::Run()
Tony Barbouref20d322015-02-25 12:28:39 -0700511{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800512 xcb_flush(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700513
514 while (! m_quit) {
515 xcb_generic_event_t *event;
516
517 if (m_pause) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800518 event = xcb_wait_for_event(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700519 } else {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800520 event = xcb_poll_for_event(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700521 }
522 if (event) {
523 HandleEvent(event);
524 free(event);
525 }
526 }
527}
528
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800529void TestFrameworkVkPresent::CreateSwapChain()
Tony Barbouref20d322015-02-25 12:28:39 -0700530{
Tony Barbour22a30862015-04-22 09:02:32 -0600531 VkResult U_ASSERT_ONLY err;
Tony Barbouref20d322015-02-25 12:28:39 -0700532
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800533 VkSwapChainCreateInfoWSI swap_chain = {};
534 swap_chain.sType = VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI;
535 swap_chain.pNativeWindowSystemHandle = (void *) m_connection;
536 swap_chain.pNativeWindowHandle = (void *) (intptr_t) m_window;
537 swap_chain.imageCount = m_images.size();
538 swap_chain.imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
539 swap_chain.imageExtent.width = m_width;
540 swap_chain.imageExtent.height = m_height;
541 swap_chain.imageArraySize = 1;
542 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT;
543 swap_chain.swapModeFlags = VK_SWAP_MODE_FLIP_BIT_WSI |
544 VK_SWAP_MODE_BLIT_BIT_WSI;
545
546 err = vkCreateSwapChainWSI(m_device.obj(), &swap_chain, &m_swap_chain);
547 assert(!err);
548
549 size_t size = sizeof(VkSwapChainImageInfoWSI) * m_images.size();
550 std::vector<VkSwapChainImageInfoWSI> persistent_images;
551 persistent_images.resize(m_images.size());
552 err = vkGetSwapChainInfoWSI(m_swap_chain,
553 VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI,
554 &size, &persistent_images[0]);
555 assert(!err && size == sizeof(VkSwapChainImageInfoWSI) * m_images.size());
556
Tony Barbouref20d322015-02-25 12:28:39 -0700557 m_display_image = m_images.begin();
558
559 for (int x=0; x < m_images.size(); x++)
560 {
Tony Barbouref20d322015-02-25 12:28:39 -0700561 void *dest_ptr;
562
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800563 m_display_image->m_presentableImage = persistent_images[x].image;
564 m_display_image->m_presentableMemory = persistent_images[x].memory;
Tony Barbouref20d322015-02-25 12:28:39 -0700565
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600566 vk_testing::Buffer buf;
Tony Barbour8205d902015-04-16 15:59:00 -0600567 buf.init(m_device, (VkDeviceSize) m_display_image->m_data_size);
Tony Barbouref20d322015-02-25 12:28:39 -0700568 dest_ptr = buf.map();
569 memcpy(dest_ptr,m_display_image->m_data, m_display_image->m_data_size);
570 buf.unmap();
571
572 m_cmdbuf.begin();
573
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600574 VkBufferImageCopy region = {};
Tony Barbouref20d322015-02-25 12:28:39 -0700575 region.imageExtent.height = m_display_image->m_height;
576 region.imageExtent.width = m_display_image->m_width;
577 region.imageExtent.depth = 1;
578
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600579 vkCmdCopyBufferToImage(m_cmdbuf.obj(),
Courtney Goeltzenleuchter51cbf302015-03-25 11:25:10 -0600580 buf.obj(),
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600581 m_display_image->m_presentableImage, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
Courtney Goeltzenleuchter51cbf302015-03-25 11:25:10 -0600582 1, &region);
Tony Barbouref20d322015-02-25 12:28:39 -0700583 m_cmdbuf.end();
584
Courtney Goeltzenleuchter46962942015-04-16 13:38:46 -0600585 vkQueueAddMemReferences(m_queue.obj(), 1, &m_display_image->m_presentableMemory);
586 vkQueueAddMemReferences(m_queue.obj(), buf.memories().size(), &buf.memories()[0]);
Tony Barbouref20d322015-02-25 12:28:39 -0700587
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600588 VkCmdBuffer cmdBufs[1];
Tony Barbouref20d322015-02-25 12:28:39 -0700589 cmdBufs[0] = m_cmdbuf.obj();
590
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600591 vkQueueSubmit(m_queue.obj(), 1, cmdBufs, NULL);
Tony Barbouref20d322015-02-25 12:28:39 -0700592 m_queue.wait();
593
Courtney Goeltzenleuchter46962942015-04-16 13:38:46 -0600594 vkQueueRemoveMemReferences(m_queue.obj(), 1, &m_display_image->m_presentableMemory);
595 vkQueueRemoveMemReferences(m_queue.obj(), buf.memories().size(), &buf.memories()[0]);
Tony Barbouref20d322015-02-25 12:28:39 -0700596
Tony Barbouref20d322015-02-25 12:28:39 -0700597 ++m_display_image;
Tony Barbouref20d322015-02-25 12:28:39 -0700598 }
599
600 m_display_image = m_images.begin();
601}
602
Tony Barbour01999182015-04-09 12:58:51 -0600603void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn)
Tony Barbouref20d322015-02-25 12:28:39 -0700604{
605 m_images = imagesIn;
606}
607
Tony Barbour01999182015-04-09 12:58:51 -0600608void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbouref20d322015-02-25 12:28:39 -0700609{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800610 const xcb_setup_t *setup;
611 xcb_screen_iterator_t iter;
612 int scr;
Tony Barbouref20d322015-02-25 12:28:39 -0700613 uint32_t value_mask, value_list[32];
614
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800615 m_connection = xcb_connect(NULL, &scr);
616
617 setup = xcb_get_setup(m_connection);
618 iter = xcb_setup_roots_iterator(setup);
619 while (scr-- > 0)
620 xcb_screen_next(&iter);
621
622 m_screen = iter.data;
623
624 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
625 it != m_images.end(); it++) {
626 if (m_width < it->m_width)
627 m_width = it->m_width;
628 if (m_height < it->m_height)
629 m_height = it->m_height;
630 }
631
632 m_window = xcb_generate_id(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700633
634 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800635 value_list[0] = m_screen->black_pixel;
Tony Barbouref20d322015-02-25 12:28:39 -0700636 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
637 XCB_EVENT_MASK_EXPOSURE |
638 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
639
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800640 xcb_create_window(m_connection,
Tony Barbouref20d322015-02-25 12:28:39 -0700641 XCB_COPY_FROM_PARENT,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800642 m_window, m_screen->root,
Tony Barbouref20d322015-02-25 12:28:39 -0700643 0, 0, m_width, m_height, 0,
644 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800645 m_screen->root_visual,
Tony Barbouref20d322015-02-25 12:28:39 -0700646 value_mask, value_list);
647
648 /* Magic code that will send notification when window is destroyed */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800649 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbouref20d322015-02-25 12:28:39 -0700650 "WM_PROTOCOLS");
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800651 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbouref20d322015-02-25 12:28:39 -0700652
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800653 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
654 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbouref20d322015-02-25 12:28:39 -0700655
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800656 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbouref20d322015-02-25 12:28:39 -0700657 m_window, (*reply).atom, 4, 32, 1,
658 &(*m_atom_wm_delete_window).atom);
659 free(reply);
660
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800661 xcb_map_window(m_connection, m_window);
Tony Barbouref20d322015-02-25 12:28:39 -0700662}
663
Tony Barbour01999182015-04-09 12:58:51 -0600664void TestFrameworkVkPresent::TearDown()
Tony Barbouref20d322015-02-25 12:28:39 -0700665{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800666 vkDestroySwapChainWSI(m_swap_chain);
667 xcb_destroy_window(m_connection, m_window);
668 xcb_disconnect(m_connection);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600669}
670
Tony Barbour01999182015-04-09 12:58:51 -0600671void VkTestFramework::Finish()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600672{
673 if (m_images.size() == 0) return;
674
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800675 vk_testing::Environment env;
676 env.SetUp();
Tony Barbouref20d322015-02-25 12:28:39 -0700677 {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800678 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbouref20d322015-02-25 12:28:39 -0700679
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600680 vkPresent.InitPresentFramework(m_images);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600681 vkPresent.CreateMyWindow();
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800682 vkPresent.CreateSwapChain();
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600683 vkPresent.Run();
684 vkPresent.TearDown();
Tony Barbouref20d322015-02-25 12:28:39 -0700685 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800686 env.TearDown();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600687}
688
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600689//
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600690// These are the default resources for TBuiltInResources, used for both
691// - parsing this string for the case where the user didn't supply one
692// - dumping out a template for user construction of a config file
693//
694static const char* DefaultConfig =
695 "MaxLights 32\n"
696 "MaxClipPlanes 6\n"
697 "MaxTextureUnits 32\n"
698 "MaxTextureCoords 32\n"
699 "MaxVertexAttribs 64\n"
700 "MaxVertexUniformComponents 4096\n"
701 "MaxVaryingFloats 64\n"
702 "MaxVertexTextureImageUnits 32\n"
703 "MaxCombinedTextureImageUnits 80\n"
704 "MaxTextureImageUnits 32\n"
705 "MaxFragmentUniformComponents 4096\n"
706 "MaxDrawBuffers 32\n"
707 "MaxVertexUniformVectors 128\n"
708 "MaxVaryingVectors 8\n"
709 "MaxFragmentUniformVectors 16\n"
710 "MaxVertexOutputVectors 16\n"
711 "MaxFragmentInputVectors 15\n"
712 "MinProgramTexelOffset -8\n"
713 "MaxProgramTexelOffset 7\n"
714 "MaxClipDistances 8\n"
715 "MaxComputeWorkGroupCountX 65535\n"
716 "MaxComputeWorkGroupCountY 65535\n"
717 "MaxComputeWorkGroupCountZ 65535\n"
718 "MaxComputeWorkGroupSizeX 1024\n"
719 "MaxComputeWorkGroupSizeY 1024\n"
720 "MaxComputeWorkGroupSizeZ 64\n"
721 "MaxComputeUniformComponents 1024\n"
722 "MaxComputeTextureImageUnits 16\n"
723 "MaxComputeImageUniforms 8\n"
724 "MaxComputeAtomicCounters 8\n"
725 "MaxComputeAtomicCounterBuffers 1\n"
726 "MaxVaryingComponents 60\n"
727 "MaxVertexOutputComponents 64\n"
728 "MaxGeometryInputComponents 64\n"
729 "MaxGeometryOutputComponents 128\n"
730 "MaxFragmentInputComponents 128\n"
731 "MaxImageUnits 8\n"
732 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
733 "MaxCombinedShaderOutputResources 8\n"
734 "MaxImageSamples 0\n"
735 "MaxVertexImageUniforms 0\n"
736 "MaxTessControlImageUniforms 0\n"
737 "MaxTessEvaluationImageUniforms 0\n"
738 "MaxGeometryImageUniforms 0\n"
739 "MaxFragmentImageUniforms 8\n"
740 "MaxCombinedImageUniforms 8\n"
741 "MaxGeometryTextureImageUnits 16\n"
742 "MaxGeometryOutputVertices 256\n"
743 "MaxGeometryTotalOutputComponents 1024\n"
744 "MaxGeometryUniformComponents 1024\n"
745 "MaxGeometryVaryingComponents 64\n"
746 "MaxTessControlInputComponents 128\n"
747 "MaxTessControlOutputComponents 128\n"
748 "MaxTessControlTextureImageUnits 16\n"
749 "MaxTessControlUniformComponents 1024\n"
750 "MaxTessControlTotalOutputComponents 4096\n"
751 "MaxTessEvaluationInputComponents 128\n"
752 "MaxTessEvaluationOutputComponents 128\n"
753 "MaxTessEvaluationTextureImageUnits 16\n"
754 "MaxTessEvaluationUniformComponents 1024\n"
755 "MaxTessPatchComponents 120\n"
756 "MaxPatchVertices 32\n"
757 "MaxTessGenLevel 64\n"
758 "MaxViewports 16\n"
759 "MaxVertexAtomicCounters 0\n"
760 "MaxTessControlAtomicCounters 0\n"
761 "MaxTessEvaluationAtomicCounters 0\n"
762 "MaxGeometryAtomicCounters 0\n"
763 "MaxFragmentAtomicCounters 8\n"
764 "MaxCombinedAtomicCounters 8\n"
765 "MaxAtomicCounterBindings 1\n"
766 "MaxVertexAtomicCounterBuffers 0\n"
767 "MaxTessControlAtomicCounterBuffers 0\n"
768 "MaxTessEvaluationAtomicCounterBuffers 0\n"
769 "MaxGeometryAtomicCounterBuffers 0\n"
770 "MaxFragmentAtomicCounterBuffers 1\n"
771 "MaxCombinedAtomicCounterBuffers 1\n"
772 "MaxAtomicCounterBufferSize 16384\n"
773 "MaxTransformFeedbackBuffers 4\n"
774 "MaxTransformFeedbackInterleavedComponents 64\n"
775 "MaxCullDistances 8\n"
776 "MaxCombinedClipAndCullDistances 8\n"
777 "MaxSamples 4\n"
778
779 "nonInductiveForLoops 1\n"
780 "whileLoops 1\n"
781 "doWhileLoops 1\n"
782 "generalUniformIndexing 1\n"
783 "generalAttributeMatrixVectorIndexing 1\n"
784 "generalVaryingIndexing 1\n"
785 "generalSamplerIndexing 1\n"
786 "generalVariableIndexing 1\n"
787 "generalConstantMatrixVectorIndexing 1\n"
788 ;
789
790//
791// *.conf => this is a config file that can set limits/resources
792//
Tony Barbour01999182015-04-09 12:58:51 -0600793bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600794{
795 if (name.size() < 5)
796 return false;
797
798 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
799 ConfigFile = name;
800 return true;
801 }
802
803 return false;
804}
805
806//
807// Parse either a .conf file provided by the user or the default string above.
808//
Tony Barbour01999182015-04-09 12:58:51 -0600809void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600810{
811 char** configStrings = 0;
812 char* config = 0;
813 if (ConfigFile.size() > 0) {
814 configStrings = ReadFileData(ConfigFile.c_str());
815 if (configStrings)
816 config = *configStrings;
817 else {
818 printf("Error opening configuration file; will instead use the default configuration\n");
819 }
820 }
821
822 if (config == 0) {
823 config = new char[strlen(DefaultConfig) + 1];
824 strcpy(config, DefaultConfig);
825 }
826
827 const char* delims = " \t\n\r";
828 const char* token = strtok(config, delims);
829 while (token) {
830 const char* valueStr = strtok(0, delims);
831 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
832 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
833 return;
834 }
835 int value = atoi(valueStr);
836
837 if (strcmp(token, "MaxLights") == 0)
838 Resources.maxLights = value;
839 else if (strcmp(token, "MaxClipPlanes") == 0)
840 Resources.maxClipPlanes = value;
841 else if (strcmp(token, "MaxTextureUnits") == 0)
842 Resources.maxTextureUnits = value;
843 else if (strcmp(token, "MaxTextureCoords") == 0)
844 Resources.maxTextureCoords = value;
845 else if (strcmp(token, "MaxVertexAttribs") == 0)
846 Resources.maxVertexAttribs = value;
847 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
848 Resources.maxVertexUniformComponents = value;
849 else if (strcmp(token, "MaxVaryingFloats") == 0)
850 Resources.maxVaryingFloats = value;
851 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
852 Resources.maxVertexTextureImageUnits = value;
853 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
854 Resources.maxCombinedTextureImageUnits = value;
855 else if (strcmp(token, "MaxTextureImageUnits") == 0)
856 Resources.maxTextureImageUnits = value;
857 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
858 Resources.maxFragmentUniformComponents = value;
859 else if (strcmp(token, "MaxDrawBuffers") == 0)
860 Resources.maxDrawBuffers = value;
861 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
862 Resources.maxVertexUniformVectors = value;
863 else if (strcmp(token, "MaxVaryingVectors") == 0)
864 Resources.maxVaryingVectors = value;
865 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
866 Resources.maxFragmentUniformVectors = value;
867 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
868 Resources.maxVertexOutputVectors = value;
869 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
870 Resources.maxFragmentInputVectors = value;
871 else if (strcmp(token, "MinProgramTexelOffset") == 0)
872 Resources.minProgramTexelOffset = value;
873 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
874 Resources.maxProgramTexelOffset = value;
875 else if (strcmp(token, "MaxClipDistances") == 0)
876 Resources.maxClipDistances = value;
877 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
878 Resources.maxComputeWorkGroupCountX = value;
879 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
880 Resources.maxComputeWorkGroupCountY = value;
881 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
882 Resources.maxComputeWorkGroupCountZ = value;
883 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
884 Resources.maxComputeWorkGroupSizeX = value;
885 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
886 Resources.maxComputeWorkGroupSizeY = value;
887 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
888 Resources.maxComputeWorkGroupSizeZ = value;
889 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
890 Resources.maxComputeUniformComponents = value;
891 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
892 Resources.maxComputeTextureImageUnits = value;
893 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
894 Resources.maxComputeImageUniforms = value;
895 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
896 Resources.maxComputeAtomicCounters = value;
897 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
898 Resources.maxComputeAtomicCounterBuffers = value;
899 else if (strcmp(token, "MaxVaryingComponents") == 0)
900 Resources.maxVaryingComponents = value;
901 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
902 Resources.maxVertexOutputComponents = value;
903 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
904 Resources.maxGeometryInputComponents = value;
905 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
906 Resources.maxGeometryOutputComponents = value;
907 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
908 Resources.maxFragmentInputComponents = value;
909 else if (strcmp(token, "MaxImageUnits") == 0)
910 Resources.maxImageUnits = value;
911 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
912 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
913 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
914 Resources.maxCombinedShaderOutputResources = value;
915 else if (strcmp(token, "MaxImageSamples") == 0)
916 Resources.maxImageSamples = value;
917 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
918 Resources.maxVertexImageUniforms = value;
919 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
920 Resources.maxTessControlImageUniforms = value;
921 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
922 Resources.maxTessEvaluationImageUniforms = value;
923 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
924 Resources.maxGeometryImageUniforms = value;
925 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
926 Resources.maxFragmentImageUniforms = value;
927 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
928 Resources.maxCombinedImageUniforms = value;
929 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
930 Resources.maxGeometryTextureImageUnits = value;
931 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
932 Resources.maxGeometryOutputVertices = value;
933 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
934 Resources.maxGeometryTotalOutputComponents = value;
935 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
936 Resources.maxGeometryUniformComponents = value;
937 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
938 Resources.maxGeometryVaryingComponents = value;
939 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
940 Resources.maxTessControlInputComponents = value;
941 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
942 Resources.maxTessControlOutputComponents = value;
943 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
944 Resources.maxTessControlTextureImageUnits = value;
945 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
946 Resources.maxTessControlUniformComponents = value;
947 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
948 Resources.maxTessControlTotalOutputComponents = value;
949 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
950 Resources.maxTessEvaluationInputComponents = value;
951 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
952 Resources.maxTessEvaluationOutputComponents = value;
953 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
954 Resources.maxTessEvaluationTextureImageUnits = value;
955 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
956 Resources.maxTessEvaluationUniformComponents = value;
957 else if (strcmp(token, "MaxTessPatchComponents") == 0)
958 Resources.maxTessPatchComponents = value;
959 else if (strcmp(token, "MaxPatchVertices") == 0)
960 Resources.maxPatchVertices = value;
961 else if (strcmp(token, "MaxTessGenLevel") == 0)
962 Resources.maxTessGenLevel = value;
963 else if (strcmp(token, "MaxViewports") == 0)
964 Resources.maxViewports = value;
965 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
966 Resources.maxVertexAtomicCounters = value;
967 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
968 Resources.maxTessControlAtomicCounters = value;
969 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
970 Resources.maxTessEvaluationAtomicCounters = value;
971 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
972 Resources.maxGeometryAtomicCounters = value;
973 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
974 Resources.maxFragmentAtomicCounters = value;
975 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
976 Resources.maxCombinedAtomicCounters = value;
977 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
978 Resources.maxAtomicCounterBindings = value;
979 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
980 Resources.maxVertexAtomicCounterBuffers = value;
981 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
982 Resources.maxTessControlAtomicCounterBuffers = value;
983 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
984 Resources.maxTessEvaluationAtomicCounterBuffers = value;
985 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
986 Resources.maxGeometryAtomicCounterBuffers = value;
987 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
988 Resources.maxFragmentAtomicCounterBuffers = value;
989 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
990 Resources.maxCombinedAtomicCounterBuffers = value;
991 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
992 Resources.maxAtomicCounterBufferSize = value;
993 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
994 Resources.maxTransformFeedbackBuffers = value;
995 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
996 Resources.maxTransformFeedbackInterleavedComponents = value;
997 else if (strcmp(token, "MaxCullDistances") == 0)
998 Resources.maxCullDistances = value;
999 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1000 Resources.maxCombinedClipAndCullDistances = value;
1001 else if (strcmp(token, "MaxSamples") == 0)
1002 Resources.maxSamples = value;
1003
1004 else if (strcmp(token, "nonInductiveForLoops") == 0)
1005 Resources.limits.nonInductiveForLoops = (value != 0);
1006 else if (strcmp(token, "whileLoops") == 0)
1007 Resources.limits.whileLoops = (value != 0);
1008 else if (strcmp(token, "doWhileLoops") == 0)
1009 Resources.limits.doWhileLoops = (value != 0);
1010 else if (strcmp(token, "generalUniformIndexing") == 0)
1011 Resources.limits.generalUniformIndexing = (value != 0);
1012 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1013 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1014 else if (strcmp(token, "generalVaryingIndexing") == 0)
1015 Resources.limits.generalVaryingIndexing = (value != 0);
1016 else if (strcmp(token, "generalSamplerIndexing") == 0)
1017 Resources.limits.generalSamplerIndexing = (value != 0);
1018 else if (strcmp(token, "generalVariableIndexing") == 0)
1019 Resources.limits.generalVariableIndexing = (value != 0);
1020 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1021 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1022 else
1023 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1024
1025 token = strtok(0, delims);
1026 }
1027 if (configStrings)
1028 FreeFileData(configStrings);
1029}
1030
Tony Barbour01999182015-04-09 12:58:51 -06001031void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001032{
1033 if (m_compile_options & EOptionRelaxedErrors)
1034 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1035 if (m_compile_options & EOptionIntermediate)
1036 messages = (EShMessages)(messages | EShMsgAST);
1037 if (m_compile_options & EOptionSuppressWarnings)
1038 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1039}
1040
1041//
1042// Malloc a string of sufficient size and read a string into it.
1043//
Tony Barbour01999182015-04-09 12:58:51 -06001044char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001045{
1046 FILE *in;
1047 #if defined(_WIN32) && defined(__GNUC__)
1048 in = fopen(fileName, "r");
1049 int errorCode = in ? 0 : 1;
1050 #else
1051 int errorCode = fopen_s(&in, fileName, "r");
1052 #endif
1053
1054 char *fdata;
1055 int count = 0;
1056 const int maxSourceStrings = 5;
1057 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1058
1059 if (errorCode) {
1060 printf("Error: unable to open input file: %s\n", fileName);
1061 return 0;
1062 }
1063
1064 while (fgetc(in) != EOF)
1065 count++;
1066
1067 fseek(in, 0, SEEK_SET);
1068
1069 if (!(fdata = (char*)malloc(count+2))) {
1070 printf("Error allocating memory\n");
1071 return 0;
1072 }
1073 if (fread(fdata,1,count, in)!=count) {
1074 printf("Error reading input file: %s\n", fileName);
1075 return 0;
1076 }
1077 fdata[count] = '\0';
1078 fclose(in);
1079 if (count == 0) {
1080 return_data[0]=(char*)malloc(count+2);
1081 return_data[0][0]='\0';
1082 m_num_shader_strings = 0;
1083 return return_data;
1084 } else
1085 m_num_shader_strings = 1;
1086
1087 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1088 int ptr_len=0,i=0;
1089 while(count>0){
1090 return_data[i]=(char*)malloc(len+2);
1091 memcpy(return_data[i],fdata+ptr_len,len);
1092 return_data[i][len]='\0';
1093 count-=(len);
1094 ptr_len+=(len);
1095 if(count<len){
1096 if(count==0){
1097 m_num_shader_strings=(i+1);
1098 break;
1099 }
1100 len = count;
1101 }
1102 ++i;
1103 }
1104 return return_data;
1105}
1106
Tony Barbour01999182015-04-09 12:58:51 -06001107void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001108{
1109 for(int i=0;i<m_num_shader_strings;i++)
1110 free(data[i]);
1111}
1112
1113//
1114// Deduce the language from the filename. Files must end in one of the
1115// following extensions:
1116//
1117// .vert = vertex
1118// .tesc = tessellation control
1119// .tese = tessellation evaluation
1120// .geom = geometry
1121// .frag = fragment
1122// .comp = compute
1123//
Tony Barbour01999182015-04-09 12:58:51 -06001124EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001125{
1126 size_t ext = name.rfind('.');
1127 if (ext == std::string::npos) {
1128 return EShLangVertex;
1129 }
1130
1131 std::string suffix = name.substr(ext + 1, std::string::npos);
1132 if (suffix == "vert")
1133 return EShLangVertex;
1134 else if (suffix == "tesc")
1135 return EShLangTessControl;
1136 else if (suffix == "tese")
1137 return EShLangTessEvaluation;
1138 else if (suffix == "geom")
1139 return EShLangGeometry;
1140 else if (suffix == "frag")
1141 return EShLangFragment;
1142 else if (suffix == "comp")
1143 return EShLangCompute;
1144
1145 return EShLangVertex;
1146}
1147
1148//
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001149// Convert VK shader type to compiler's
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001150//
Tony Barbour8205d902015-04-16 15:59:00 -06001151EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001152{
1153 switch (shader_type) {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001154 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001155 return EShLangVertex;
1156
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001157 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001158 return EShLangTessControl;
1159
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001160 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001161 return EShLangTessEvaluation;
1162
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001163 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001164 return EShLangGeometry;
1165
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001166 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001167 return EShLangFragment;
1168
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001169 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001170 return EShLangCompute;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001171
Chia-I Wubbdeacc2014-12-15 23:50:11 +08001172 default:
1173 return EShLangVertex;
1174 }
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001175}
1176
1177
1178//
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001179// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001180// Return value of false means an error was encountered.
1181//
Tony Barbour8205d902015-04-16 15:59:00 -06001182bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001183 const char *pshader,
Cody Northropacfb0492015-03-17 15:55:58 -06001184 std::vector<unsigned int> &spv)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001185{
1186 glslang::TProgram& program = *new glslang::TProgram;
1187 const char *shaderStrings[1];
1188
1189 // TODO: Do we want to load a special config file depending on the
1190 // shader source? Optional name maybe?
1191 // SetConfigFile(fileName);
1192
1193 ProcessConfigFile();
1194
1195 EShMessages messages = EShMsgDefault;
1196 SetMessageOptions(messages);
1197
1198 EShLanguage stage = FindLanguage(shader_type);
1199 glslang::TShader* shader = new glslang::TShader(stage);
1200
1201 shaderStrings[0] = pshader;
1202 shader->setStrings(shaderStrings, 1);
1203
1204 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1205
Cody Northropad306f02014-11-03 12:54:37 -07001206 if (! (m_compile_options & EOptionSuppressInfolog)) {
1207 puts(shader->getInfoLog());
1208 puts(shader->getInfoDebugLog());
1209 }
1210
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001211 return false; // something didn't work
1212 }
1213
1214 program.addShader(shader);
1215
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001216
1217 //
1218 // Program-level processing...
1219 //
1220
Cody Northropad306f02014-11-03 12:54:37 -07001221 if (! program.link(messages)) {
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001222
Cody Northropad306f02014-11-03 12:54:37 -07001223 if (! (m_compile_options & EOptionSuppressInfolog)) {
1224 puts(shader->getInfoLog());
1225 puts(shader->getInfoDebugLog());
1226 }
1227
1228 return false;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001229 }
1230
1231 if (m_compile_options & EOptionDumpReflection) {
1232 program.buildReflection();
1233 program.dumpReflection();
1234 }
1235
Cody Northropacfb0492015-03-17 15:55:58 -06001236 glslang::GlslangToSpv(*program.getIntermediate(stage), spv);
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001237
1238 return true;
1239}
1240
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001241
1242
Tony Barbour01999182015-04-09 12:58:51 -06001243VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001244 m_width( 0 ),
1245 m_height( 0 ),
Chia-I Wub2c2dea2014-12-15 23:29:34 +08001246 m_data( NULL ),
Tony Barbouref20d322015-02-25 12:28:39 -07001247 m_presentableImage( NULL ),
1248 m_presentableMemory( NULL),
Chia-I Wub2c2dea2014-12-15 23:29:34 +08001249 m_data_size( 0 )
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001250{
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001251}
1252
Tony Barbour01999182015-04-09 12:58:51 -06001253VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001254{
1255
1256}
1257
Tony Barbour01999182015-04-09 12:58:51 -06001258VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001259{
1260 m_title = copyin.m_title;
1261 m_width = copyin.m_width;
1262 m_height = copyin.m_height;
1263 m_data_size = copyin.m_data_size;
1264 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
Tony Barbouref20d322015-02-25 12:28:39 -07001265 m_presentableImage = copyin.m_presentableImage;
1266 m_presentableMemory = copyin.m_presentableMemory;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001267}
1268
Tony Barbour01999182015-04-09 12:58:51 -06001269ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001270{
Tony Barbour01999182015-04-09 12:58:51 -06001271 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1272 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001273 return output;
1274}
1275
Tony Barbour01999182015-04-09 12:58:51 -06001276VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001277{
1278 m_title = rhs.m_title;
1279 m_width = rhs.m_width;
1280 m_height = rhs.m_height;
1281 m_data_size = rhs.m_data_size;
1282 m_data = rhs.m_data;
Tony Barbouref20d322015-02-25 12:28:39 -07001283 m_presentableImage = rhs.m_presentableImage;
1284 m_presentableMemory = rhs.m_presentableMemory;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001285 return *this;
1286}
1287
Tony Barbour01999182015-04-09 12:58:51 -06001288int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001289{
1290 if( this->m_data != rhs.m_data) return 0;
1291 return 1;
1292}
1293
1294// This function is required for built-in STL list functions like sort
Tony Barbour01999182015-04-09 12:58:51 -06001295int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001296{
1297 if( this->m_data_size < rhs.m_data_size ) return 1;
1298 return 0;
1299}
1300