blob: 5792ecfbcf6daca34007fdfb6c5bb3a6cba87891 [file] [log] [blame]
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001// VK tests
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06002//
3// Copyright (C) 2014 LunarG, Inc.
4//
5// Permission is hereby granted, free of charge, to any person obtaining a
6// copy of this software and associated documentation files (the "Software"),
7// to deal in the Software without restriction, including without limitation
8// the rights to use, copy, modify, merge, publish, distribute, sublicense,
9// and/or sell copies of the Software, and to permit persons to whom the
10// Software is furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included
13// in all copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21// DEALINGS IN THE SOFTWARE.
22
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060023#include "vktestframework.h"
24#include "vkrenderframework.h"
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -060025#include "GL/freeglut_std.h"
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060026//#include "ShaderLang.h"
Steve Kc1638cc2015-03-17 09:40:23 -060027#include "GlslangToSpv.h"
Tony Barbour4ab45422014-12-10 17:00:20 -070028#include <limits.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060029#include <math.h>
Chia-I Wuec664fa2014-12-02 11:54:24 +080030#include <wand/MagickWand.h>
Chia-I Wuf8693382015-04-16 22:02:10 +080031#include <xcb/xcb.h>
32#include <vk_wsi_lunarg.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060033
34// Command-line options
35enum TOptions {
36 EOptionNone = 0x000,
37 EOptionIntermediate = 0x001,
38 EOptionSuppressInfolog = 0x002,
39 EOptionMemoryLeakMode = 0x004,
40 EOptionRelaxedErrors = 0x008,
41 EOptionGiveWarnings = 0x010,
42 EOptionLinkProgram = 0x020,
43 EOptionMultiThreaded = 0x040,
44 EOptionDumpConfig = 0x080,
45 EOptionDumpReflection = 0x100,
46 EOptionSuppressWarnings = 0x200,
47 EOptionDumpVersions = 0x400,
Cody Northrop3bfd27c2015-03-17 15:55:58 -060048 EOptionSpv = 0x800,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060049 EOptionDefaultDesktop = 0x1000,
50};
51
Chia-I Wuf8693382015-04-16 22:02:10 +080052class TestFrameworkVkPresent
53{
54public:
55 TestFrameworkVkPresent(vk_testing::Device &device);
56
57 void Run();
58 void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn);
59 void CreateMyWindow();
60 void CreateSwapChain();
61 void TearDown();
62
63protected:
64 vk_testing::Device &m_device;
65 vk_testing::Queue &m_queue;
66 vk_testing::CmdBuffer m_cmdbuf;
67
68private:
69 xcb_connection_t *m_connection;
70 xcb_screen_t *m_screen;
71 xcb_window_t m_window;
72 xcb_intern_atom_reply_t *m_atom_wm_delete_window;
Courtney Goeltzenleuchterd6079ec2015-04-22 10:09:35 -060073 std::list<VkTestImageRecord> m_images;
Chia-I Wuf8693382015-04-16 22:02:10 +080074
75 VkSwapChainWSI m_swap_chain;
76
77 bool m_quit;
78 bool m_pause;
79
80 uint32_t m_width;
81 uint32_t m_height;
82
83 std::list<VkTestImageRecord>::iterator m_display_image;
84
85 void Display();
86 void HandleEvent(xcb_generic_event_t *event);
87};
88
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060089#ifndef _WIN32
90
91#include <errno.h>
92
93int fopen_s(
94 FILE** pFile,
95 const char* filename,
96 const char* mode
97)
98{
99 if (!pFile || !filename || !mode) {
100 return EINVAL;
101 }
102
103 FILE* f = fopen(filename, mode);
104 if (! f) {
105 if (errno != 0) {
106 return errno;
107 } else {
108 return ENOENT;
109 }
110 }
111 *pFile = f;
112
113 return 0;
114}
115
116#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600117
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600118// Set up environment for GLSL compiler
119// Must be done once per process
120void TestEnvironment::SetUp()
121{
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600122 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600123 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800124
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600125 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600126}
127
128void TestEnvironment::TearDown()
129{
130 glslang::FinalizeProcess();
131}
132
Tony Barbour6918cd52015-04-09 12:58:51 -0600133VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600134 m_compile_options( 0 ),
135 m_num_shader_strings( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600136{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600137
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600138}
139
Tony Barbour6918cd52015-04-09 12:58:51 -0600140VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600141{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600142
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600143}
144
145// Define all the static elements
Tony Barbour6918cd52015-04-09 12:58:51 -0600146bool VkTestFramework::m_show_images = false;
147bool VkTestFramework::m_save_images = false;
148bool VkTestFramework::m_compare_images = false;
Tony Barbour0dd968a2015-04-02 15:48:24 -0600149#ifdef _WIN32
Tony Barbour6918cd52015-04-09 12:58:51 -0600150bool VkTestFramework::m_use_spv = false;
Tony Barbour0dd968a2015-04-02 15:48:24 -0600151#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600152bool VkTestFramework::m_use_spv = true;
Tony Barbour0dd968a2015-04-02 15:48:24 -0600153#endif
Tony Barbour6918cd52015-04-09 12:58:51 -0600154int VkTestFramework::m_width = 0;
155int VkTestFramework::m_height = 0;
156std::list<VkTestImageRecord> VkTestFramework::m_images;
157std::list<VkTestImageRecord>::iterator VkTestFramework::m_display_image;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600158int m_display_image_idx = 0;
159
Tony Barbour6918cd52015-04-09 12:58:51 -0600160void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600161{
162 int i, n;
163
164 for (i=0, n=0; i< *argc; i++) {
165 if (strncmp("--show-images", argv[i], 13) == 0) {
166 m_show_images = true;
167 continue;
168 }
169 if (strncmp("--save-images", argv[i], 13) == 0) {
170 m_save_images = true;
171 continue;
172 }
173
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600174 if (strncmp("--use-SPV", argv[i], 13) == 0) {
175 m_use_spv = true;
Courtney Goeltzenleuchterb666dc62014-10-09 09:13:56 -0600176 continue;
177 }
178
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600179 if (strncmp("--no-SPV", argv[i], 13) == 0) {
180 m_use_spv = false;
Courtney Goeltzenleuchterc44e3ee2014-10-31 14:13:33 -0600181 continue;
182 }
183
Tony Barbour247bf372014-10-30 14:29:04 -0600184 if (strncmp("--compare-images", argv[i], 16) == 0) {
185 m_compare_images = true;
186 continue;
187 }
188
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600189 /*
190 * Since the above "consume" inputs, update argv
191 * so that it contains the trimmed list of args for glutInit
192 */
Tony Barboura98d3932014-12-11 09:52:49 -0700193 if (strncmp("--help", argv[i], 6) == 0 || strncmp("-h", argv[i], 2) == 0) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700194 printf("\nOther options:\n");
195 printf("\t--show-images\n"
196 "\t\tDisplay test images in viewer after tests complete.\n");
197 printf("\t--save-images\n"
198 "\t\tSave tests images as ppm files in current working directory.\n"
199 "\t\tUsed to generate golden images for compare-images.\n");
200 printf("\t--compare-images\n"
201 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barboura98d3932014-12-11 09:52:49 -0700202 "\t\tAlso saves the generated test image in current working\n"
203 "\t\t\tdirectory but only if the image is different from the golden\n"
204 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
205 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700206 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600207 printf("\t--use-SPV\n"
208 "\t\tUse SPV code path (default).\n");
209 printf("\t--no-SPV\n"
210 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700211 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700212 }
213
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600214 argv[n] = argv[i];
215 n++;
216 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600217}
218
Tony Barbour6918cd52015-04-09 12:58:51 -0600219void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600220{
221 string filename;
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600222 VkResult err;
Tony Barbour84d448c2015-04-02 14:02:33 -0600223 int x, y;
Tony Barbour6918cd52015-04-09 12:58:51 -0600224 VkImageObj displayImage(image->device());
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600225 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbour84d448c2015-04-02 14:02:33 -0600226
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600227 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, VK_IMAGE_TILING_LINEAR, reqs);
Tony Barbour84d448c2015-04-02 14:02:33 -0600228 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600229
230 filename.append(basename);
231 filename.append(".ppm");
232
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600233 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600234 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600235 };
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600236 VkSubresourceLayout sr_layout;
Chia-I Wu99ff89d2014-12-27 14:14:50 +0800237 size_t data_size = sizeof(sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600238
Mike Stroyanb050c682015-04-17 12:36:38 -0600239 err = vkGetImageSubresourceInfo(image->device()->device(), image->image(), &sr,
Tony Barbourd1c35722015-04-16 15:59:00 -0600240 VK_SUBRESOURCE_INFO_TYPE_LAYOUT,
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600241 &data_size, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600242 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600243 ASSERT_EQ(data_size, sizeof(sr_layout));
244
Tony Barbour84d448c2015-04-02 14:02:33 -0600245 char *ptr;
246 ptr = (char *) displayImage.map();
Courtney Goeltzenleuchter30e9dc42014-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 Barbour84d448c2015-04-02 14:02:33 -0600253 file << displayImage.width() << "\n";
254 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600255 file << 255 << "\n";
256
Tony Barbour84d448c2015-04-02 14:02:33 -0600257 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700258 const int *row = (const int *) ptr;
259 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600260
Tony Barbourd1c35722015-04-16 15:59:00 -0600261 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700262 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600263 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-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 Barbourd1c35722015-04-16 15:59:00 -0600269 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700270 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600271 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-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 Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600279 }
280
281 ptr += sr_layout.rowPitch;
282 }
283
284 file.close();
Tony Barbour84d448c2015-04-02 14:02:33 -0600285 displayImage.unmap();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600286}
287
Tony Barbour6918cd52015-04-09 12:58:51 -0600288void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour247bf372014-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 Barbour4ab45422014-12-10 17:00:20 -0700295 char testimage[256],golden[PATH_MAX+256],golddir[PATH_MAX] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600296 double differenz;
297
Tony Barbour4ab45422014-12-10 17:00:20 -0700298 if (getenv("RENDERTEST_GOLDEN_DIR"))
299 {
300 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
301 }
302
Tony Barbour247bf372014-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 Barbour4ab45422014-12-10 17:00:20 -0700312 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600313 status=MagickReadImage(magick_wand_2,golden);
314 ASSERT_TRUE(status) << "Unable to open file: " << golden;
315
Tony Barbour247bf372014-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 Goeltzenleuchterfcda72d2014-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 Barbour247bf372014-10-30 14:29:04 -0600339}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600340
Tony Barbour6918cd52015-04-09 12:58:51 -0600341void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600342{
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600343 VkResult err;
Courtney Goeltzenleuchterfcf43ab2015-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 Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600355
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600356 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600357 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600358 };
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600359
Courtney Goeltzenleuchterfcf43ab2015-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 Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600363 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600364 ASSERT_EQ(data_size, sizeof(sr_layout));
365
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600366 err = displayImage.MapMemory( (void **) &ptr );
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600367 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600368
369 ptr += sr_layout.offset;
370
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600371 record.m_title.append(comment);
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600372 record.m_width = displayImage.width();
373 record.m_height = displayImage.height();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600374 // TODO: Need to make this more robust to handle different image formats
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600375 record.m_data_size = displayImage.width()*displayImage.height()*4;
Courtney Goeltzenleuchter30e9dc42014-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 Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600381 err = displayImage.UnmapMemory();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600382 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600383}
384
Tony Barbour6918cd52015-04-09 12:58:51 -0600385void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600386{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600387 for (int32_t i = 0; i < images.size(); i++) {
388 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600389 }
390}
391
Tony Barbour6918cd52015-04-09 12:58:51 -0600392void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600393{
394 const ::testing::TestInfo* const test_info =
395 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600396 ostringstream filestream;
397 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600398
Tony Barbour247bf372014-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 Barboura0e2ee82014-11-18 17:02:36 -0700404 m_frameNum = 2;
405 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600406 }
407 else {
408 filestream << test_info->name() << "-" << m_frameNum;
409 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700410 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600411 }
412
Tony Barbour247bf372014-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 Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600420 }
421
422 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600423 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600424 }
425}
426
Chia-I Wuf8693382015-04-16 22:02:10 +0800427TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
428 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700429 m_queue(*m_device.graphics_queues()[0]),
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600430 m_cmdbuf(m_device, vk_testing::CmdBuffer::create_info(m_device.graphics_queue_node_index_))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600431{
Tony Barbour96db8822015-02-25 12:28:39 -0700432 m_quit = false;
433 m_pause = false;
434 m_width = 0;
435 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600436}
437
Tony Barbour6918cd52015-04-09 12:58:51 -0600438void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600439{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600440 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700441
Chia-I Wuf8693382015-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 Barbour96db8822015-02-25 12:28:39 -0700446
Chia-I Wuf8693382015-04-16 22:02:10 +0800447 xcb_change_property (m_connection,
Tony Barbour96db8822015-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 Wuf8693382015-04-16 22:02:10 +0800456 err = vkQueuePresentWSI(m_queue.obj(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700457 assert(!err);
458
459 m_queue.wait();
460
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600461}
462
Tony Barbour6918cd52015-04-09 12:58:51 -0600463void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600464{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600465 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-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 Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600474 }
475 break;
Tony Barbour96db8822015-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 Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600480
Tony Barbour96db8822015-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 Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600506 break;
507 }
Tony Barbour96db8822015-02-25 12:28:39 -0700508}
509
Tony Barbour6918cd52015-04-09 12:58:51 -0600510void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700511{
Chia-I Wuf8693382015-04-16 22:02:10 +0800512 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700513
514 while (! m_quit) {
515 xcb_generic_event_t *event;
516
517 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800518 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700519 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800520 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700521 }
522 if (event) {
523 HandleEvent(event);
524 free(event);
525 }
526 }
527}
528
Chia-I Wuf8693382015-04-16 22:02:10 +0800529void TestFrameworkVkPresent::CreateSwapChain()
Tony Barbour96db8822015-02-25 12:28:39 -0700530{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600531 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700532
Chia-I Wuf8693382015-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 Barbour96db8822015-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 Barbour96db8822015-02-25 12:28:39 -0700561 void *dest_ptr;
562
Chia-I Wuf8693382015-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 Barbour96db8822015-02-25 12:28:39 -0700565
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600566 vk_testing::Buffer buf;
Tony Barbourd1c35722015-04-16 15:59:00 -0600567 buf.init(m_device, (VkDeviceSize) m_display_image->m_data_size);
Tony Barbour96db8822015-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 Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600574 VkBufferImageCopy region = {};
Tony Barbour96db8822015-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 Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600579 vkCmdCopyBufferToImage(m_cmdbuf.obj(),
Courtney Goeltzenleuchterb3efe9b2015-03-25 11:25:10 -0600580 buf.obj(),
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600581 m_display_image->m_presentableImage, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
Courtney Goeltzenleuchterb3efe9b2015-03-25 11:25:10 -0600582 1, &region);
Tony Barbour96db8822015-02-25 12:28:39 -0700583 m_cmdbuf.end();
584
Courtney Goeltzenleuchterf68ad722015-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 Barbour96db8822015-02-25 12:28:39 -0700587
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600588 VkCmdBuffer cmdBufs[1];
Tony Barbour96db8822015-02-25 12:28:39 -0700589 cmdBufs[0] = m_cmdbuf.obj();
590
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600591 vkQueueSubmit(m_queue.obj(), 1, cmdBufs, NULL);
Tony Barbour96db8822015-02-25 12:28:39 -0700592 m_queue.wait();
593
Courtney Goeltzenleuchterf68ad722015-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 Barbour96db8822015-02-25 12:28:39 -0700596
Tony Barbour96db8822015-02-25 12:28:39 -0700597 ++m_display_image;
Tony Barbour96db8822015-02-25 12:28:39 -0700598 }
599
600 m_display_image = m_images.begin();
601}
602
Tony Barbour6918cd52015-04-09 12:58:51 -0600603void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn)
Tony Barbour96db8822015-02-25 12:28:39 -0700604{
605 m_images = imagesIn;
606}
607
Tony Barbour6918cd52015-04-09 12:58:51 -0600608void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -0700609{
Chia-I Wuf8693382015-04-16 22:02:10 +0800610 const xcb_setup_t *setup;
611 xcb_screen_iterator_t iter;
612 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -0700613 uint32_t value_mask, value_list[32];
614
Chia-I Wuf8693382015-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 Barbour96db8822015-02-25 12:28:39 -0700633
634 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +0800635 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-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 Wuf8693382015-04-16 22:02:10 +0800640 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700641 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800642 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -0700643 0, 0, m_width, m_height, 0,
644 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800645 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -0700646 value_mask, value_list);
647
648 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +0800649 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -0700650 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +0800651 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -0700652
Chia-I Wuf8693382015-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 Barbour96db8822015-02-25 12:28:39 -0700655
Chia-I Wuf8693382015-04-16 22:02:10 +0800656 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-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 Wuf8693382015-04-16 22:02:10 +0800661 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -0700662}
663
Tony Barbour6918cd52015-04-09 12:58:51 -0600664void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -0700665{
Chia-I Wuf8693382015-04-16 22:02:10 +0800666 vkDestroySwapChainWSI(m_swap_chain);
667 xcb_destroy_window(m_connection, m_window);
668 xcb_disconnect(m_connection);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600669}
670
Tony Barbour6918cd52015-04-09 12:58:51 -0600671void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600672{
673 if (m_images.size() == 0) return;
674
Chia-I Wuf8693382015-04-16 22:02:10 +0800675 vk_testing::Environment env;
676 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -0700677 {
Chia-I Wuf8693382015-04-16 22:02:10 +0800678 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -0700679
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600680 vkPresent.InitPresentFramework(m_images);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600681 vkPresent.CreateMyWindow();
Chia-I Wuf8693382015-04-16 22:02:10 +0800682 vkPresent.CreateSwapChain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600683 vkPresent.Run();
684 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -0700685 }
Chia-I Wuf8693382015-04-16 22:02:10 +0800686 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600687}
688
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600689//
Courtney Goeltzenleuchter9818f782014-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 Barbour6918cd52015-04-09 12:58:51 -0600793bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-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 Barbour6918cd52015-04-09 12:58:51 -0600809void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-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 Barbour6918cd52015-04-09 12:58:51 -06001031void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-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 Barbour6918cd52015-04-09 12:58:51 -06001044char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-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 Barbour6918cd52015-04-09 12:58:51 -06001107void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-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 Barbour6918cd52015-04-09 12:58:51 -06001124EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-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 Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001149// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001150//
Tony Barbourd1c35722015-04-16 15:59:00 -06001151EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001152{
1153 switch (shader_type) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001154 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001155 return EShLangVertex;
1156
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001157 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001158 return EShLangTessControl;
1159
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001160 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001161 return EShLangTessEvaluation;
1162
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001163 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001164 return EShLangGeometry;
1165
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001166 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001167 return EShLangFragment;
1168
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001169 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001170 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001171
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001172 default:
1173 return EShLangVertex;
1174 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001175}
1176
1177
1178//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001179// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001180// Return value of false means an error was encountered.
1181//
Tony Barbourd1c35722015-04-16 15:59:00 -06001182bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001183 const char *pshader,
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001184 std::vector<unsigned int> &spv)
Courtney Goeltzenleuchter9818f782014-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 Northrop195d6622014-11-03 12:54:37 -07001206 if (! (m_compile_options & EOptionSuppressInfolog)) {
1207 puts(shader->getInfoLog());
1208 puts(shader->getInfoDebugLog());
1209 }
1210
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001211 return false; // something didn't work
1212 }
1213
1214 program.addShader(shader);
1215
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001216
1217 //
1218 // Program-level processing...
1219 //
1220
Cody Northrop195d6622014-11-03 12:54:37 -07001221 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001222
Cody Northrop195d6622014-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 Goeltzenleuchter9818f782014-10-03 09:53:32 -06001229 }
1230
1231 if (m_compile_options & EOptionDumpReflection) {
1232 program.buildReflection();
1233 program.dumpReflection();
1234 }
1235
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001236 glslang::GlslangToSpv(*program.getIntermediate(stage), spv);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001237
1238 return true;
1239}
1240
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001241
1242
Tony Barbour6918cd52015-04-09 12:58:51 -06001243VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001244 m_width( 0 ),
1245 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001246 m_data( NULL ),
Tony Barbour96db8822015-02-25 12:28:39 -07001247 m_presentableImage( NULL ),
1248 m_presentableMemory( NULL),
Chia-I Wu837f9952014-12-15 23:29:34 +08001249 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001250{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001251}
1252
Tony Barbour6918cd52015-04-09 12:58:51 -06001253VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001254{
1255
1256}
1257
Tony Barbour6918cd52015-04-09 12:58:51 -06001258VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-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 Barbour96db8822015-02-25 12:28:39 -07001265 m_presentableImage = copyin.m_presentableImage;
1266 m_presentableMemory = copyin.m_presentableMemory;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001267}
1268
Tony Barbour6918cd52015-04-09 12:58:51 -06001269ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001270{
Tony Barbour6918cd52015-04-09 12:58:51 -06001271 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1272 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001273 return output;
1274}
1275
Tony Barbour6918cd52015-04-09 12:58:51 -06001276VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-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 Barbour96db8822015-02-25 12:28:39 -07001283 m_presentableImage = rhs.m_presentableImage;
1284 m_presentableMemory = rhs.m_presentableMemory;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001285 return *this;
1286}
1287
Tony Barbour6918cd52015-04-09 12:58:51 -06001288int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-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 Barbour6918cd52015-04-09 12:58:51 -06001295int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001296{
1297 if( this->m_data_size < rhs.m_data_size ) return 1;
1298 return 0;
1299}
1300