blob: 85096aeacf0227d172f092c14c55f09f3fba6ca1 [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;
Courtney Goeltzenleuchter9675ea02015-04-29 10:54:08 -0600567 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
568 buf.init(m_device, (VkDeviceSize) m_display_image->m_data_size, flags);
Tony Barbouref20d322015-02-25 12:28:39 -0700569 dest_ptr = buf.map();
570 memcpy(dest_ptr,m_display_image->m_data, m_display_image->m_data_size);
571 buf.unmap();
572
573 m_cmdbuf.begin();
574
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600575 VkBufferImageCopy region = {};
Tony Barbouref20d322015-02-25 12:28:39 -0700576 region.imageExtent.height = m_display_image->m_height;
577 region.imageExtent.width = m_display_image->m_width;
578 region.imageExtent.depth = 1;
579
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600580 vkCmdCopyBufferToImage(m_cmdbuf.obj(),
Courtney Goeltzenleuchter51cbf302015-03-25 11:25:10 -0600581 buf.obj(),
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600582 m_display_image->m_presentableImage, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
Courtney Goeltzenleuchter51cbf302015-03-25 11:25:10 -0600583 1, &region);
Tony Barbouref20d322015-02-25 12:28:39 -0700584 m_cmdbuf.end();
585
Courtney Goeltzenleuchter46962942015-04-16 13:38:46 -0600586 vkQueueAddMemReferences(m_queue.obj(), 1, &m_display_image->m_presentableMemory);
587 vkQueueAddMemReferences(m_queue.obj(), buf.memories().size(), &buf.memories()[0]);
Tony Barbouref20d322015-02-25 12:28:39 -0700588
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600589 VkCmdBuffer cmdBufs[1];
Tony Barbouref20d322015-02-25 12:28:39 -0700590 cmdBufs[0] = m_cmdbuf.obj();
591
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600592 vkQueueSubmit(m_queue.obj(), 1, cmdBufs, NULL);
Tony Barbouref20d322015-02-25 12:28:39 -0700593 m_queue.wait();
594
Courtney Goeltzenleuchter46962942015-04-16 13:38:46 -0600595 vkQueueRemoveMemReferences(m_queue.obj(), 1, &m_display_image->m_presentableMemory);
596 vkQueueRemoveMemReferences(m_queue.obj(), buf.memories().size(), &buf.memories()[0]);
Tony Barbouref20d322015-02-25 12:28:39 -0700597
Tony Barbouref20d322015-02-25 12:28:39 -0700598 ++m_display_image;
Tony Barbouref20d322015-02-25 12:28:39 -0700599 }
600
601 m_display_image = m_images.begin();
602}
603
Tony Barbour01999182015-04-09 12:58:51 -0600604void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn)
Tony Barbouref20d322015-02-25 12:28:39 -0700605{
606 m_images = imagesIn;
607}
608
Tony Barbour01999182015-04-09 12:58:51 -0600609void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbouref20d322015-02-25 12:28:39 -0700610{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800611 const xcb_setup_t *setup;
612 xcb_screen_iterator_t iter;
613 int scr;
Tony Barbouref20d322015-02-25 12:28:39 -0700614 uint32_t value_mask, value_list[32];
615
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800616 m_connection = xcb_connect(NULL, &scr);
617
618 setup = xcb_get_setup(m_connection);
619 iter = xcb_setup_roots_iterator(setup);
620 while (scr-- > 0)
621 xcb_screen_next(&iter);
622
623 m_screen = iter.data;
624
625 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
626 it != m_images.end(); it++) {
627 if (m_width < it->m_width)
628 m_width = it->m_width;
629 if (m_height < it->m_height)
630 m_height = it->m_height;
631 }
632
633 m_window = xcb_generate_id(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700634
635 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800636 value_list[0] = m_screen->black_pixel;
Tony Barbouref20d322015-02-25 12:28:39 -0700637 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
638 XCB_EVENT_MASK_EXPOSURE |
639 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
640
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800641 xcb_create_window(m_connection,
Tony Barbouref20d322015-02-25 12:28:39 -0700642 XCB_COPY_FROM_PARENT,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800643 m_window, m_screen->root,
Tony Barbouref20d322015-02-25 12:28:39 -0700644 0, 0, m_width, m_height, 0,
645 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800646 m_screen->root_visual,
Tony Barbouref20d322015-02-25 12:28:39 -0700647 value_mask, value_list);
648
649 /* Magic code that will send notification when window is destroyed */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800650 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbouref20d322015-02-25 12:28:39 -0700651 "WM_PROTOCOLS");
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800652 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbouref20d322015-02-25 12:28:39 -0700653
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800654 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
655 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbouref20d322015-02-25 12:28:39 -0700656
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800657 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbouref20d322015-02-25 12:28:39 -0700658 m_window, (*reply).atom, 4, 32, 1,
659 &(*m_atom_wm_delete_window).atom);
660 free(reply);
661
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800662 xcb_map_window(m_connection, m_window);
Tony Barbouref20d322015-02-25 12:28:39 -0700663}
664
Tony Barbour01999182015-04-09 12:58:51 -0600665void TestFrameworkVkPresent::TearDown()
Tony Barbouref20d322015-02-25 12:28:39 -0700666{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800667 vkDestroySwapChainWSI(m_swap_chain);
668 xcb_destroy_window(m_connection, m_window);
669 xcb_disconnect(m_connection);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600670}
671
Tony Barbour01999182015-04-09 12:58:51 -0600672void VkTestFramework::Finish()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600673{
674 if (m_images.size() == 0) return;
675
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800676 vk_testing::Environment env;
677 env.SetUp();
Tony Barbouref20d322015-02-25 12:28:39 -0700678 {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800679 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbouref20d322015-02-25 12:28:39 -0700680
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600681 vkPresent.InitPresentFramework(m_images);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600682 vkPresent.CreateMyWindow();
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800683 vkPresent.CreateSwapChain();
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600684 vkPresent.Run();
685 vkPresent.TearDown();
Tony Barbouref20d322015-02-25 12:28:39 -0700686 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800687 env.TearDown();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600688}
689
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600690//
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600691// These are the default resources for TBuiltInResources, used for both
692// - parsing this string for the case where the user didn't supply one
693// - dumping out a template for user construction of a config file
694//
695static const char* DefaultConfig =
696 "MaxLights 32\n"
697 "MaxClipPlanes 6\n"
698 "MaxTextureUnits 32\n"
699 "MaxTextureCoords 32\n"
700 "MaxVertexAttribs 64\n"
701 "MaxVertexUniformComponents 4096\n"
702 "MaxVaryingFloats 64\n"
703 "MaxVertexTextureImageUnits 32\n"
704 "MaxCombinedTextureImageUnits 80\n"
705 "MaxTextureImageUnits 32\n"
706 "MaxFragmentUniformComponents 4096\n"
707 "MaxDrawBuffers 32\n"
708 "MaxVertexUniformVectors 128\n"
709 "MaxVaryingVectors 8\n"
710 "MaxFragmentUniformVectors 16\n"
711 "MaxVertexOutputVectors 16\n"
712 "MaxFragmentInputVectors 15\n"
713 "MinProgramTexelOffset -8\n"
714 "MaxProgramTexelOffset 7\n"
715 "MaxClipDistances 8\n"
716 "MaxComputeWorkGroupCountX 65535\n"
717 "MaxComputeWorkGroupCountY 65535\n"
718 "MaxComputeWorkGroupCountZ 65535\n"
719 "MaxComputeWorkGroupSizeX 1024\n"
720 "MaxComputeWorkGroupSizeY 1024\n"
721 "MaxComputeWorkGroupSizeZ 64\n"
722 "MaxComputeUniformComponents 1024\n"
723 "MaxComputeTextureImageUnits 16\n"
724 "MaxComputeImageUniforms 8\n"
725 "MaxComputeAtomicCounters 8\n"
726 "MaxComputeAtomicCounterBuffers 1\n"
727 "MaxVaryingComponents 60\n"
728 "MaxVertexOutputComponents 64\n"
729 "MaxGeometryInputComponents 64\n"
730 "MaxGeometryOutputComponents 128\n"
731 "MaxFragmentInputComponents 128\n"
732 "MaxImageUnits 8\n"
733 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
734 "MaxCombinedShaderOutputResources 8\n"
735 "MaxImageSamples 0\n"
736 "MaxVertexImageUniforms 0\n"
737 "MaxTessControlImageUniforms 0\n"
738 "MaxTessEvaluationImageUniforms 0\n"
739 "MaxGeometryImageUniforms 0\n"
740 "MaxFragmentImageUniforms 8\n"
741 "MaxCombinedImageUniforms 8\n"
742 "MaxGeometryTextureImageUnits 16\n"
743 "MaxGeometryOutputVertices 256\n"
744 "MaxGeometryTotalOutputComponents 1024\n"
745 "MaxGeometryUniformComponents 1024\n"
746 "MaxGeometryVaryingComponents 64\n"
747 "MaxTessControlInputComponents 128\n"
748 "MaxTessControlOutputComponents 128\n"
749 "MaxTessControlTextureImageUnits 16\n"
750 "MaxTessControlUniformComponents 1024\n"
751 "MaxTessControlTotalOutputComponents 4096\n"
752 "MaxTessEvaluationInputComponents 128\n"
753 "MaxTessEvaluationOutputComponents 128\n"
754 "MaxTessEvaluationTextureImageUnits 16\n"
755 "MaxTessEvaluationUniformComponents 1024\n"
756 "MaxTessPatchComponents 120\n"
757 "MaxPatchVertices 32\n"
758 "MaxTessGenLevel 64\n"
759 "MaxViewports 16\n"
760 "MaxVertexAtomicCounters 0\n"
761 "MaxTessControlAtomicCounters 0\n"
762 "MaxTessEvaluationAtomicCounters 0\n"
763 "MaxGeometryAtomicCounters 0\n"
764 "MaxFragmentAtomicCounters 8\n"
765 "MaxCombinedAtomicCounters 8\n"
766 "MaxAtomicCounterBindings 1\n"
767 "MaxVertexAtomicCounterBuffers 0\n"
768 "MaxTessControlAtomicCounterBuffers 0\n"
769 "MaxTessEvaluationAtomicCounterBuffers 0\n"
770 "MaxGeometryAtomicCounterBuffers 0\n"
771 "MaxFragmentAtomicCounterBuffers 1\n"
772 "MaxCombinedAtomicCounterBuffers 1\n"
773 "MaxAtomicCounterBufferSize 16384\n"
774 "MaxTransformFeedbackBuffers 4\n"
775 "MaxTransformFeedbackInterleavedComponents 64\n"
776 "MaxCullDistances 8\n"
777 "MaxCombinedClipAndCullDistances 8\n"
778 "MaxSamples 4\n"
779
780 "nonInductiveForLoops 1\n"
781 "whileLoops 1\n"
782 "doWhileLoops 1\n"
783 "generalUniformIndexing 1\n"
784 "generalAttributeMatrixVectorIndexing 1\n"
785 "generalVaryingIndexing 1\n"
786 "generalSamplerIndexing 1\n"
787 "generalVariableIndexing 1\n"
788 "generalConstantMatrixVectorIndexing 1\n"
789 ;
790
791//
792// *.conf => this is a config file that can set limits/resources
793//
Tony Barbour01999182015-04-09 12:58:51 -0600794bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600795{
796 if (name.size() < 5)
797 return false;
798
799 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
800 ConfigFile = name;
801 return true;
802 }
803
804 return false;
805}
806
807//
808// Parse either a .conf file provided by the user or the default string above.
809//
Tony Barbour01999182015-04-09 12:58:51 -0600810void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600811{
812 char** configStrings = 0;
813 char* config = 0;
814 if (ConfigFile.size() > 0) {
815 configStrings = ReadFileData(ConfigFile.c_str());
816 if (configStrings)
817 config = *configStrings;
818 else {
819 printf("Error opening configuration file; will instead use the default configuration\n");
820 }
821 }
822
823 if (config == 0) {
824 config = new char[strlen(DefaultConfig) + 1];
825 strcpy(config, DefaultConfig);
826 }
827
828 const char* delims = " \t\n\r";
829 const char* token = strtok(config, delims);
830 while (token) {
831 const char* valueStr = strtok(0, delims);
832 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
833 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
834 return;
835 }
836 int value = atoi(valueStr);
837
838 if (strcmp(token, "MaxLights") == 0)
839 Resources.maxLights = value;
840 else if (strcmp(token, "MaxClipPlanes") == 0)
841 Resources.maxClipPlanes = value;
842 else if (strcmp(token, "MaxTextureUnits") == 0)
843 Resources.maxTextureUnits = value;
844 else if (strcmp(token, "MaxTextureCoords") == 0)
845 Resources.maxTextureCoords = value;
846 else if (strcmp(token, "MaxVertexAttribs") == 0)
847 Resources.maxVertexAttribs = value;
848 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
849 Resources.maxVertexUniformComponents = value;
850 else if (strcmp(token, "MaxVaryingFloats") == 0)
851 Resources.maxVaryingFloats = value;
852 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
853 Resources.maxVertexTextureImageUnits = value;
854 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
855 Resources.maxCombinedTextureImageUnits = value;
856 else if (strcmp(token, "MaxTextureImageUnits") == 0)
857 Resources.maxTextureImageUnits = value;
858 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
859 Resources.maxFragmentUniformComponents = value;
860 else if (strcmp(token, "MaxDrawBuffers") == 0)
861 Resources.maxDrawBuffers = value;
862 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
863 Resources.maxVertexUniformVectors = value;
864 else if (strcmp(token, "MaxVaryingVectors") == 0)
865 Resources.maxVaryingVectors = value;
866 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
867 Resources.maxFragmentUniformVectors = value;
868 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
869 Resources.maxVertexOutputVectors = value;
870 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
871 Resources.maxFragmentInputVectors = value;
872 else if (strcmp(token, "MinProgramTexelOffset") == 0)
873 Resources.minProgramTexelOffset = value;
874 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
875 Resources.maxProgramTexelOffset = value;
876 else if (strcmp(token, "MaxClipDistances") == 0)
877 Resources.maxClipDistances = value;
878 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
879 Resources.maxComputeWorkGroupCountX = value;
880 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
881 Resources.maxComputeWorkGroupCountY = value;
882 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
883 Resources.maxComputeWorkGroupCountZ = value;
884 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
885 Resources.maxComputeWorkGroupSizeX = value;
886 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
887 Resources.maxComputeWorkGroupSizeY = value;
888 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
889 Resources.maxComputeWorkGroupSizeZ = value;
890 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
891 Resources.maxComputeUniformComponents = value;
892 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
893 Resources.maxComputeTextureImageUnits = value;
894 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
895 Resources.maxComputeImageUniforms = value;
896 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
897 Resources.maxComputeAtomicCounters = value;
898 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
899 Resources.maxComputeAtomicCounterBuffers = value;
900 else if (strcmp(token, "MaxVaryingComponents") == 0)
901 Resources.maxVaryingComponents = value;
902 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
903 Resources.maxVertexOutputComponents = value;
904 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
905 Resources.maxGeometryInputComponents = value;
906 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
907 Resources.maxGeometryOutputComponents = value;
908 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
909 Resources.maxFragmentInputComponents = value;
910 else if (strcmp(token, "MaxImageUnits") == 0)
911 Resources.maxImageUnits = value;
912 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
913 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
914 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
915 Resources.maxCombinedShaderOutputResources = value;
916 else if (strcmp(token, "MaxImageSamples") == 0)
917 Resources.maxImageSamples = value;
918 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
919 Resources.maxVertexImageUniforms = value;
920 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
921 Resources.maxTessControlImageUniforms = value;
922 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
923 Resources.maxTessEvaluationImageUniforms = value;
924 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
925 Resources.maxGeometryImageUniforms = value;
926 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
927 Resources.maxFragmentImageUniforms = value;
928 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
929 Resources.maxCombinedImageUniforms = value;
930 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
931 Resources.maxGeometryTextureImageUnits = value;
932 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
933 Resources.maxGeometryOutputVertices = value;
934 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
935 Resources.maxGeometryTotalOutputComponents = value;
936 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
937 Resources.maxGeometryUniformComponents = value;
938 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
939 Resources.maxGeometryVaryingComponents = value;
940 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
941 Resources.maxTessControlInputComponents = value;
942 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
943 Resources.maxTessControlOutputComponents = value;
944 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
945 Resources.maxTessControlTextureImageUnits = value;
946 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
947 Resources.maxTessControlUniformComponents = value;
948 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
949 Resources.maxTessControlTotalOutputComponents = value;
950 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
951 Resources.maxTessEvaluationInputComponents = value;
952 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
953 Resources.maxTessEvaluationOutputComponents = value;
954 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
955 Resources.maxTessEvaluationTextureImageUnits = value;
956 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
957 Resources.maxTessEvaluationUniformComponents = value;
958 else if (strcmp(token, "MaxTessPatchComponents") == 0)
959 Resources.maxTessPatchComponents = value;
960 else if (strcmp(token, "MaxPatchVertices") == 0)
961 Resources.maxPatchVertices = value;
962 else if (strcmp(token, "MaxTessGenLevel") == 0)
963 Resources.maxTessGenLevel = value;
964 else if (strcmp(token, "MaxViewports") == 0)
965 Resources.maxViewports = value;
966 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
967 Resources.maxVertexAtomicCounters = value;
968 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
969 Resources.maxTessControlAtomicCounters = value;
970 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
971 Resources.maxTessEvaluationAtomicCounters = value;
972 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
973 Resources.maxGeometryAtomicCounters = value;
974 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
975 Resources.maxFragmentAtomicCounters = value;
976 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
977 Resources.maxCombinedAtomicCounters = value;
978 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
979 Resources.maxAtomicCounterBindings = value;
980 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
981 Resources.maxVertexAtomicCounterBuffers = value;
982 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
983 Resources.maxTessControlAtomicCounterBuffers = value;
984 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
985 Resources.maxTessEvaluationAtomicCounterBuffers = value;
986 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
987 Resources.maxGeometryAtomicCounterBuffers = value;
988 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
989 Resources.maxFragmentAtomicCounterBuffers = value;
990 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
991 Resources.maxCombinedAtomicCounterBuffers = value;
992 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
993 Resources.maxAtomicCounterBufferSize = value;
994 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
995 Resources.maxTransformFeedbackBuffers = value;
996 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
997 Resources.maxTransformFeedbackInterleavedComponents = value;
998 else if (strcmp(token, "MaxCullDistances") == 0)
999 Resources.maxCullDistances = value;
1000 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1001 Resources.maxCombinedClipAndCullDistances = value;
1002 else if (strcmp(token, "MaxSamples") == 0)
1003 Resources.maxSamples = value;
1004
1005 else if (strcmp(token, "nonInductiveForLoops") == 0)
1006 Resources.limits.nonInductiveForLoops = (value != 0);
1007 else if (strcmp(token, "whileLoops") == 0)
1008 Resources.limits.whileLoops = (value != 0);
1009 else if (strcmp(token, "doWhileLoops") == 0)
1010 Resources.limits.doWhileLoops = (value != 0);
1011 else if (strcmp(token, "generalUniformIndexing") == 0)
1012 Resources.limits.generalUniformIndexing = (value != 0);
1013 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1014 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1015 else if (strcmp(token, "generalVaryingIndexing") == 0)
1016 Resources.limits.generalVaryingIndexing = (value != 0);
1017 else if (strcmp(token, "generalSamplerIndexing") == 0)
1018 Resources.limits.generalSamplerIndexing = (value != 0);
1019 else if (strcmp(token, "generalVariableIndexing") == 0)
1020 Resources.limits.generalVariableIndexing = (value != 0);
1021 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1022 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1023 else
1024 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1025
1026 token = strtok(0, delims);
1027 }
1028 if (configStrings)
1029 FreeFileData(configStrings);
1030}
1031
Tony Barbour01999182015-04-09 12:58:51 -06001032void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001033{
1034 if (m_compile_options & EOptionRelaxedErrors)
1035 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1036 if (m_compile_options & EOptionIntermediate)
1037 messages = (EShMessages)(messages | EShMsgAST);
1038 if (m_compile_options & EOptionSuppressWarnings)
1039 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1040}
1041
1042//
1043// Malloc a string of sufficient size and read a string into it.
1044//
Tony Barbour01999182015-04-09 12:58:51 -06001045char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001046{
1047 FILE *in;
1048 #if defined(_WIN32) && defined(__GNUC__)
1049 in = fopen(fileName, "r");
1050 int errorCode = in ? 0 : 1;
1051 #else
1052 int errorCode = fopen_s(&in, fileName, "r");
1053 #endif
1054
1055 char *fdata;
1056 int count = 0;
1057 const int maxSourceStrings = 5;
1058 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1059
1060 if (errorCode) {
1061 printf("Error: unable to open input file: %s\n", fileName);
1062 return 0;
1063 }
1064
1065 while (fgetc(in) != EOF)
1066 count++;
1067
1068 fseek(in, 0, SEEK_SET);
1069
1070 if (!(fdata = (char*)malloc(count+2))) {
1071 printf("Error allocating memory\n");
1072 return 0;
1073 }
1074 if (fread(fdata,1,count, in)!=count) {
1075 printf("Error reading input file: %s\n", fileName);
1076 return 0;
1077 }
1078 fdata[count] = '\0';
1079 fclose(in);
1080 if (count == 0) {
1081 return_data[0]=(char*)malloc(count+2);
1082 return_data[0][0]='\0';
1083 m_num_shader_strings = 0;
1084 return return_data;
1085 } else
1086 m_num_shader_strings = 1;
1087
1088 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1089 int ptr_len=0,i=0;
1090 while(count>0){
1091 return_data[i]=(char*)malloc(len+2);
1092 memcpy(return_data[i],fdata+ptr_len,len);
1093 return_data[i][len]='\0';
1094 count-=(len);
1095 ptr_len+=(len);
1096 if(count<len){
1097 if(count==0){
1098 m_num_shader_strings=(i+1);
1099 break;
1100 }
1101 len = count;
1102 }
1103 ++i;
1104 }
1105 return return_data;
1106}
1107
Tony Barbour01999182015-04-09 12:58:51 -06001108void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001109{
1110 for(int i=0;i<m_num_shader_strings;i++)
1111 free(data[i]);
1112}
1113
1114//
1115// Deduce the language from the filename. Files must end in one of the
1116// following extensions:
1117//
1118// .vert = vertex
1119// .tesc = tessellation control
1120// .tese = tessellation evaluation
1121// .geom = geometry
1122// .frag = fragment
1123// .comp = compute
1124//
Tony Barbour01999182015-04-09 12:58:51 -06001125EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001126{
1127 size_t ext = name.rfind('.');
1128 if (ext == std::string::npos) {
1129 return EShLangVertex;
1130 }
1131
1132 std::string suffix = name.substr(ext + 1, std::string::npos);
1133 if (suffix == "vert")
1134 return EShLangVertex;
1135 else if (suffix == "tesc")
1136 return EShLangTessControl;
1137 else if (suffix == "tese")
1138 return EShLangTessEvaluation;
1139 else if (suffix == "geom")
1140 return EShLangGeometry;
1141 else if (suffix == "frag")
1142 return EShLangFragment;
1143 else if (suffix == "comp")
1144 return EShLangCompute;
1145
1146 return EShLangVertex;
1147}
1148
1149//
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001150// Convert VK shader type to compiler's
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001151//
Tony Barbour8205d902015-04-16 15:59:00 -06001152EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001153{
1154 switch (shader_type) {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001155 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001156 return EShLangVertex;
1157
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001158 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001159 return EShLangTessControl;
1160
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001161 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001162 return EShLangTessEvaluation;
1163
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001164 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001165 return EShLangGeometry;
1166
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001167 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001168 return EShLangFragment;
1169
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001170 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001171 return EShLangCompute;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001172
Chia-I Wubbdeacc2014-12-15 23:50:11 +08001173 default:
1174 return EShLangVertex;
1175 }
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001176}
1177
1178
1179//
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001180// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001181// Return value of false means an error was encountered.
1182//
Tony Barbour8205d902015-04-16 15:59:00 -06001183bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001184 const char *pshader,
Cody Northropacfb0492015-03-17 15:55:58 -06001185 std::vector<unsigned int> &spv)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001186{
1187 glslang::TProgram& program = *new glslang::TProgram;
1188 const char *shaderStrings[1];
1189
1190 // TODO: Do we want to load a special config file depending on the
1191 // shader source? Optional name maybe?
1192 // SetConfigFile(fileName);
1193
1194 ProcessConfigFile();
1195
1196 EShMessages messages = EShMsgDefault;
1197 SetMessageOptions(messages);
1198
1199 EShLanguage stage = FindLanguage(shader_type);
1200 glslang::TShader* shader = new glslang::TShader(stage);
1201
1202 shaderStrings[0] = pshader;
1203 shader->setStrings(shaderStrings, 1);
1204
1205 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1206
Cody Northropad306f02014-11-03 12:54:37 -07001207 if (! (m_compile_options & EOptionSuppressInfolog)) {
1208 puts(shader->getInfoLog());
1209 puts(shader->getInfoDebugLog());
1210 }
1211
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001212 return false; // something didn't work
1213 }
1214
1215 program.addShader(shader);
1216
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001217
1218 //
1219 // Program-level processing...
1220 //
1221
Cody Northropad306f02014-11-03 12:54:37 -07001222 if (! program.link(messages)) {
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001223
Cody Northropad306f02014-11-03 12:54:37 -07001224 if (! (m_compile_options & EOptionSuppressInfolog)) {
1225 puts(shader->getInfoLog());
1226 puts(shader->getInfoDebugLog());
1227 }
1228
1229 return false;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001230 }
1231
1232 if (m_compile_options & EOptionDumpReflection) {
1233 program.buildReflection();
1234 program.dumpReflection();
1235 }
1236
Cody Northropacfb0492015-03-17 15:55:58 -06001237 glslang::GlslangToSpv(*program.getIntermediate(stage), spv);
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001238
1239 return true;
1240}
1241
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001242
1243
Tony Barbour01999182015-04-09 12:58:51 -06001244VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001245 m_width( 0 ),
1246 m_height( 0 ),
Chia-I Wub2c2dea2014-12-15 23:29:34 +08001247 m_data( NULL ),
Tony Barbouref20d322015-02-25 12:28:39 -07001248 m_presentableImage( NULL ),
1249 m_presentableMemory( NULL),
Chia-I Wub2c2dea2014-12-15 23:29:34 +08001250 m_data_size( 0 )
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001251{
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001252}
1253
Tony Barbour01999182015-04-09 12:58:51 -06001254VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001255{
1256
1257}
1258
Tony Barbour01999182015-04-09 12:58:51 -06001259VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001260{
1261 m_title = copyin.m_title;
1262 m_width = copyin.m_width;
1263 m_height = copyin.m_height;
1264 m_data_size = copyin.m_data_size;
1265 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
Tony Barbouref20d322015-02-25 12:28:39 -07001266 m_presentableImage = copyin.m_presentableImage;
1267 m_presentableMemory = copyin.m_presentableMemory;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001268}
1269
Tony Barbour01999182015-04-09 12:58:51 -06001270ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001271{
Tony Barbour01999182015-04-09 12:58:51 -06001272 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1273 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001274 return output;
1275}
1276
Tony Barbour01999182015-04-09 12:58:51 -06001277VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001278{
1279 m_title = rhs.m_title;
1280 m_width = rhs.m_width;
1281 m_height = rhs.m_height;
1282 m_data_size = rhs.m_data_size;
1283 m_data = rhs.m_data;
Tony Barbouref20d322015-02-25 12:28:39 -07001284 m_presentableImage = rhs.m_presentableImage;
1285 m_presentableMemory = rhs.m_presentableMemory;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001286 return *this;
1287}
1288
Tony Barbour01999182015-04-09 12:58:51 -06001289int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001290{
1291 if( this->m_data != rhs.m_data) return 0;
1292 return 1;
1293}
1294
1295// This function is required for built-in STL list functions like sort
Tony Barbour01999182015-04-09 12:58:51 -06001296int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001297{
1298 if( this->m_data_size < rhs.m_data_size ) return 1;
1299 return 0;
1300}
1301