blob: e3ec496aa69d156ec50efd27e49a92065397b81c [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"
Cody Northrop5a95b472015-06-03 13:01:54 -060025#include "SPIRV/GlslangToSpv.h"
26#include "SPIRV/SPVRemapper.h"
Tony Barbour4ab45422014-12-10 17:00:20 -070027#include <limits.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060028#include <math.h>
Chia-I Wuec664fa2014-12-02 11:54:24 +080029#include <wand/MagickWand.h>
Chia-I Wuf8693382015-04-16 22:02:10 +080030#include <xcb/xcb.h>
Ian Elliott1a3845b2015-07-06 14:33:04 -060031#include "vk_wsi_swapchain.h"
32#include "vk_wsi_device_swapchain.h"
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060033
Tony Barbour3d69c9e2015-05-20 16:53:31 -060034#if defined(PATH_MAX) && !defined(MAX_PATH)
35#define MAX_PATH PATH_MAX
36#endif
37
Tony Barbour6a3faf02015-07-23 10:36:18 -060038#ifdef _WIN32
39#define ERR_EXIT(err_msg, err_class) \
40 do { \
41 MessageBox(NULL, err_msg, err_class, MB_OK); \
42 exit(1); \
43 } while (0)
44#else // _WIN32
45
46#define ERR_EXIT(err_msg, err_class) \
47 do { \
48 printf(err_msg); \
49 fflush(stdout); \
50 exit(1); \
51 } while (0)
52#endif // _WIN32
53
54#define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \
55{ \
56 m_fp##entrypoint = (PFN_vk##entrypoint) vkGetInstanceProcAddr(inst, "vk"#entrypoint); \
57 if (m_fp##entrypoint == NULL) { \
58 ERR_EXIT("vkGetInstanceProcAddr failed to find vk"#entrypoint, \
59 "vkGetInstanceProcAddr Failure"); \
60 } \
61}
62
63#define GET_DEVICE_PROC_ADDR(dev, entrypoint) \
64{ \
65 m_fp##entrypoint = (PFN_vk##entrypoint) vkGetDeviceProcAddr(dev, "vk"#entrypoint); \
66 if (m_fp##entrypoint == NULL) { \
67 ERR_EXIT("vkGetDeviceProcAddr failed to find vk"#entrypoint, \
68 "vkGetDeviceProcAddr Failure"); \
69 } \
70}
71
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060072// Command-line options
73enum TOptions {
74 EOptionNone = 0x000,
75 EOptionIntermediate = 0x001,
76 EOptionSuppressInfolog = 0x002,
77 EOptionMemoryLeakMode = 0x004,
78 EOptionRelaxedErrors = 0x008,
79 EOptionGiveWarnings = 0x010,
80 EOptionLinkProgram = 0x020,
81 EOptionMultiThreaded = 0x040,
82 EOptionDumpConfig = 0x080,
83 EOptionDumpReflection = 0x100,
84 EOptionSuppressWarnings = 0x200,
85 EOptionDumpVersions = 0x400,
Cody Northrop3bfd27c2015-03-17 15:55:58 -060086 EOptionSpv = 0x800,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060087 EOptionDefaultDesktop = 0x1000,
88};
89
Tony Barbour6a3faf02015-07-23 10:36:18 -060090typedef struct _SwapChainBuffers {
91 VkImage image;
92 VkCmdBuffer cmd;
93 VkAttachmentView view;
94} SwapChainBuffers;
95
Chia-I Wuf8693382015-04-16 22:02:10 +080096class TestFrameworkVkPresent
97{
98public:
99 TestFrameworkVkPresent(vk_testing::Device &device);
100
101 void Run();
Jon Ashburn07daee72015-05-21 18:13:33 -0600102 void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst);
Chia-I Wuf8693382015-04-16 22:02:10 +0800103 void CreateMyWindow();
104 void CreateSwapChain();
105 void TearDown();
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600106#ifdef _WIN32
107 static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
108#endif
109
Chia-I Wuf8693382015-04-16 22:02:10 +0800110
111protected:
112 vk_testing::Device &m_device;
113 vk_testing::Queue &m_queue;
Dana Jansens233a0ea2015-07-30 13:04:16 -0700114 vk_testing::CmdPool m_cmdpool;
Chia-I Wuf8693382015-04-16 22:02:10 +0800115 vk_testing::CmdBuffer m_cmdbuf;
116
117private:
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600118#ifdef _WIN32
119 HINSTANCE m_connection; // hInstance - Windows Instance
120 HWND m_window; // hWnd - window handle
121
122#else
Chia-I Wuf8693382015-04-16 22:02:10 +0800123 xcb_connection_t *m_connection;
124 xcb_screen_t *m_screen;
125 xcb_window_t m_window;
126 xcb_intern_atom_reply_t *m_atom_wm_delete_window;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600127 VkPlatformHandleXcbWSI m_platform_handle_xcb;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600128#endif
Courtney Goeltzenleuchterd6079ec2015-04-22 10:09:35 -0600129 std::list<VkTestImageRecord> m_images;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600130 uint32_t m_present_queue_node_index;
Chia-I Wuf8693382015-04-16 22:02:10 +0800131
Tony Barbour6a3faf02015-07-23 10:36:18 -0600132 PFN_vkGetPhysicalDeviceSurfaceSupportWSI m_fpGetPhysicalDeviceSurfaceSupportWSI;
133 PFN_vkGetSurfaceInfoWSI m_fpGetSurfaceInfoWSI;
Jon Ashburn07daee72015-05-21 18:13:33 -0600134 PFN_vkCreateSwapChainWSI m_fpCreateSwapChainWSI;
135 PFN_vkDestroySwapChainWSI m_fpDestroySwapChainWSI;
136 PFN_vkGetSwapChainInfoWSI m_fpGetSwapChainInfoWSI;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600137 PFN_vkAcquireNextImageWSI m_fpAcquireNextImageWSI;
Jon Ashburn07daee72015-05-21 18:13:33 -0600138 PFN_vkQueuePresentWSI m_fpQueuePresentWSI;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600139 VkSurfaceDescriptionWindowWSI m_surface_description;
140 size_t m_swapChainImageCount;
Chia-I Wuf8693382015-04-16 22:02:10 +0800141 VkSwapChainWSI m_swap_chain;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600142 SwapChainBuffers *m_buffers;
143 VkFormat m_format;
144
145 uint32_t m_current_buffer;
Chia-I Wuf8693382015-04-16 22:02:10 +0800146
147 bool m_quit;
148 bool m_pause;
149
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600150 int m_width;
151 int m_height;
Chia-I Wuf8693382015-04-16 22:02:10 +0800152
153 std::list<VkTestImageRecord>::iterator m_display_image;
154
155 void Display();
156 void HandleEvent(xcb_generic_event_t *event);
157};
158
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600159#ifndef _WIN32
160
161#include <errno.h>
162
163int fopen_s(
164 FILE** pFile,
165 const char* filename,
166 const char* mode
167)
168{
169 if (!pFile || !filename || !mode) {
170 return EINVAL;
171 }
172
173 FILE* f = fopen(filename, mode);
174 if (! f) {
175 if (errno != 0) {
176 return errno;
177 } else {
178 return ENOENT;
179 }
180 }
181 *pFile = f;
182
183 return 0;
184}
185
186#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600187
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600188
189
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600190// Set up environment for GLSL compiler
191// Must be done once per process
192void TestEnvironment::SetUp()
193{
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600194 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600195 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800196
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600197 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600198}
199
200void TestEnvironment::TearDown()
201{
202 glslang::FinalizeProcess();
203}
204
Tony Barbour6918cd52015-04-09 12:58:51 -0600205VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600206 m_compile_options( 0 ),
207 m_num_shader_strings( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600208{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600209
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600210}
211
Tony Barbour6918cd52015-04-09 12:58:51 -0600212VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600213{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600214
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600215}
216
217// Define all the static elements
Cody Northropa3673cf2015-06-09 13:00:45 -0600218bool VkTestFramework::m_show_images = false;
219bool VkTestFramework::m_save_images = false;
220bool VkTestFramework::m_compare_images = false;
221bool VkTestFramework::m_use_glsl = false;
222bool VkTestFramework::m_canonicalize_spv = false;
223bool VkTestFramework::m_strip_spv = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600224bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour6918cd52015-04-09 12:58:51 -0600225int VkTestFramework::m_width = 0;
226int VkTestFramework::m_height = 0;
227std::list<VkTestImageRecord> VkTestFramework::m_images;
228std::list<VkTestImageRecord>::iterator VkTestFramework::m_display_image;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600229int m_display_image_idx = 0;
230
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600231bool VkTestFramework::optionMatch(const char* option, char* optionLine)
232{
233 if (strncmp(option, optionLine, strlen(option)) == 0)
234 return true;
235 else
236 return false;
237}
238
Tony Barbour6918cd52015-04-09 12:58:51 -0600239void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600240{
241 int i, n;
242
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600243 for (i=1, n=1; i< *argc; i++) {
244 if (optionMatch("--show-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600245 m_show_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600246 else if (optionMatch("--save-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600247 m_save_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600248 else if (optionMatch("--no-SPV", argv[i]))
249 m_use_glsl = true;
250 else if (optionMatch("--strip-SPV", argv[i]))
251 m_strip_spv = true;
252 else if (optionMatch("--canonicalize-SPV", argv[i]))
253 m_canonicalize_spv = true;
254 else if (optionMatch("--compare-images", argv[i]))
Tony Barbour247bf372014-10-30 14:29:04 -0600255 m_compare_images = true;
Tony Barbour247bf372014-10-30 14:29:04 -0600256
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600257 else if (optionMatch("--help", argv[i]) ||
258 optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700259 printf("\nOther options:\n");
260 printf("\t--show-images\n"
261 "\t\tDisplay test images in viewer after tests complete.\n");
262 printf("\t--save-images\n"
263 "\t\tSave tests images as ppm files in current working directory.\n"
264 "\t\tUsed to generate golden images for compare-images.\n");
265 printf("\t--compare-images\n"
266 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barboura98d3932014-12-11 09:52:49 -0700267 "\t\tAlso saves the generated test image in current working\n"
268 "\t\t\tdirectory but only if the image is different from the golden\n"
269 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
270 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700271 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600272 printf("\t--no-SPV\n"
273 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600274 printf("\t--strip-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600275 "\t\tStrip SPIR-V debug information (line numbers, names, etc).\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600276 printf("\t--canonicalize-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600277 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600278 exit(0);
279 } else {
280 printf("\nUnrecognized option: %s\n", argv[i]);
281 printf("\nUse --help or -h for option list.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700282 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700283 }
284
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600285 /*
286 * Since the above "consume" inputs, update argv
287 * so that it contains the trimmed list of args for glutInit
288 */
289
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600290 argv[n] = argv[i];
291 n++;
292 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600293}
294
Tony Barbour6918cd52015-04-09 12:58:51 -0600295void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600296{
297 string filename;
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600298 VkResult err;
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600299 uint32_t x, y;
Tony Barbour6918cd52015-04-09 12:58:51 -0600300 VkImageObj displayImage(image->device());
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600301 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbour84d448c2015-04-02 14:02:33 -0600302
Tony Barboure65788f2015-07-21 17:01:42 -0600303 displayImage.init(image->extent().width, image->extent().height, image->format(), VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT, VK_IMAGE_TILING_LINEAR, reqs);
Tony Barbour84d448c2015-04-02 14:02:33 -0600304 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600305
306 filename.append(basename);
307 filename.append(".ppm");
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600308
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600309 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600310 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600311 };
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600312 VkSubresourceLayout sr_layout;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600313
Tony Barbour59a47322015-06-24 16:06:58 -0600314 err = vkGetImageSubresourceLayout(image->device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600315 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600316
Tony Barbour84d448c2015-04-02 14:02:33 -0600317 char *ptr;
Chia-I Wu681d7a02015-07-03 13:44:34 +0800318 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600319 ptr += sr_layout.offset;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600320 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600321 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
322
323 file << "P6\n";
Tony Barbour84d448c2015-04-02 14:02:33 -0600324 file << displayImage.width() << "\n";
325 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600326 file << 255 << "\n";
327
Tony Barbour84d448c2015-04-02 14:02:33 -0600328 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700329 const int *row = (const int *) ptr;
330 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600331
Tony Barbourd1c35722015-04-16 15:59:00 -0600332 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700333 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600334 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700335 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
336 file.write((char *) &swapped, 3);
337 row++;
338 }
339 }
Tony Barbourd1c35722015-04-16 15:59:00 -0600340 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700341 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600342 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700343 file.write((char *) row, 3);
344 row++;
345 }
346 }
347 else {
348 printf("Unrecognized image format - will not write image files");
349 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600350 }
351
352 ptr += sr_layout.rowPitch;
353 }
354
355 file.close();
Chia-I Wu681d7a02015-07-03 13:44:34 +0800356 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600357}
358
Tony Barbour6918cd52015-04-09 12:58:51 -0600359void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour247bf372014-10-30 14:29:04 -0600360{
361
362 MagickWand *magick_wand_1;
363 MagickWand *magick_wand_2;
364 MagickWand *compare_wand;
365 MagickBooleanType status;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600366 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600367 double differenz;
368
Tony Barbour4ab45422014-12-10 17:00:20 -0700369 if (getenv("RENDERTEST_GOLDEN_DIR"))
370 {
371 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
372 }
373
Tony Barbour247bf372014-10-30 14:29:04 -0600374 MagickWandGenesis();
375 magick_wand_1=NewMagickWand();
376 sprintf(testimage,"%s.ppm",basename);
377 status=MagickReadImage(magick_wand_1,testimage);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600378 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour247bf372014-10-30 14:29:04 -0600379
380
381 MagickWandGenesis();
382 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700383 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600384 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600385 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour247bf372014-10-30 14:29:04 -0600386
Tony Barbour247bf372014-10-30 14:29:04 -0600387 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
388 if (differenz != 0.0)
389 {
390 char difference[256];
391
392 sprintf(difference,"%s-diff.ppm",basename);
393 status = MagickWriteImage(compare_wand, difference);
394 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
395 }
396 DestroyMagickWand(compare_wand);
397
398 DestroyMagickWand(magick_wand_1);
399 DestroyMagickWand(magick_wand_2);
400 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700401
402 if (differenz == 0.0)
403 {
404 /*
405 * If test image and golden image match, we do not need to
406 * keep around the test image.
407 */
408 remove(testimage);
409 }
Tony Barbour247bf372014-10-30 14:29:04 -0600410}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600411
Tony Barbour6918cd52015-04-09 12:58:51 -0600412void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600413{
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600414 VkResult err;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600415 VkSubresourceLayout sr_layout;
416 char *ptr;
417 VkTestImageRecord record;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600418 VkImageObj displayImage(image->device());
419 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
420
Cody Northropc9a69912015-06-18 17:05:15 -0600421 displayImage.init(image->extent().width, image->extent().height, image->format(), VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT, VK_IMAGE_TILING_LINEAR, reqs);
422
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600423 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600424
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600425 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600426 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600427 };
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600428
Tony Barbour59a47322015-06-24 16:06:58 -0600429 err = vkGetImageSubresourceLayout(displayImage.device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600430 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600431
Chia-I Wu681d7a02015-07-03 13:44:34 +0800432 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600433 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600434
435 ptr += sr_layout.offset;
436
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600437 record.m_title.append(comment);
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600438 record.m_width = displayImage.width();
439 record.m_height = displayImage.height();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600440 // TODO: Need to make this more robust to handle different image formats
Tony-LunarG399dfca2015-05-19 14:08:26 -0600441 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600442 record.m_data = malloc(record.m_data_size);
443 memcpy(record.m_data, ptr, record.m_data_size);
444 m_images.push_back(record);
445 m_display_image = --m_images.end();
446
Chia-I Wu681d7a02015-07-03 13:44:34 +0800447 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600448}
449
Tony Barbour6918cd52015-04-09 12:58:51 -0600450void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600451{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600452 for (int32_t i = 0; i < images.size(); i++) {
453 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600454 }
455}
456
Tony Barbour6918cd52015-04-09 12:58:51 -0600457void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600458{
459 const ::testing::TestInfo* const test_info =
460 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600461 ostringstream filestream;
462 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600463
Tony Barbour247bf372014-10-30 14:29:04 -0600464 m_width = 40;
465
466 if (strcmp(test_info->name(), m_testName.c_str())) {
467 filestream << test_info->name();
468 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700469 m_frameNum = 2;
470 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600471 }
472 else {
473 filestream << test_info->name() << "-" << m_frameNum;
474 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700475 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600476 }
477
Tony Barbour247bf372014-10-30 14:29:04 -0600478 // ToDo - scrub string for bad characters
479
480 if (m_save_images || m_compare_images) {
481 WritePPM(filename.c_str(), image);
482 if (m_compare_images) {
483 Compare(filename.c_str(), image);
484 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600485 }
486
487 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600488 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600489 }
490}
491
Chia-I Wuf8693382015-04-16 22:02:10 +0800492TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
493 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700494 m_queue(*m_device.graphics_queues()[0]),
Dana Jansens233a0ea2015-07-30 13:04:16 -0700495 m_cmdpool(m_device, vk_testing::CmdPool::create_info(m_device.graphics_queue_node_index_)),
496 m_cmdbuf(m_device, vk_testing::CmdBuffer::create_info(m_cmdpool.handle()))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600497{
Tony Barbour96db8822015-02-25 12:28:39 -0700498 m_quit = false;
499 m_pause = false;
500 m_width = 0;
501 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600502}
503
Tony Barbour6918cd52015-04-09 12:58:51 -0600504void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600505{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600506 VkResult U_ASSERT_ONLY err;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600507 vk_testing::Buffer buf;
508 void *dest_ptr;
509
Tony Barbour6a3faf02015-07-23 10:36:18 -0600510 VkSemaphore presentCompleteSemaphore;
511 VkSemaphoreCreateInfo presentCompleteSemaphoreCreateInfo = {};
512 presentCompleteSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
513 presentCompleteSemaphoreCreateInfo.pNext = NULL;
514 presentCompleteSemaphoreCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
515
516
517 err = vkCreateSemaphore(m_device.handle(),
518 &presentCompleteSemaphoreCreateInfo,
519 &presentCompleteSemaphore);
520 assert(!err);
521
522 // Get the index of the next available swapchain image:
523 err = m_fpAcquireNextImageWSI(m_device.handle(), m_swap_chain,
524 UINT64_MAX,
525 presentCompleteSemaphore,
526 &m_current_buffer);
527 // TODO: Deal with the VK_SUBOPTIMAL_WSI and VK_ERROR_OUT_OF_DATE_WSI
528 // return codes
529 assert(!err);
530
531 // Wait for the present complete semaphore to be signaled to ensure
532 // that the image won't be rendered to until the presentation
533 // engine has fully released ownership to the application, and it is
534 // okay to render to the image.
535 vkQueueWaitSemaphore(m_queue.handle(), presentCompleteSemaphore);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600536
537 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Cody Northrop7fb43862015-06-22 14:56:14 -0600538 buf.init_as_src(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800539 dest_ptr = buf.memory().map();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600540 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800541 buf.memory().unmap();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600542
543 m_cmdbuf.begin();
544
545 VkBufferImageCopy region = {};
546 region.imageExtent.height = m_display_image->m_height;
547 region.imageExtent.width = m_display_image->m_width;
548 region.imageExtent.depth = 1;
549
Chia-I Wube2b9172015-07-03 11:49:42 +0800550 vkCmdCopyBufferToImage(m_cmdbuf.handle(),
Chia-I Wu681d7a02015-07-03 13:44:34 +0800551 buf.handle(),
Tony Barbour6a3faf02015-07-23 10:36:18 -0600552 m_buffers[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600553 1, &region);
554 m_cmdbuf.end();
555
556 VkCmdBuffer cmdBufs[1];
Chia-I Wube2b9172015-07-03 11:49:42 +0800557 cmdBufs[0] = m_cmdbuf.handle();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600558
Tony Barbour67e99152015-07-10 14:10:27 -0600559 VkFence nullFence = { VK_NULL_HANDLE };
560 vkQueueSubmit(m_queue.handle(), 1, cmdBufs, nullFence);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600561 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700562
Chia-I Wuf8693382015-04-16 22:02:10 +0800563 VkPresentInfoWSI present = {};
Ian Elliott1a3845b2015-07-06 14:33:04 -0600564 present.sType = VK_STRUCTURE_TYPE_QUEUE_PRESENT_INFO_WSI;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600565 present.pNext = NULL;
566 present.swapChainCount = 1;
567 present.swapChains = & m_swap_chain;
568 present.imageIndices = &m_current_buffer;
Tony Barbour96db8822015-02-25 12:28:39 -0700569
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600570#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800571 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700572 XCB_PROP_MODE_REPLACE,
573 m_window,
574 XCB_ATOM_WM_NAME,
575 XCB_ATOM_STRING,
576 8,
577 m_display_image->m_title.size(),
578 m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600579#endif
Jon Ashburn07daee72015-05-21 18:13:33 -0600580
Chia-I Wudf12ffd2015-07-03 10:53:18 +0800581 err = m_fpQueuePresentWSI(m_queue.handle(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700582 assert(!err);
583
584 m_queue.wait();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600585 m_current_buffer = (m_current_buffer + 1) % 2;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600586}
587
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600588#ifdef _WIN32
Tony-LunarG399dfca2015-05-19 14:08:26 -0600589# define PREVIOUSLY_DOWN 1<<29
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600590// MS-Windows event handling function:
591LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
592 UINT uMsg,
593 WPARAM wParam,
594 LPARAM lParam)
595{
596
597 switch(uMsg)
598 {
599 case WM_CLOSE:
600 PostQuitMessage(0);
601 break;
602
603 case WM_PAINT:
604 {
605 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
606 if (me) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600607 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600608 me->Display();
609 }
610 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600611 break;
612
613 case WM_KEYDOWN:
614 {
615 if (lParam & (PREVIOUSLY_DOWN)){
616 break;
617 }
618 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
619 // the window, we put the this pointer into the window's user data so we could get it back now
620 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
621 switch (wParam)
622 {
623 case VK_ESCAPE: me->m_quit = true;
624 break;
625
626 case VK_LEFT: // left arrow key
627 if (me->m_display_image == me->m_images.begin()) {
628 me->m_display_image = --me->m_images.end();
629 }
630 else {
631 --me->m_display_image;
632 }
633 break;
634
635 case VK_RIGHT: // right arrow key
636 ++me->m_display_image;
637 if (me->m_display_image == me->m_images.end()) {
638 me->m_display_image = me->m_images.begin();
639 }
640 break;
641
642 default:
643 break;
644 }
645 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
646 me->Display();
647 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600648 }
649 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
650}
651
652void TestFrameworkVkPresent::Run()
653{
654 MSG msg; // message
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600655
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600656 /* main message loop*/
Tony-LunarG399dfca2015-05-19 14:08:26 -0600657 while(! m_quit) {
658 GetMessage(&msg, m_window, 0, 0);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600659 if (msg.message == WM_QUIT) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600660 m_quit = true; //if found, quit app
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600661 } else {
662 /* Translate and dispatch to event queue*/
663 TranslateMessage(&msg);
664 DispatchMessage(&msg);
665 }
666 }
667}
668
669#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600670void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600671{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600672 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700673 switch (event_code) {
674 case XCB_EXPOSE:
675 Display(); // TODO: handle resize
676 break;
677 case XCB_CLIENT_MESSAGE:
678 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
679 (m_atom_wm_delete_window)->atom) {
680 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600681 }
682 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700683 case XCB_KEY_RELEASE:
684 {
685 const xcb_key_release_event_t *key =
686 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600687
Tony Barbour96db8822015-02-25 12:28:39 -0700688 switch (key->detail) {
689 case 0x9: // Escape
690 m_quit = true;
691 break;
692 case 0x71: // left arrow key
693 if (m_display_image == m_images.begin()) {
694 m_display_image = --m_images.end();
695 } else {
696 --m_display_image;
697 }
698 break;
699 case 0x72: // right arrow key
700 ++m_display_image;
701 if (m_display_image == m_images.end()) {
702 m_display_image = m_images.begin();
703 }
704 break;
705 case 0x41:
706 m_pause = !m_pause;
707 break;
708 }
709 Display();
710 }
711 break;
712 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600713 break;
714 }
Tony Barbour96db8822015-02-25 12:28:39 -0700715}
716
Tony Barbour6918cd52015-04-09 12:58:51 -0600717void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700718{
Chia-I Wuf8693382015-04-16 22:02:10 +0800719 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700720
721 while (! m_quit) {
722 xcb_generic_event_t *event;
723
724 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800725 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700726 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800727 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700728 }
729 if (event) {
730 HandleEvent(event);
731 free(event);
732 }
733 }
734}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600735#endif // _WIN32
Tony Barbour96db8822015-02-25 12:28:39 -0700736
Chia-I Wuf8693382015-04-16 22:02:10 +0800737void TestFrameworkVkPresent::CreateSwapChain()
Tony Barbour96db8822015-02-25 12:28:39 -0700738{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600739 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700740
Tony-LunarG399dfca2015-05-19 14:08:26 -0600741 m_display_image = m_images.begin();
742 m_current_buffer = 0;
743
Tony Barbour6a3faf02015-07-23 10:36:18 -0600744 // Construct the WSI surface description:
745 m_surface_description.sType = VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_WSI;
746 m_surface_description.pNext = NULL;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600747#ifdef _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -0600748 m_surface_description.platform = VK_PLATFORM_WIN32_WSI;
749 m_surface_description.pPlatformHandle = m_connection;
750 m_surface_description.pPlatformWindow = m_window;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600751#else // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -0600752 m_platform_handle_xcb.connection = m_connection;
753 m_platform_handle_xcb.root = m_screen->root;
754 m_surface_description.platform = VK_PLATFORM_XCB_WSI;
755 m_surface_description.pPlatformHandle = &m_platform_handle_xcb;
756 m_surface_description.pPlatformWindow = &m_window;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600757#endif // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -0600758
759 // Iterate over each queue to learn whether it supports presenting to WSI:
760 VkBool32 supportsPresent;
761 m_present_queue_node_index = UINT32_MAX;
762 std::vector<vk_testing::Queue *> queues = m_device.graphics_queues();
763 for (int i=0; i < queues.size(); i++)
764 {
765 int family_index = queues[i]->get_family_index();
766 m_fpGetPhysicalDeviceSurfaceSupportWSI(m_device.phy().handle(),
767 family_index,
768 (VkSurfaceDescriptionWSI *) &m_surface_description,
769 &supportsPresent);
770 if (supportsPresent) {
771 m_present_queue_node_index = family_index;
772 }
773 }
774
775 assert(m_present_queue_node_index != UINT32_MAX);
776
777
778 // Get the list of VkFormat's that are supported:
779 size_t formatsSize;
780 err = m_fpGetSurfaceInfoWSI(m_device.handle(),
781 (VkSurfaceDescriptionWSI *) &m_surface_description,
782 VK_SURFACE_INFO_TYPE_FORMATS_WSI,
783 &formatsSize, NULL);
784 assert(!err);
785 VkSurfaceFormatPropertiesWSI *surfFormats = (VkSurfaceFormatPropertiesWSI *)malloc(formatsSize);
786 err = m_fpGetSurfaceInfoWSI(m_device.handle(),
787 (VkSurfaceDescriptionWSI *) &m_surface_description,
788 VK_SURFACE_INFO_TYPE_FORMATS_WSI,
789 &formatsSize, surfFormats);
790 assert(!err);
791 // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
792 // the surface has no preferred format. Otherwise, at least one
793 // supported format will be returned.
794 size_t formatCount = formatsSize / sizeof(VkSurfaceFormatPropertiesWSI);
795 if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED)
796 {
797 m_format = VK_FORMAT_B8G8R8A8_UNORM;
798 }
799 else
800 {
801 assert(formatCount >= 1);
802 m_format = surfFormats[0].format;
803 }
804
805 // Check the surface proprties and formats
806 size_t capsSize;
807 size_t presentModesSize;
808 err = m_fpGetSurfaceInfoWSI(m_device.handle(),
809 (const VkSurfaceDescriptionWSI *)&m_surface_description,
810 VK_SURFACE_INFO_TYPE_PROPERTIES_WSI, &capsSize, NULL);
811 assert(!err);
812 err = m_fpGetSurfaceInfoWSI(m_device.handle(),
813 (const VkSurfaceDescriptionWSI *)&m_surface_description,
814 VK_SURFACE_INFO_TYPE_PRESENT_MODES_WSI, &presentModesSize, NULL);
815 assert(!err);
816
817 VkSurfacePropertiesWSI *surfProperties =
818 (VkSurfacePropertiesWSI *)malloc(capsSize);
819 VkSurfacePresentModePropertiesWSI *presentModes =
820 (VkSurfacePresentModePropertiesWSI *)malloc(presentModesSize);
821
822 err = m_fpGetSurfaceInfoWSI(m_device.handle(),
823 (const VkSurfaceDescriptionWSI *)&m_surface_description,
824 VK_SURFACE_INFO_TYPE_PROPERTIES_WSI, &capsSize, surfProperties);
825 assert(!err);
826 err = m_fpGetSurfaceInfoWSI(m_device.handle(),
827 (const VkSurfaceDescriptionWSI *)&m_surface_description,
828 VK_SURFACE_INFO_TYPE_PRESENT_MODES_WSI, &presentModesSize, presentModes);
829 assert(!err);
830
831 VkExtent2D swapChainExtent;
832 // width and height are either both -1, or both not -1.
833 if (surfProperties->currentExtent.width == -1)
834 {
835 // If the surface size is undefined, the size is set to
836 // the size of the images requested.
837 swapChainExtent.width = m_width;
838 swapChainExtent.height = m_height;
839 }
840 else
841 {
842 // If the surface size is defined, the swap chain size must match
843 swapChainExtent = surfProperties->currentExtent;
844 }
845
846 // If mailbox mode is available, use it, as is the lowest-latency non-
847 // tearing mode. If not, fall back to IMMEDIATE which should always be
848 // available.
849 VkPresentModeWSI swapChainPresentMode = VK_PRESENT_MODE_IMMEDIATE_WSI;
850 size_t presentModeCount = presentModesSize / sizeof(VkSurfacePresentModePropertiesWSI);
851 for (size_t i = 0; i < presentModeCount; i++) {
852 if (presentModes[i].presentMode == VK_PRESENT_MODE_MAILBOX_WSI) {
853 swapChainPresentMode = VK_PRESENT_MODE_MAILBOX_WSI;
854 break;
855 }
856 }
857
858 // Determine the number of VkImage's to use in the swap chain (we desire to
859 // own only 1 image at a time, besides the images being displayed and
860 // queued for display):
861 uint32_t desiredNumberOfSwapChainImages = surfProperties->minImageCount + 1;
862 if ((surfProperties->maxImageCount > 0) &&
863 (desiredNumberOfSwapChainImages > surfProperties->maxImageCount))
864 {
865 // Application must settle for fewer images than desired:
866 desiredNumberOfSwapChainImages = surfProperties->maxImageCount;
867 }
868
869 VkSurfaceTransformWSI preTransform;
870 if (surfProperties->supportedTransforms & VK_SURFACE_TRANSFORM_NONE_BIT_WSI) {
871 preTransform = VK_SURFACE_TRANSFORM_NONE_WSI;
872 } else {
873 preTransform = surfProperties->currentTransform;
874 }
Ian Elliott1a3845b2015-07-06 14:33:04 -0600875
Chia-I Wuf8693382015-04-16 22:02:10 +0800876 VkSwapChainCreateInfoWSI swap_chain = {};
877 swap_chain.sType = VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600878 swap_chain.pNext = NULL;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600879 swap_chain.pSurfaceDescription = (const VkSurfaceDescriptionWSI *)&m_surface_description;
880 swap_chain.minImageCount = desiredNumberOfSwapChainImages;
881 swap_chain.imageFormat = m_format;
882 swap_chain.imageExtent.width = swapChainExtent.width;
883 swap_chain.imageExtent.height = swapChainExtent.height;
884 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT;
885 swap_chain.preTransform = preTransform;
Chia-I Wuf8693382015-04-16 22:02:10 +0800886 swap_chain.imageArraySize = 1;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600887 swap_chain.presentMode = swapChainPresentMode;
888 swap_chain.oldSwapChain.handle = 0;
889 swap_chain.clipped = true;
890
891 uint32_t i;
Chia-I Wuf8693382015-04-16 22:02:10 +0800892
Chia-I Wuf368b602015-07-03 10:41:20 +0800893 err = m_fpCreateSwapChainWSI(m_device.handle(), &swap_chain, &m_swap_chain);
Chia-I Wuf8693382015-04-16 22:02:10 +0800894 assert(!err);
895
Tony Barbour6a3faf02015-07-23 10:36:18 -0600896 size_t swapChainImagesSize;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600897 err = m_fpGetSwapChainInfoWSI(m_device.handle(), m_swap_chain,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600898 VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI,
899 &swapChainImagesSize, NULL);
900 assert(!err);
901
902 VkSwapChainImagePropertiesWSI* swapChainImages = (VkSwapChainImagePropertiesWSI*)malloc(swapChainImagesSize);
903 assert(swapChainImages);
904 err = m_fpGetSwapChainInfoWSI(m_device.handle(), m_swap_chain,
905 VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI,
906 &swapChainImagesSize, swapChainImages);
907 assert(!err);
908
909 // The number of images within the swap chain is determined based on the
910 // size of the info returned
911 m_swapChainImageCount = swapChainImagesSize / sizeof(VkSwapChainImagePropertiesWSI);
912
913 m_buffers = (SwapChainBuffers*)malloc(sizeof(SwapChainBuffers)*m_swapChainImageCount);
914 assert(m_buffers);
915
916 for (i = 0; i < m_swapChainImageCount; i++) {
917 VkAttachmentViewCreateInfo color_attachment_view = {};
918 color_attachment_view.sType = VK_STRUCTURE_TYPE_ATTACHMENT_VIEW_CREATE_INFO;
919 color_attachment_view.pNext = NULL;
920 color_attachment_view.format = m_format;
921 color_attachment_view.mipLevel = 0;
922 color_attachment_view.baseArraySlice = 0;
923 color_attachment_view.arraySize = 1;
924
925 m_buffers[i].image = swapChainImages[i].image;
926
927 color_attachment_view.image = m_buffers[i].image;
928 err = vkCreateAttachmentView(m_device.handle(),
929 &color_attachment_view, &m_buffers[i].view);
930 assert(!err);
931 }
Tony Barbour96db8822015-02-25 12:28:39 -0700932}
933
Jon Ashburn07daee72015-05-21 18:13:33 -0600934void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -0700935{
Tony Barbour6a3faf02015-07-23 10:36:18 -0600936 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceSupportWSI);
937 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfaceInfoWSI);
938 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapChainWSI);
939 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapChainWSI);
940 GET_DEVICE_PROC_ADDR(m_device.handle(), DestroySwapChainWSI);
941 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSwapChainInfoWSI);
942 GET_DEVICE_PROC_ADDR(m_device.handle(), AcquireNextImageWSI);
943 GET_DEVICE_PROC_ADDR(m_device.handle(), QueuePresentWSI);
Jon Ashburn07daee72015-05-21 18:13:33 -0600944
Tony Barbour96db8822015-02-25 12:28:39 -0700945 m_images = imagesIn;
946}
947
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600948#ifdef _WIN32
949void TestFrameworkVkPresent::CreateMyWindow()
950{
951 WNDCLASSEX win_class;
952 // const ::testing::TestInfo* const test_info =
953 // ::testing::UnitTest::GetInstance()->current_test_info();
954 m_connection = GetModuleHandle(NULL);
955
956 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
957 it != m_images.end(); it++) {
958 if (m_width < it->m_width)
959 m_width = it->m_width;
960 if (m_height < it->m_height)
961 m_height = it->m_height;
962 }
963 // Initialize the window class structure:
964 win_class.cbSize = sizeof(WNDCLASSEX);
965 win_class.style = CS_HREDRAW | CS_VREDRAW;
966 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
967 win_class.cbClsExtra = 0;
968 win_class.cbWndExtra = 0;
969 win_class.hInstance = m_connection; // hInstance
970 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
971 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
972 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
973 win_class.lpszMenuName = NULL;
974 win_class.lpszClassName = "Test";
975 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
976 // Register window class:
977 if (!RegisterClassEx(&win_class)) {
978 // It didn't work, so try to give a useful error:
979 printf("Unexpected error trying to start the application!\n");
980 fflush(stdout);
981 exit(1);
982 }
983 // Create window with the registered class:
984 m_window = CreateWindowEx(0,
985 "Test", // class name
986 "Test", // app name
987 WS_OVERLAPPEDWINDOW | // window style
988 WS_VISIBLE |
989 WS_SYSMENU,
990 100,100, // x/y coords
991 m_width, // width
992 m_height, // height
993 NULL, // handle to parent
994 NULL, // handle to menu
995 m_connection, // hInstance
996 NULL); // no extra parameters
997
998 if (!m_window) {
999 // It didn't work, so try to give a useful error:
1000 DWORD error = GetLastError();
1001 char message[120];
1002 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
1003 MessageBox(NULL, message, "Error", MB_OK);
1004 exit(1);
1005 }
Tony-LunarG399dfca2015-05-19 14:08:26 -06001006 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
1007 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001008}
1009#else
Tony Barbour6918cd52015-04-09 12:58:51 -06001010void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -07001011{
Chia-I Wuf8693382015-04-16 22:02:10 +08001012 const xcb_setup_t *setup;
1013 xcb_screen_iterator_t iter;
1014 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -07001015 uint32_t value_mask, value_list[32];
1016
Chia-I Wuf8693382015-04-16 22:02:10 +08001017 m_connection = xcb_connect(NULL, &scr);
1018
1019 setup = xcb_get_setup(m_connection);
1020 iter = xcb_setup_roots_iterator(setup);
1021 while (scr-- > 0)
1022 xcb_screen_next(&iter);
1023
1024 m_screen = iter.data;
1025
1026 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1027 it != m_images.end(); it++) {
1028 if (m_width < it->m_width)
1029 m_width = it->m_width;
1030 if (m_height < it->m_height)
1031 m_height = it->m_height;
1032 }
1033
1034 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -07001035
1036 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +08001037 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -07001038 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
1039 XCB_EVENT_MASK_EXPOSURE |
1040 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
1041
Chia-I Wuf8693382015-04-16 22:02:10 +08001042 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -07001043 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001044 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -07001045 0, 0, m_width, m_height, 0,
1046 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001047 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -07001048 value_mask, value_list);
1049
1050 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +08001051 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -07001052 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +08001053 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001054
Chia-I Wuf8693382015-04-16 22:02:10 +08001055 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
1056 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001057
Chia-I Wuf8693382015-04-16 22:02:10 +08001058 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -07001059 m_window, (*reply).atom, 4, 32, 1,
1060 &(*m_atom_wm_delete_window).atom);
1061 free(reply);
1062
Chia-I Wuf8693382015-04-16 22:02:10 +08001063 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -07001064}
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001065#endif
Tony Barbour96db8822015-02-25 12:28:39 -07001066
Tony Barbour6918cd52015-04-09 12:58:51 -06001067void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -07001068{
Ian Elliott1a3845b2015-07-06 14:33:04 -06001069 m_fpDestroySwapChainWSI(m_device.handle(), m_swap_chain);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001070#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +08001071 xcb_destroy_window(m_connection, m_window);
1072 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001073#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001074}
1075
Tony Barbour6918cd52015-04-09 12:58:51 -06001076void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001077{
1078 if (m_images.size() == 0) return;
1079
Chia-I Wuf8693382015-04-16 22:02:10 +08001080 vk_testing::Environment env;
1081 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -07001082 {
Chia-I Wuf8693382015-04-16 22:02:10 +08001083 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -07001084
Jon Ashburn07daee72015-05-21 18:13:33 -06001085 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001086 vkPresent.CreateMyWindow();
Chia-I Wuf8693382015-04-16 22:02:10 +08001087 vkPresent.CreateSwapChain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001088 vkPresent.Run();
1089 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -07001090 }
Chia-I Wuf8693382015-04-16 22:02:10 +08001091 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001092}
1093
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001094//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001095// These are the default resources for TBuiltInResources, used for both
1096// - parsing this string for the case where the user didn't supply one
1097// - dumping out a template for user construction of a config file
1098//
1099static const char* DefaultConfig =
1100 "MaxLights 32\n"
1101 "MaxClipPlanes 6\n"
1102 "MaxTextureUnits 32\n"
1103 "MaxTextureCoords 32\n"
1104 "MaxVertexAttribs 64\n"
1105 "MaxVertexUniformComponents 4096\n"
1106 "MaxVaryingFloats 64\n"
1107 "MaxVertexTextureImageUnits 32\n"
1108 "MaxCombinedTextureImageUnits 80\n"
1109 "MaxTextureImageUnits 32\n"
1110 "MaxFragmentUniformComponents 4096\n"
1111 "MaxDrawBuffers 32\n"
1112 "MaxVertexUniformVectors 128\n"
1113 "MaxVaryingVectors 8\n"
1114 "MaxFragmentUniformVectors 16\n"
1115 "MaxVertexOutputVectors 16\n"
1116 "MaxFragmentInputVectors 15\n"
1117 "MinProgramTexelOffset -8\n"
1118 "MaxProgramTexelOffset 7\n"
1119 "MaxClipDistances 8\n"
1120 "MaxComputeWorkGroupCountX 65535\n"
1121 "MaxComputeWorkGroupCountY 65535\n"
1122 "MaxComputeWorkGroupCountZ 65535\n"
1123 "MaxComputeWorkGroupSizeX 1024\n"
1124 "MaxComputeWorkGroupSizeY 1024\n"
1125 "MaxComputeWorkGroupSizeZ 64\n"
1126 "MaxComputeUniformComponents 1024\n"
1127 "MaxComputeTextureImageUnits 16\n"
1128 "MaxComputeImageUniforms 8\n"
1129 "MaxComputeAtomicCounters 8\n"
1130 "MaxComputeAtomicCounterBuffers 1\n"
1131 "MaxVaryingComponents 60\n"
1132 "MaxVertexOutputComponents 64\n"
1133 "MaxGeometryInputComponents 64\n"
1134 "MaxGeometryOutputComponents 128\n"
1135 "MaxFragmentInputComponents 128\n"
1136 "MaxImageUnits 8\n"
1137 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
1138 "MaxCombinedShaderOutputResources 8\n"
1139 "MaxImageSamples 0\n"
1140 "MaxVertexImageUniforms 0\n"
1141 "MaxTessControlImageUniforms 0\n"
1142 "MaxTessEvaluationImageUniforms 0\n"
1143 "MaxGeometryImageUniforms 0\n"
1144 "MaxFragmentImageUniforms 8\n"
1145 "MaxCombinedImageUniforms 8\n"
1146 "MaxGeometryTextureImageUnits 16\n"
1147 "MaxGeometryOutputVertices 256\n"
1148 "MaxGeometryTotalOutputComponents 1024\n"
1149 "MaxGeometryUniformComponents 1024\n"
1150 "MaxGeometryVaryingComponents 64\n"
1151 "MaxTessControlInputComponents 128\n"
1152 "MaxTessControlOutputComponents 128\n"
1153 "MaxTessControlTextureImageUnits 16\n"
1154 "MaxTessControlUniformComponents 1024\n"
1155 "MaxTessControlTotalOutputComponents 4096\n"
1156 "MaxTessEvaluationInputComponents 128\n"
1157 "MaxTessEvaluationOutputComponents 128\n"
1158 "MaxTessEvaluationTextureImageUnits 16\n"
1159 "MaxTessEvaluationUniformComponents 1024\n"
1160 "MaxTessPatchComponents 120\n"
1161 "MaxPatchVertices 32\n"
1162 "MaxTessGenLevel 64\n"
1163 "MaxViewports 16\n"
1164 "MaxVertexAtomicCounters 0\n"
1165 "MaxTessControlAtomicCounters 0\n"
1166 "MaxTessEvaluationAtomicCounters 0\n"
1167 "MaxGeometryAtomicCounters 0\n"
1168 "MaxFragmentAtomicCounters 8\n"
1169 "MaxCombinedAtomicCounters 8\n"
1170 "MaxAtomicCounterBindings 1\n"
1171 "MaxVertexAtomicCounterBuffers 0\n"
1172 "MaxTessControlAtomicCounterBuffers 0\n"
1173 "MaxTessEvaluationAtomicCounterBuffers 0\n"
1174 "MaxGeometryAtomicCounterBuffers 0\n"
1175 "MaxFragmentAtomicCounterBuffers 1\n"
1176 "MaxCombinedAtomicCounterBuffers 1\n"
1177 "MaxAtomicCounterBufferSize 16384\n"
1178 "MaxTransformFeedbackBuffers 4\n"
1179 "MaxTransformFeedbackInterleavedComponents 64\n"
1180 "MaxCullDistances 8\n"
1181 "MaxCombinedClipAndCullDistances 8\n"
1182 "MaxSamples 4\n"
1183
1184 "nonInductiveForLoops 1\n"
1185 "whileLoops 1\n"
1186 "doWhileLoops 1\n"
1187 "generalUniformIndexing 1\n"
1188 "generalAttributeMatrixVectorIndexing 1\n"
1189 "generalVaryingIndexing 1\n"
1190 "generalSamplerIndexing 1\n"
1191 "generalVariableIndexing 1\n"
1192 "generalConstantMatrixVectorIndexing 1\n"
1193 ;
1194
1195//
1196// *.conf => this is a config file that can set limits/resources
1197//
Tony Barbour6918cd52015-04-09 12:58:51 -06001198bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001199{
1200 if (name.size() < 5)
1201 return false;
1202
1203 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
1204 ConfigFile = name;
1205 return true;
1206 }
1207
1208 return false;
1209}
1210
1211//
1212// Parse either a .conf file provided by the user or the default string above.
1213//
Tony Barbour6918cd52015-04-09 12:58:51 -06001214void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001215{
1216 char** configStrings = 0;
1217 char* config = 0;
1218 if (ConfigFile.size() > 0) {
1219 configStrings = ReadFileData(ConfigFile.c_str());
1220 if (configStrings)
1221 config = *configStrings;
1222 else {
1223 printf("Error opening configuration file; will instead use the default configuration\n");
1224 }
1225 }
1226
1227 if (config == 0) {
1228 config = new char[strlen(DefaultConfig) + 1];
1229 strcpy(config, DefaultConfig);
1230 }
1231
1232 const char* delims = " \t\n\r";
1233 const char* token = strtok(config, delims);
1234 while (token) {
1235 const char* valueStr = strtok(0, delims);
1236 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1237 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1238 return;
1239 }
1240 int value = atoi(valueStr);
1241
1242 if (strcmp(token, "MaxLights") == 0)
1243 Resources.maxLights = value;
1244 else if (strcmp(token, "MaxClipPlanes") == 0)
1245 Resources.maxClipPlanes = value;
1246 else if (strcmp(token, "MaxTextureUnits") == 0)
1247 Resources.maxTextureUnits = value;
1248 else if (strcmp(token, "MaxTextureCoords") == 0)
1249 Resources.maxTextureCoords = value;
1250 else if (strcmp(token, "MaxVertexAttribs") == 0)
1251 Resources.maxVertexAttribs = value;
1252 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1253 Resources.maxVertexUniformComponents = value;
1254 else if (strcmp(token, "MaxVaryingFloats") == 0)
1255 Resources.maxVaryingFloats = value;
1256 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1257 Resources.maxVertexTextureImageUnits = value;
1258 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1259 Resources.maxCombinedTextureImageUnits = value;
1260 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1261 Resources.maxTextureImageUnits = value;
1262 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1263 Resources.maxFragmentUniformComponents = value;
1264 else if (strcmp(token, "MaxDrawBuffers") == 0)
1265 Resources.maxDrawBuffers = value;
1266 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1267 Resources.maxVertexUniformVectors = value;
1268 else if (strcmp(token, "MaxVaryingVectors") == 0)
1269 Resources.maxVaryingVectors = value;
1270 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1271 Resources.maxFragmentUniformVectors = value;
1272 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1273 Resources.maxVertexOutputVectors = value;
1274 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1275 Resources.maxFragmentInputVectors = value;
1276 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1277 Resources.minProgramTexelOffset = value;
1278 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1279 Resources.maxProgramTexelOffset = value;
1280 else if (strcmp(token, "MaxClipDistances") == 0)
1281 Resources.maxClipDistances = value;
1282 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1283 Resources.maxComputeWorkGroupCountX = value;
1284 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1285 Resources.maxComputeWorkGroupCountY = value;
1286 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1287 Resources.maxComputeWorkGroupCountZ = value;
1288 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1289 Resources.maxComputeWorkGroupSizeX = value;
1290 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1291 Resources.maxComputeWorkGroupSizeY = value;
1292 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1293 Resources.maxComputeWorkGroupSizeZ = value;
1294 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1295 Resources.maxComputeUniformComponents = value;
1296 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1297 Resources.maxComputeTextureImageUnits = value;
1298 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1299 Resources.maxComputeImageUniforms = value;
1300 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1301 Resources.maxComputeAtomicCounters = value;
1302 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1303 Resources.maxComputeAtomicCounterBuffers = value;
1304 else if (strcmp(token, "MaxVaryingComponents") == 0)
1305 Resources.maxVaryingComponents = value;
1306 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1307 Resources.maxVertexOutputComponents = value;
1308 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1309 Resources.maxGeometryInputComponents = value;
1310 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1311 Resources.maxGeometryOutputComponents = value;
1312 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1313 Resources.maxFragmentInputComponents = value;
1314 else if (strcmp(token, "MaxImageUnits") == 0)
1315 Resources.maxImageUnits = value;
1316 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1317 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1318 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1319 Resources.maxCombinedShaderOutputResources = value;
1320 else if (strcmp(token, "MaxImageSamples") == 0)
1321 Resources.maxImageSamples = value;
1322 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1323 Resources.maxVertexImageUniforms = value;
1324 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1325 Resources.maxTessControlImageUniforms = value;
1326 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1327 Resources.maxTessEvaluationImageUniforms = value;
1328 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1329 Resources.maxGeometryImageUniforms = value;
1330 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1331 Resources.maxFragmentImageUniforms = value;
1332 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1333 Resources.maxCombinedImageUniforms = value;
1334 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1335 Resources.maxGeometryTextureImageUnits = value;
1336 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1337 Resources.maxGeometryOutputVertices = value;
1338 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1339 Resources.maxGeometryTotalOutputComponents = value;
1340 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1341 Resources.maxGeometryUniformComponents = value;
1342 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1343 Resources.maxGeometryVaryingComponents = value;
1344 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1345 Resources.maxTessControlInputComponents = value;
1346 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1347 Resources.maxTessControlOutputComponents = value;
1348 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1349 Resources.maxTessControlTextureImageUnits = value;
1350 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1351 Resources.maxTessControlUniformComponents = value;
1352 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1353 Resources.maxTessControlTotalOutputComponents = value;
1354 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1355 Resources.maxTessEvaluationInputComponents = value;
1356 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1357 Resources.maxTessEvaluationOutputComponents = value;
1358 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1359 Resources.maxTessEvaluationTextureImageUnits = value;
1360 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1361 Resources.maxTessEvaluationUniformComponents = value;
1362 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1363 Resources.maxTessPatchComponents = value;
1364 else if (strcmp(token, "MaxPatchVertices") == 0)
1365 Resources.maxPatchVertices = value;
1366 else if (strcmp(token, "MaxTessGenLevel") == 0)
1367 Resources.maxTessGenLevel = value;
1368 else if (strcmp(token, "MaxViewports") == 0)
1369 Resources.maxViewports = value;
1370 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1371 Resources.maxVertexAtomicCounters = value;
1372 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1373 Resources.maxTessControlAtomicCounters = value;
1374 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1375 Resources.maxTessEvaluationAtomicCounters = value;
1376 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1377 Resources.maxGeometryAtomicCounters = value;
1378 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1379 Resources.maxFragmentAtomicCounters = value;
1380 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1381 Resources.maxCombinedAtomicCounters = value;
1382 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1383 Resources.maxAtomicCounterBindings = value;
1384 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1385 Resources.maxVertexAtomicCounterBuffers = value;
1386 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1387 Resources.maxTessControlAtomicCounterBuffers = value;
1388 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1389 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1390 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1391 Resources.maxGeometryAtomicCounterBuffers = value;
1392 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1393 Resources.maxFragmentAtomicCounterBuffers = value;
1394 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1395 Resources.maxCombinedAtomicCounterBuffers = value;
1396 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1397 Resources.maxAtomicCounterBufferSize = value;
1398 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1399 Resources.maxTransformFeedbackBuffers = value;
1400 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1401 Resources.maxTransformFeedbackInterleavedComponents = value;
1402 else if (strcmp(token, "MaxCullDistances") == 0)
1403 Resources.maxCullDistances = value;
1404 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1405 Resources.maxCombinedClipAndCullDistances = value;
1406 else if (strcmp(token, "MaxSamples") == 0)
1407 Resources.maxSamples = value;
1408
1409 else if (strcmp(token, "nonInductiveForLoops") == 0)
1410 Resources.limits.nonInductiveForLoops = (value != 0);
1411 else if (strcmp(token, "whileLoops") == 0)
1412 Resources.limits.whileLoops = (value != 0);
1413 else if (strcmp(token, "doWhileLoops") == 0)
1414 Resources.limits.doWhileLoops = (value != 0);
1415 else if (strcmp(token, "generalUniformIndexing") == 0)
1416 Resources.limits.generalUniformIndexing = (value != 0);
1417 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1418 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1419 else if (strcmp(token, "generalVaryingIndexing") == 0)
1420 Resources.limits.generalVaryingIndexing = (value != 0);
1421 else if (strcmp(token, "generalSamplerIndexing") == 0)
1422 Resources.limits.generalSamplerIndexing = (value != 0);
1423 else if (strcmp(token, "generalVariableIndexing") == 0)
1424 Resources.limits.generalVariableIndexing = (value != 0);
1425 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1426 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1427 else
1428 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1429
1430 token = strtok(0, delims);
1431 }
1432 if (configStrings)
1433 FreeFileData(configStrings);
1434}
1435
Tony Barbour6918cd52015-04-09 12:58:51 -06001436void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001437{
1438 if (m_compile_options & EOptionRelaxedErrors)
1439 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1440 if (m_compile_options & EOptionIntermediate)
1441 messages = (EShMessages)(messages | EShMsgAST);
1442 if (m_compile_options & EOptionSuppressWarnings)
1443 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1444}
1445
1446//
1447// Malloc a string of sufficient size and read a string into it.
1448//
Tony Barbour6918cd52015-04-09 12:58:51 -06001449char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001450{
1451 FILE *in;
1452 #if defined(_WIN32) && defined(__GNUC__)
1453 in = fopen(fileName, "r");
1454 int errorCode = in ? 0 : 1;
1455 #else
1456 int errorCode = fopen_s(&in, fileName, "r");
1457 #endif
1458
1459 char *fdata;
1460 int count = 0;
1461 const int maxSourceStrings = 5;
1462 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1463
1464 if (errorCode) {
1465 printf("Error: unable to open input file: %s\n", fileName);
1466 return 0;
1467 }
1468
1469 while (fgetc(in) != EOF)
1470 count++;
1471
1472 fseek(in, 0, SEEK_SET);
1473
1474 if (!(fdata = (char*)malloc(count+2))) {
1475 printf("Error allocating memory\n");
1476 return 0;
1477 }
1478 if (fread(fdata,1,count, in)!=count) {
1479 printf("Error reading input file: %s\n", fileName);
1480 return 0;
1481 }
1482 fdata[count] = '\0';
1483 fclose(in);
1484 if (count == 0) {
1485 return_data[0]=(char*)malloc(count+2);
1486 return_data[0][0]='\0';
1487 m_num_shader_strings = 0;
1488 return return_data;
1489 } else
1490 m_num_shader_strings = 1;
1491
1492 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1493 int ptr_len=0,i=0;
1494 while(count>0){
1495 return_data[i]=(char*)malloc(len+2);
1496 memcpy(return_data[i],fdata+ptr_len,len);
1497 return_data[i][len]='\0';
1498 count-=(len);
1499 ptr_len+=(len);
1500 if(count<len){
1501 if(count==0){
1502 m_num_shader_strings=(i+1);
1503 break;
1504 }
1505 len = count;
1506 }
1507 ++i;
1508 }
1509 return return_data;
1510}
1511
Tony Barbour6918cd52015-04-09 12:58:51 -06001512void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001513{
1514 for(int i=0;i<m_num_shader_strings;i++)
1515 free(data[i]);
1516}
1517
1518//
1519// Deduce the language from the filename. Files must end in one of the
1520// following extensions:
1521//
1522// .vert = vertex
1523// .tesc = tessellation control
1524// .tese = tessellation evaluation
1525// .geom = geometry
1526// .frag = fragment
1527// .comp = compute
1528//
Tony Barbour6918cd52015-04-09 12:58:51 -06001529EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001530{
1531 size_t ext = name.rfind('.');
1532 if (ext == std::string::npos) {
1533 return EShLangVertex;
1534 }
1535
1536 std::string suffix = name.substr(ext + 1, std::string::npos);
1537 if (suffix == "vert")
1538 return EShLangVertex;
1539 else if (suffix == "tesc")
1540 return EShLangTessControl;
1541 else if (suffix == "tese")
1542 return EShLangTessEvaluation;
1543 else if (suffix == "geom")
1544 return EShLangGeometry;
1545 else if (suffix == "frag")
1546 return EShLangFragment;
1547 else if (suffix == "comp")
1548 return EShLangCompute;
1549
1550 return EShLangVertex;
1551}
1552
1553//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001554// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001555//
Tony Barbourd1c35722015-04-16 15:59:00 -06001556EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001557{
1558 switch (shader_type) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001559 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001560 return EShLangVertex;
1561
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001562 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001563 return EShLangTessControl;
1564
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001565 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001566 return EShLangTessEvaluation;
1567
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001568 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001569 return EShLangGeometry;
1570
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001571 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001572 return EShLangFragment;
1573
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001574 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001575 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001576
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001577 default:
1578 return EShLangVertex;
1579 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001580}
1581
1582
1583//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001584// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001585// Return value of false means an error was encountered.
1586//
Tony Barbourd1c35722015-04-16 15:59:00 -06001587bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001588 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001589 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001590{
1591 glslang::TProgram& program = *new glslang::TProgram;
1592 const char *shaderStrings[1];
1593
1594 // TODO: Do we want to load a special config file depending on the
1595 // shader source? Optional name maybe?
1596 // SetConfigFile(fileName);
1597
1598 ProcessConfigFile();
1599
1600 EShMessages messages = EShMsgDefault;
1601 SetMessageOptions(messages);
1602
1603 EShLanguage stage = FindLanguage(shader_type);
1604 glslang::TShader* shader = new glslang::TShader(stage);
1605
1606 shaderStrings[0] = pshader;
1607 shader->setStrings(shaderStrings, 1);
1608
1609 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1610
Cody Northrop195d6622014-11-03 12:54:37 -07001611 if (! (m_compile_options & EOptionSuppressInfolog)) {
1612 puts(shader->getInfoLog());
1613 puts(shader->getInfoDebugLog());
1614 }
1615
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001616 return false; // something didn't work
1617 }
1618
1619 program.addShader(shader);
1620
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001621
1622 //
1623 // Program-level processing...
1624 //
1625
Cody Northrop195d6622014-11-03 12:54:37 -07001626 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001627
Cody Northrop195d6622014-11-03 12:54:37 -07001628 if (! (m_compile_options & EOptionSuppressInfolog)) {
1629 puts(shader->getInfoLog());
1630 puts(shader->getInfoDebugLog());
1631 }
1632
1633 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001634 }
1635
1636 if (m_compile_options & EOptionDumpReflection) {
1637 program.buildReflection();
1638 program.dumpReflection();
1639 }
1640
Cody Northrop5a95b472015-06-03 13:01:54 -06001641 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1642
1643 //
1644 // Test the different modes of SPIR-V modification
1645 //
1646 if (this->m_canonicalize_spv) {
1647 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1648 }
1649
1650 if (this->m_strip_spv) {
1651 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1652 }
1653
1654 if (this->m_do_everything_spv) {
1655 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1656 }
1657
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001658
1659 return true;
1660}
1661
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001662
1663
Tony Barbour6918cd52015-04-09 12:58:51 -06001664VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001665 m_width( 0 ),
1666 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001667 m_data( NULL ),
1668 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001669{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001670}
1671
Tony Barbour6918cd52015-04-09 12:58:51 -06001672VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001673{
1674
1675}
1676
Tony Barbour6918cd52015-04-09 12:58:51 -06001677VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001678{
1679 m_title = copyin.m_title;
1680 m_width = copyin.m_width;
1681 m_height = copyin.m_height;
1682 m_data_size = copyin.m_data_size;
1683 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1684}
1685
Tony Barbour6918cd52015-04-09 12:58:51 -06001686ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001687{
Tony Barbour6918cd52015-04-09 12:58:51 -06001688 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1689 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001690 return output;
1691}
1692
Tony Barbour6918cd52015-04-09 12:58:51 -06001693VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001694{
1695 m_title = rhs.m_title;
1696 m_width = rhs.m_width;
1697 m_height = rhs.m_height;
1698 m_data_size = rhs.m_data_size;
1699 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001700 return *this;
1701}
1702
Tony Barbour6918cd52015-04-09 12:58:51 -06001703int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001704{
1705 if( this->m_data != rhs.m_data) return 0;
1706 return 1;
1707}
1708
1709// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001710int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001711{
1712 if( this->m_data_size < rhs.m_data_size ) return 1;
1713 return 0;
1714}
1715