blob: 5e1fbfa58ab5f16e8a2bfac49d54947b1853c21b [file] [log] [blame]
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001//
Courtney Goeltzenleuchterfcbe16f2015-10-29 13:50:34 -06002// Copyright (C) 2015 Valve Corporation
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06003//
4// Permission is hereby granted, free of charge, to any person obtaining a
5// copy of this software and associated documentation files (the "Software"),
6// to deal in the Software without restriction, including without limitation
7// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8// and/or sell copies of the Software, and to permit persons to whom the
9// Software is furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included
12// in all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060021//
22// Author: Chia-I Wu <olv@lunarg.com>
23// Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
24// Author: Tony Barbour <tony@LunarG.com>
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -060025
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060026#include "vktestframework.h"
27#include "vkrenderframework.h"
Jon Ashburn94207e92015-12-04 17:03:59 -070028//TODO FIXME remove this once glslang doesn't define this
29#undef BadValue
Cody Northrop5a95b472015-06-03 13:01:54 -060030#include "SPIRV/GlslangToSpv.h"
31#include "SPIRV/SPVRemapper.h"
Tony Barbour4ab45422014-12-10 17:00:20 -070032#include <limits.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060033#include <math.h>
Chia-I Wuec664fa2014-12-02 11:54:24 +080034#include <wand/MagickWand.h>
Jon Ashburn94207e92015-12-04 17:03:59 -070035
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060036
Tony Barbour3d69c9e2015-05-20 16:53:31 -060037#if defined(PATH_MAX) && !defined(MAX_PATH)
38#define MAX_PATH PATH_MAX
39#endif
40
Tony Barbour6a3faf02015-07-23 10:36:18 -060041#ifdef _WIN32
42#define ERR_EXIT(err_msg, err_class) \
43 do { \
44 MessageBox(NULL, err_msg, err_class, MB_OK); \
45 exit(1); \
46 } while (0)
47#else // _WIN32
48
49#define ERR_EXIT(err_msg, err_class) \
50 do { \
51 printf(err_msg); \
52 fflush(stdout); \
53 exit(1); \
54 } while (0)
55#endif // _WIN32
56
57#define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \
58{ \
59 m_fp##entrypoint = (PFN_vk##entrypoint) vkGetInstanceProcAddr(inst, "vk"#entrypoint); \
60 if (m_fp##entrypoint == NULL) { \
61 ERR_EXIT("vkGetInstanceProcAddr failed to find vk"#entrypoint, \
62 "vkGetInstanceProcAddr Failure"); \
63 } \
64}
65
66#define GET_DEVICE_PROC_ADDR(dev, entrypoint) \
67{ \
68 m_fp##entrypoint = (PFN_vk##entrypoint) vkGetDeviceProcAddr(dev, "vk"#entrypoint); \
69 if (m_fp##entrypoint == NULL) { \
70 ERR_EXIT("vkGetDeviceProcAddr failed to find vk"#entrypoint, \
71 "vkGetDeviceProcAddr Failure"); \
72 } \
73}
74
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060075// Command-line options
76enum TOptions {
77 EOptionNone = 0x000,
78 EOptionIntermediate = 0x001,
79 EOptionSuppressInfolog = 0x002,
80 EOptionMemoryLeakMode = 0x004,
81 EOptionRelaxedErrors = 0x008,
82 EOptionGiveWarnings = 0x010,
83 EOptionLinkProgram = 0x020,
84 EOptionMultiThreaded = 0x040,
85 EOptionDumpConfig = 0x080,
86 EOptionDumpReflection = 0x100,
87 EOptionSuppressWarnings = 0x200,
88 EOptionDumpVersions = 0x400,
Cody Northrop3bfd27c2015-03-17 15:55:58 -060089 EOptionSpv = 0x800,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060090 EOptionDefaultDesktop = 0x1000,
91};
92
Ian Elliott7e40db92015-08-21 15:09:33 -060093typedef struct _SwapchainBuffers {
Tony Barbour6a3faf02015-07-23 10:36:18 -060094 VkImage image;
Chia-I Wu3432a0c2015-10-27 18:04:07 +080095 VkCommandBuffer cmd;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -060096 VkImageView view;
Ian Elliott7e40db92015-08-21 15:09:33 -060097} SwapchainBuffers;
Tony Barbour6a3faf02015-07-23 10:36:18 -060098
Chia-I Wuf8693382015-04-16 22:02:10 +080099class TestFrameworkVkPresent
100{
101public:
102 TestFrameworkVkPresent(vk_testing::Device &device);
103
104 void Run();
Jon Ashburn07daee72015-05-21 18:13:33 -0600105 void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst);
Chia-I Wuf8693382015-04-16 22:02:10 +0800106 void CreateMyWindow();
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700107 VkFormat GetPresentFormat();
Tony Barboure1837292015-12-07 13:46:11 -0700108 void DestroyMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -0600109 void CreateSwapchain();
Tony Barbourbd094ce2015-10-23 11:00:15 -0600110 void SetImageLayout(VkImage image, VkImageAspectFlags aspectMask,
111 VkImageLayout old_image_layout, VkImageLayout new_image_layout);
Chia-I Wuf8693382015-04-16 22:02:10 +0800112 void TearDown();
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600113#ifdef _WIN32
114 static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
115#endif
116
Chia-I Wuf8693382015-04-16 22:02:10 +0800117
118protected:
119 vk_testing::Device &m_device;
120 vk_testing::Queue &m_queue;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800121 vk_testing::CommandPool m_cmdpool;
122 vk_testing::CommandBuffer m_cmdbuf;
Chia-I Wuf8693382015-04-16 22:02:10 +0800123
124private:
Ian Elliottc11750d2015-10-30 13:24:12 -0600125 VkInstance m_instance;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600126#ifdef _WIN32
127 HINSTANCE m_connection; // hInstance - Windows Instance
128 HWND m_window; // hWnd - window handle
129
130#else
Chia-I Wuf8693382015-04-16 22:02:10 +0800131 xcb_connection_t *m_connection;
132 xcb_screen_t *m_screen;
133 xcb_window_t m_window;
134 xcb_intern_atom_reply_t *m_atom_wm_delete_window;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600135#endif
Ian Elliottc11750d2015-10-30 13:24:12 -0600136 VkSurfaceKHR m_surface;
Courtney Goeltzenleuchterd6079ec2015-04-22 10:09:35 -0600137 std::list<VkTestImageRecord> m_images;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600138 uint32_t m_present_queue_node_index;
Chia-I Wuf8693382015-04-16 22:02:10 +0800139
Ian Elliott7e40db92015-08-21 15:09:33 -0600140 PFN_vkGetPhysicalDeviceSurfaceSupportKHR m_fpGetPhysicalDeviceSurfaceSupportKHR;
Ian Elliottc11750d2015-10-30 13:24:12 -0600141 PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR m_fpGetPhysicalDeviceSurfaceCapabilitiesKHR;
142 PFN_vkGetPhysicalDeviceSurfaceFormatsKHR m_fpGetPhysicalDeviceSurfaceFormatsKHR;
143 PFN_vkGetPhysicalDeviceSurfacePresentModesKHR m_fpGetPhysicalDeviceSurfacePresentModesKHR;
Ian Elliott7e40db92015-08-21 15:09:33 -0600144 PFN_vkCreateSwapchainKHR m_fpCreateSwapchainKHR;
145 PFN_vkDestroySwapchainKHR m_fpDestroySwapchainKHR;
146 PFN_vkGetSwapchainImagesKHR m_fpGetSwapchainImagesKHR;
147 PFN_vkAcquireNextImageKHR m_fpAcquireNextImageKHR;
148 PFN_vkQueuePresentKHR m_fpQueuePresentKHR;
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700149 PFN_vkDestroySurfaceKHR m_fpDestroySurfaceKHR;
Ian Elliott7e40db92015-08-21 15:09:33 -0600150 uint32_t m_swapchainImageCount;
151 VkSwapchainKHR m_swap_chain;
152 SwapchainBuffers *m_buffers;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600153 VkFormat m_format;
Ian Elliott7e40db92015-08-21 15:09:33 -0600154 VkColorSpaceKHR m_color_space;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600155
156 uint32_t m_current_buffer;
Chia-I Wuf8693382015-04-16 22:02:10 +0800157
158 bool m_quit;
159 bool m_pause;
160
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600161 int m_width;
162 int m_height;
Chia-I Wuf8693382015-04-16 22:02:10 +0800163
164 std::list<VkTestImageRecord>::iterator m_display_image;
165
166 void Display();
Tony Barbourfeb61962015-09-21 15:17:33 -0600167#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800168 void HandleEvent(xcb_generic_event_t *event);
Tony Barbourfeb61962015-09-21 15:17:33 -0600169#endif
Chia-I Wuf8693382015-04-16 22:02:10 +0800170};
171
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600172#ifndef _WIN32
173
174#include <errno.h>
175
176int fopen_s(
177 FILE** pFile,
178 const char* filename,
179 const char* mode
180)
181{
182 if (!pFile || !filename || !mode) {
183 return EINVAL;
184 }
185
186 FILE* f = fopen(filename, mode);
187 if (! f) {
188 if (errno != 0) {
189 return errno;
190 } else {
191 return ENOENT;
192 }
193 }
194 *pFile = f;
195
196 return 0;
197}
198
199#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600200
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600201
202
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600203// Set up environment for GLSL compiler
204// Must be done once per process
205void TestEnvironment::SetUp()
206{
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600207 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600208 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800209
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600210 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600211}
212
213void TestEnvironment::TearDown()
214{
215 glslang::FinalizeProcess();
216}
217
Tony Barbour6918cd52015-04-09 12:58:51 -0600218VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600219 m_compile_options( 0 ),
220 m_num_shader_strings( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600221{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600222
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600223}
224
Tony Barbour6918cd52015-04-09 12:58:51 -0600225VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600226{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600227
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600228}
229
230// Define all the static elements
Cody Northropa3673cf2015-06-09 13:00:45 -0600231bool VkTestFramework::m_show_images = false;
232bool VkTestFramework::m_save_images = false;
233bool VkTestFramework::m_compare_images = false;
234bool VkTestFramework::m_use_glsl = false;
235bool VkTestFramework::m_canonicalize_spv = false;
236bool VkTestFramework::m_strip_spv = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600237bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour6918cd52015-04-09 12:58:51 -0600238int VkTestFramework::m_width = 0;
239int VkTestFramework::m_height = 0;
240std::list<VkTestImageRecord> VkTestFramework::m_images;
241std::list<VkTestImageRecord>::iterator VkTestFramework::m_display_image;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600242int m_display_image_idx = 0;
243
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600244bool VkTestFramework::optionMatch(const char* option, char* optionLine)
245{
246 if (strncmp(option, optionLine, strlen(option)) == 0)
247 return true;
248 else
249 return false;
250}
251
Tony Barbour6918cd52015-04-09 12:58:51 -0600252void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600253{
254 int i, n;
255
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600256 for (i=1, n=1; i< *argc; i++) {
257 if (optionMatch("--show-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600258 m_show_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600259 else if (optionMatch("--save-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600260 m_save_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600261 else if (optionMatch("--no-SPV", argv[i]))
262 m_use_glsl = true;
263 else if (optionMatch("--strip-SPV", argv[i]))
264 m_strip_spv = true;
265 else if (optionMatch("--canonicalize-SPV", argv[i]))
266 m_canonicalize_spv = true;
267 else if (optionMatch("--compare-images", argv[i]))
Tony Barbour247bf372014-10-30 14:29:04 -0600268 m_compare_images = true;
Tony Barbour247bf372014-10-30 14:29:04 -0600269
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600270 else if (optionMatch("--help", argv[i]) ||
271 optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700272 printf("\nOther options:\n");
273 printf("\t--show-images\n"
274 "\t\tDisplay test images in viewer after tests complete.\n");
275 printf("\t--save-images\n"
276 "\t\tSave tests images as ppm files in current working directory.\n"
277 "\t\tUsed to generate golden images for compare-images.\n");
278 printf("\t--compare-images\n"
279 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barboura98d3932014-12-11 09:52:49 -0700280 "\t\tAlso saves the generated test image in current working\n"
281 "\t\t\tdirectory but only if the image is different from the golden\n"
282 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
283 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700284 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600285 printf("\t--no-SPV\n"
286 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600287 printf("\t--strip-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600288 "\t\tStrip SPIR-V debug information (line numbers, names, etc).\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600289 printf("\t--canonicalize-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600290 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600291 exit(0);
292 } else {
293 printf("\nUnrecognized option: %s\n", argv[i]);
294 printf("\nUse --help or -h for option list.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700295 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700296 }
297
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600298 /*
299 * Since the above "consume" inputs, update argv
300 * so that it contains the trimmed list of args for glutInit
301 */
302
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600303 argv[n] = argv[i];
304 n++;
305 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600306}
307
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700308VkFormat VkTestFramework::GetFormat(VkInstance instance, vk_testing::Device *device)
309{
310 VkFormatProperties format_props;
311 if (!m_show_images)
312 {
313 vkGetPhysicalDeviceFormatProperties(device->phy().handle(), VK_FORMAT_B8G8R8A8_UNORM, &format_props);
314 if (format_props.linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ||
315 format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)
316 {
317 return VK_FORMAT_B8G8R8A8_UNORM;
318 }
319 vkGetPhysicalDeviceFormatProperties(device->phy().handle(), VK_FORMAT_R8G8B8A8_UNORM, &format_props);
320 if (format_props.linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ||
321 format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)
322 {
323 return VK_FORMAT_R8G8B8A8_UNORM;
324 }
325 printf("Error - device does not support VK_FORMAT_B8G8R8A8_UNORM nor VK_FORMAT_R8G8B8A8_UNORM - exiting\n");
326 exit(0);
327 }
328 else
329 {
330 /* To find which formats are presentable, you have to provide a surface to vkGetPhysicalDeviceSurfaceFormatsKHR */
331 /* To create a surface, you need a window. Use the present object to create a window, use that to create a */
332 /* KHR surface, and then find out what formats are presentable */
333 VkFormat presentFormat;
334 std::list<VkTestImageRecord> list;
335 VkTestImageRecord placeholder;
336 /* Use a dummy image record with non-zero area so the window will create on Windows */
337 placeholder.m_width = placeholder.m_height = 20;
338 list.push_back(placeholder);
339 TestFrameworkVkPresent vkPresent(*device);
340 vkPresent.InitPresentFramework(list, instance);
341 vkPresent.CreateMyWindow();
342 presentFormat = vkPresent.GetPresentFormat();
Tony Barboure1837292015-12-07 13:46:11 -0700343 vkPresent.DestroyMyWindow();
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700344 return presentFormat;
345 }
346}
347
Tony Barbour6918cd52015-04-09 12:58:51 -0600348void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600349{
350 string filename;
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600351 uint32_t x, y;
Tony Barbour6918cd52015-04-09 12:58:51 -0600352 VkImageObj displayImage(image->device());
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600353 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbour84d448c2015-04-02 14:02:33 -0600354
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800355 displayImage.init(image->extent().width, image->extent().height, image->format(), VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_LINEAR, reqs);
Tony Barbour84d448c2015-04-02 14:02:33 -0600356 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600357
358 filename.append(basename);
359 filename.append(".ppm");
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600360
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600361 const VkImageSubresource sr = {
Courtney Goeltzenleuchter908e7672015-10-21 17:00:51 -0600362 VK_IMAGE_ASPECT_COLOR_BIT, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600363 };
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600364 VkSubresourceLayout sr_layout;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600365
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600366 vkGetImageSubresourceLayout(image->device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600367
Tony Barbour84d448c2015-04-02 14:02:33 -0600368 char *ptr;
Chia-I Wu681d7a02015-07-03 13:44:34 +0800369 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600370 ptr += sr_layout.offset;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600371 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600372 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
373
374 file << "P6\n";
Tony Barbourfeb61962015-09-21 15:17:33 -0600375 file << displayImage.width() << " ";
Tony Barbour84d448c2015-04-02 14:02:33 -0600376 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600377 file << 255 << "\n";
378
Tony Barbour84d448c2015-04-02 14:02:33 -0600379 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700380 const int *row = (const int *) ptr;
381 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600382
Tony Barbourd1c35722015-04-16 15:59:00 -0600383 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700384 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600385 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700386 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
387 file.write((char *) &swapped, 3);
388 row++;
389 }
390 }
Tony Barbourd1c35722015-04-16 15:59:00 -0600391 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700392 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600393 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700394 file.write((char *) row, 3);
395 row++;
396 }
397 }
398 else {
399 printf("Unrecognized image format - will not write image files");
400 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600401 }
402
403 ptr += sr_layout.rowPitch;
404 }
405
406 file.close();
Chia-I Wu681d7a02015-07-03 13:44:34 +0800407 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600408}
409
Tony Barbour6918cd52015-04-09 12:58:51 -0600410void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour247bf372014-10-30 14:29:04 -0600411{
412
413 MagickWand *magick_wand_1;
414 MagickWand *magick_wand_2;
415 MagickWand *compare_wand;
416 MagickBooleanType status;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600417 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600418 double differenz;
419
Tony Barbour4ab45422014-12-10 17:00:20 -0700420 if (getenv("RENDERTEST_GOLDEN_DIR"))
421 {
422 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
423 }
424
Tony Barbour247bf372014-10-30 14:29:04 -0600425 MagickWandGenesis();
426 magick_wand_1=NewMagickWand();
427 sprintf(testimage,"%s.ppm",basename);
428 status=MagickReadImage(magick_wand_1,testimage);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600429 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour247bf372014-10-30 14:29:04 -0600430
431
432 MagickWandGenesis();
433 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700434 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600435 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600436 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour247bf372014-10-30 14:29:04 -0600437
Tony Barbour247bf372014-10-30 14:29:04 -0600438 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
439 if (differenz != 0.0)
440 {
441 char difference[256];
442
443 sprintf(difference,"%s-diff.ppm",basename);
444 status = MagickWriteImage(compare_wand, difference);
445 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
446 }
447 DestroyMagickWand(compare_wand);
448
449 DestroyMagickWand(magick_wand_1);
450 DestroyMagickWand(magick_wand_2);
451 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700452
453 if (differenz == 0.0)
454 {
455 /*
456 * If test image and golden image match, we do not need to
457 * keep around the test image.
458 */
459 remove(testimage);
460 }
Tony Barbour247bf372014-10-30 14:29:04 -0600461}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600462
Tony Barbour6918cd52015-04-09 12:58:51 -0600463void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600464{
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600465 VkSubresourceLayout sr_layout;
466 char *ptr;
467 VkTestImageRecord record;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600468 VkImageObj displayImage(image->device());
469 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
470
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800471 displayImage.init(image->extent().width, image->extent().height, image->format(), VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_LINEAR, reqs);
Cody Northropc9a69912015-06-18 17:05:15 -0600472
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600473 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600474
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600475 const VkImageSubresource sr = {
Courtney Goeltzenleuchter908e7672015-10-21 17:00:51 -0600476 VK_IMAGE_ASPECT_COLOR_BIT, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600477 };
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600478
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600479 vkGetImageSubresourceLayout(displayImage.device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600480
Chia-I Wu681d7a02015-07-03 13:44:34 +0800481 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600482 ptr += sr_layout.offset;
483
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600484 record.m_title.append(comment);
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600485 record.m_width = displayImage.width();
486 record.m_height = displayImage.height();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600487 // TODO: Need to make this more robust to handle different image formats
Tony-LunarG399dfca2015-05-19 14:08:26 -0600488 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600489 record.m_data = malloc(record.m_data_size);
490 memcpy(record.m_data, ptr, record.m_data_size);
491 m_images.push_back(record);
492 m_display_image = --m_images.end();
493
Chia-I Wu681d7a02015-07-03 13:44:34 +0800494 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600495}
496
Tony Barbour6918cd52015-04-09 12:58:51 -0600497void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600498{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600499 for (int32_t i = 0; i < images.size(); i++) {
500 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600501 }
502}
503
Tony Barbour6918cd52015-04-09 12:58:51 -0600504void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600505{
506 const ::testing::TestInfo* const test_info =
507 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600508 ostringstream filestream;
509 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600510
Tony Barbour247bf372014-10-30 14:29:04 -0600511 m_width = 40;
512
513 if (strcmp(test_info->name(), m_testName.c_str())) {
514 filestream << test_info->name();
515 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700516 m_frameNum = 2;
517 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600518 }
519 else {
520 filestream << test_info->name() << "-" << m_frameNum;
521 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700522 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600523 }
524
Tony Barbour247bf372014-10-30 14:29:04 -0600525 // ToDo - scrub string for bad characters
526
527 if (m_save_images || m_compare_images) {
528 WritePPM(filename.c_str(), image);
529 if (m_compare_images) {
530 Compare(filename.c_str(), image);
531 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600532 }
533
534 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600535 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600536 }
537}
538
Chia-I Wuf8693382015-04-16 22:02:10 +0800539TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
540 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700541 m_queue(*m_device.graphics_queues()[0]),
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800542 m_cmdpool(m_device, vk_testing::CommandPool::create_info(m_device.graphics_queue_node_index_)),
543 m_cmdbuf(m_device, vk_testing::CommandBuffer::create_info(m_cmdpool.handle()))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600544{
Tony Barbour96db8822015-02-25 12:28:39 -0700545 m_quit = false;
546 m_pause = false;
547 m_width = 0;
548 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600549}
550
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700551VkFormat TestFrameworkVkPresent::GetPresentFormat()
552{
553 uint32_t formatCount;
554 VkResult U_ASSERT_ONLY res;
555 VkSurfaceKHR surface;
556 VkFormat returnFormat;
557
558#ifdef _WIN32
559 res = vkCreateWin32SurfaceKHR(m_instance, m_connection, m_window,
560 NULL, &surface);
561#else // _WIN32
562 res = vkCreateXcbSurfaceKHR(m_instance, m_connection, m_window,
563 NULL, &surface);
564#endif // _WIN32
565 assert(res == VK_SUCCESS);
566
567 m_fpGetPhysicalDeviceSurfaceFormatsKHR(
568 m_device.phy().handle(),
569 surface,
570 &formatCount, NULL);
571 VkSurfaceFormatKHR *surfFormats =
572 (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
573 m_fpGetPhysicalDeviceSurfaceFormatsKHR(
574 m_device.phy().handle(),
575 surface,
576 &formatCount, surfFormats);
577
578 m_fpDestroySurfaceKHR(m_instance, surface, NULL);
579
580 returnFormat = surfFormats[0].format;
581 free(surfFormats);
582 return returnFormat;
583}
584
Tony Barbour6918cd52015-04-09 12:58:51 -0600585void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600586{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600587 VkResult U_ASSERT_ONLY err;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600588 vk_testing::Buffer buf;
589 void *dest_ptr;
590
Tony Barbour6a3faf02015-07-23 10:36:18 -0600591 VkSemaphore presentCompleteSemaphore;
592 VkSemaphoreCreateInfo presentCompleteSemaphoreCreateInfo = {};
593 presentCompleteSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
594 presentCompleteSemaphoreCreateInfo.pNext = NULL;
595 presentCompleteSemaphoreCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
596
597
598 err = vkCreateSemaphore(m_device.handle(),
599 &presentCompleteSemaphoreCreateInfo,
Chia-I Wuf7458c52015-10-26 21:10:41 +0800600 NULL, &presentCompleteSemaphore);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600601 assert(!err);
602
603 // Get the index of the next available swapchain image:
Ian Elliott7e40db92015-08-21 15:09:33 -0600604 err = m_fpAcquireNextImageKHR(m_device.handle(), m_swap_chain,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600605 UINT64_MAX,
606 presentCompleteSemaphore,
Ian Elliottc11750d2015-10-30 13:24:12 -0600607 VK_NULL_HANDLE,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600608 &m_current_buffer);
Ian Elliott7e40db92015-08-21 15:09:33 -0600609 // TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
Tony Barbour6a3faf02015-07-23 10:36:18 -0600610 // return codes
611 assert(!err);
612
Tony-LunarG399dfca2015-05-19 14:08:26 -0600613 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Cody Northrop7fb43862015-06-22 14:56:14 -0600614 buf.init_as_src(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800615 dest_ptr = buf.memory().map();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600616 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800617 buf.memory().unmap();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600618
619 m_cmdbuf.begin();
Tony Barbourbd094ce2015-10-23 11:00:15 -0600620 VkImageMemoryBarrier memoryBarrier = {};
621 memoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
622 memoryBarrier.pNext = NULL;
Tony Barbourd800bbd2015-11-05 10:54:44 -0700623 memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
Chia-I Wua4594202015-10-27 19:54:37 +0800624 memoryBarrier.dstAccessMask = 0;
Ian Elliott1dcd1092015-11-17 17:29:40 -0700625 memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800626 memoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600627 memoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800628 memoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600629 memoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
630 memoryBarrier.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800631 memoryBarrier.subresourceRange.levelCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600632 memoryBarrier.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800633 memoryBarrier.subresourceRange.layerCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600634 memoryBarrier.image = m_buffers[m_current_buffer].image;
635 VkImageMemoryBarrier *pmemory_barrier = &memoryBarrier;
Chia-I Wu89d0f942015-10-31 00:31:16 +0800636 vkCmdPipelineBarrier(m_cmdbuf.handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
Chia-I Wu53534662015-10-26 17:08:33 +0800637 0, 1, (const void * const*)&pmemory_barrier);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600638
639 VkBufferImageCopy region = {};
Tony Barbourd800bbd2015-11-05 10:54:44 -0700640 region.bufferRowLength = m_display_image->m_width;
641 region.bufferImageHeight = m_display_image->m_height;
642 region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
643 region.imageSubresource.layerCount = 1;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600644 region.imageExtent.height = m_display_image->m_height;
645 region.imageExtent.width = m_display_image->m_width;
646 region.imageExtent.depth = 1;
647
Chia-I Wube2b9172015-07-03 11:49:42 +0800648 vkCmdCopyBufferToImage(m_cmdbuf.handle(),
Chia-I Wu681d7a02015-07-03 13:44:34 +0800649 buf.handle(),
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800650 m_buffers[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600651 1, &region);
Tony Barbourbd094ce2015-10-23 11:00:15 -0600652
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800653 memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
Ian Elliott1dcd1092015-11-17 17:29:40 -0700654 memoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
Chia-I Wu89d0f942015-10-31 00:31:16 +0800655 vkCmdPipelineBarrier(m_cmdbuf.handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
Chia-I Wu53534662015-10-26 17:08:33 +0800656 0, 1, (const void * const*)&pmemory_barrier);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600657 m_cmdbuf.end();
658
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800659 VkCommandBuffer cmdBufs[1];
Chia-I Wube2b9172015-07-03 11:49:42 +0800660 cmdBufs[0] = m_cmdbuf.handle();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600661
Chia-I Wua690b412015-10-29 22:01:53 +0800662 // Wait for the present complete semaphore to be signaled to ensure
663 // that the image won't be rendered to until the presentation
664 // engine has fully released ownership to the application, and it is
665 // okay to render to the image.
Tony Barbour67e99152015-07-10 14:10:27 -0600666 VkFence nullFence = { VK_NULL_HANDLE };
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600667 VkSubmitInfo submit_info;
Chia-I Wuf9be13c2015-10-26 20:37:06 +0800668 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
669 submit_info.pNext = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +0800670 submit_info.waitSemaphoreCount = 1;
Chia-I Wua690b412015-10-29 22:01:53 +0800671 submit_info.pWaitSemaphores = &presentCompleteSemaphore,
Chia-I Wud50a7d72015-10-26 20:48:51 +0800672 submit_info.commandBufferCount = 1;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600673 submit_info.pCommandBuffers = cmdBufs;
Chia-I Wud50a7d72015-10-26 20:48:51 +0800674 submit_info.signalSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600675 submit_info.pSignalSemaphores = NULL;
676
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -0600677 vkQueueSubmit(m_queue.handle(), 1, &submit_info, nullFence);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600678 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700679
Chia-I Wuf7458c52015-10-26 21:10:41 +0800680 vkDestroySemaphore(m_device.handle(), presentCompleteSemaphore, NULL);
Chia-I Wua690b412015-10-29 22:01:53 +0800681
Ian Elliott7e40db92015-08-21 15:09:33 -0600682 VkPresentInfoKHR present = {};
683 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600684 present.pNext = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600685 present.swapchainCount = 1;
Ian Elliottc11750d2015-10-30 13:24:12 -0600686 present.pSwapchains = & m_swap_chain;
687 present.pImageIndices = &m_current_buffer;
Tony Barbour96db8822015-02-25 12:28:39 -0700688
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600689#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800690 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700691 XCB_PROP_MODE_REPLACE,
692 m_window,
693 XCB_ATOM_WM_NAME,
694 XCB_ATOM_STRING,
695 8,
696 m_display_image->m_title.size(),
697 m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600698#endif
Jon Ashburn07daee72015-05-21 18:13:33 -0600699
Ian Elliott7e40db92015-08-21 15:09:33 -0600700 err = m_fpQueuePresentKHR(m_queue.handle(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700701 assert(!err);
702
703 m_queue.wait();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600704 m_current_buffer = (m_current_buffer + 1) % 2;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600705}
706
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600707#ifdef _WIN32
Tony-LunarG399dfca2015-05-19 14:08:26 -0600708# define PREVIOUSLY_DOWN 1<<29
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600709// MS-Windows event handling function:
710LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
711 UINT uMsg,
712 WPARAM wParam,
713 LPARAM lParam)
714{
715
716 switch(uMsg)
717 {
718 case WM_CLOSE:
719 PostQuitMessage(0);
720 break;
721
722 case WM_PAINT:
723 {
724 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
725 if (me) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600726 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600727 me->Display();
728 }
729 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600730 break;
731
732 case WM_KEYDOWN:
733 {
734 if (lParam & (PREVIOUSLY_DOWN)){
735 break;
736 }
737 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
738 // the window, we put the this pointer into the window's user data so we could get it back now
739 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
740 switch (wParam)
741 {
742 case VK_ESCAPE: me->m_quit = true;
743 break;
744
745 case VK_LEFT: // left arrow key
746 if (me->m_display_image == me->m_images.begin()) {
747 me->m_display_image = --me->m_images.end();
748 }
749 else {
750 --me->m_display_image;
751 }
752 break;
753
754 case VK_RIGHT: // right arrow key
755 ++me->m_display_image;
756 if (me->m_display_image == me->m_images.end()) {
757 me->m_display_image = me->m_images.begin();
758 }
759 break;
760
761 default:
762 break;
763 }
764 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
765 me->Display();
766 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600767 }
768 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
769}
770
771void TestFrameworkVkPresent::Run()
772{
773 MSG msg; // message
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600774
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600775 /* main message loop*/
Tony-LunarG399dfca2015-05-19 14:08:26 -0600776 while(! m_quit) {
777 GetMessage(&msg, m_window, 0, 0);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600778 if (msg.message == WM_QUIT) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600779 m_quit = true; //if found, quit app
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600780 } else {
781 /* Translate and dispatch to event queue*/
782 TranslateMessage(&msg);
783 DispatchMessage(&msg);
784 }
785 }
786}
787
788#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600789void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600790{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600791 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700792 switch (event_code) {
793 case XCB_EXPOSE:
794 Display(); // TODO: handle resize
795 break;
796 case XCB_CLIENT_MESSAGE:
797 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
798 (m_atom_wm_delete_window)->atom) {
799 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600800 }
801 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700802 case XCB_KEY_RELEASE:
803 {
804 const xcb_key_release_event_t *key =
805 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600806
Tony Barbour96db8822015-02-25 12:28:39 -0700807 switch (key->detail) {
808 case 0x9: // Escape
809 m_quit = true;
810 break;
811 case 0x71: // left arrow key
812 if (m_display_image == m_images.begin()) {
813 m_display_image = --m_images.end();
814 } else {
815 --m_display_image;
816 }
817 break;
818 case 0x72: // right arrow key
819 ++m_display_image;
820 if (m_display_image == m_images.end()) {
821 m_display_image = m_images.begin();
822 }
823 break;
824 case 0x41:
825 m_pause = !m_pause;
826 break;
827 }
828 Display();
829 }
830 break;
831 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600832 break;
833 }
Tony Barbour96db8822015-02-25 12:28:39 -0700834}
835
Tony Barbour6918cd52015-04-09 12:58:51 -0600836void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700837{
Chia-I Wuf8693382015-04-16 22:02:10 +0800838 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700839
840 while (! m_quit) {
841 xcb_generic_event_t *event;
842
843 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800844 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700845 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800846 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700847 }
848 if (event) {
849 HandleEvent(event);
850 free(event);
851 }
852 }
853}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600854#endif // _WIN32
Tony Barbour96db8822015-02-25 12:28:39 -0700855
Ian Elliott7e40db92015-08-21 15:09:33 -0600856void TestFrameworkVkPresent::CreateSwapchain()
Tony Barbour96db8822015-02-25 12:28:39 -0700857{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600858 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700859
Tony-LunarG399dfca2015-05-19 14:08:26 -0600860 m_display_image = m_images.begin();
861 m_current_buffer = 0;
862
Ian Elliottc11750d2015-10-30 13:24:12 -0600863 // Create the WSI surface:
Ian Elliott1a3845b2015-07-06 14:33:04 -0600864#ifdef _WIN32
Ian Elliottc11750d2015-10-30 13:24:12 -0600865 err = vkCreateWin32SurfaceKHR(m_instance, m_connection,
866 m_window, NULL, &m_surface);
Ian Elliott1a3845b2015-07-06 14:33:04 -0600867#else // _WIN32
Ian Elliottc11750d2015-10-30 13:24:12 -0600868 err = vkCreateXcbSurfaceKHR(m_instance, m_connection,
869 m_window, NULL, &m_surface);
Ian Elliott1a3845b2015-07-06 14:33:04 -0600870#endif // _WIN32
Ian Elliottc11750d2015-10-30 13:24:12 -0600871 assert(!err);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600872
873 // Iterate over each queue to learn whether it supports presenting to WSI:
874 VkBool32 supportsPresent;
875 m_present_queue_node_index = UINT32_MAX;
876 std::vector<vk_testing::Queue *> queues = m_device.graphics_queues();
877 for (int i=0; i < queues.size(); i++)
878 {
879 int family_index = queues[i]->get_family_index();
Ian Elliott7e40db92015-08-21 15:09:33 -0600880 m_fpGetPhysicalDeviceSurfaceSupportKHR(m_device.phy().handle(),
Tony Barbour6a3faf02015-07-23 10:36:18 -0600881 family_index,
Ian Elliottc11750d2015-10-30 13:24:12 -0600882 m_surface,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600883 &supportsPresent);
884 if (supportsPresent) {
885 m_present_queue_node_index = family_index;
886 }
887 }
888
889 assert(m_present_queue_node_index != UINT32_MAX);
890
891
892 // Get the list of VkFormat's that are supported:
Ian Elliott8b139792015-08-07 11:51:12 -0600893 uint32_t formatCount;
Ian Elliottc11750d2015-10-30 13:24:12 -0600894 err = m_fpGetPhysicalDeviceSurfaceFormatsKHR(m_device.phy().handle(),
895 m_surface,
Ian Elliott8b139792015-08-07 11:51:12 -0600896 &formatCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600897 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600898 VkSurfaceFormatKHR *surfFormats =
899 (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
Ian Elliottc11750d2015-10-30 13:24:12 -0600900 err = m_fpGetPhysicalDeviceSurfaceFormatsKHR(m_device.phy().handle(),
901 m_surface,
Ian Elliott8b139792015-08-07 11:51:12 -0600902 &formatCount, surfFormats);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600903 assert(!err);
904 // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
905 // the surface has no preferred format. Otherwise, at least one
906 // supported format will be returned.
Tony Barbour6a3faf02015-07-23 10:36:18 -0600907 if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED)
908 {
909 m_format = VK_FORMAT_B8G8R8A8_UNORM;
910 }
911 else
912 {
913 assert(formatCount >= 1);
914 m_format = surfFormats[0].format;
915 }
Ian Elliott8b139792015-08-07 11:51:12 -0600916 m_color_space = surfFormats[0].colorSpace;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600917
Ian Elliottc11750d2015-10-30 13:24:12 -0600918 // Check the surface capabilities and formats
919 VkSurfaceCapabilitiesKHR surfCapabilities;
920 err = m_fpGetPhysicalDeviceSurfaceCapabilitiesKHR(m_device.phy().handle(),
921 m_surface,
922 &surfCapabilities);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600923 assert(!err);
924
Ian Elliott8b139792015-08-07 11:51:12 -0600925 uint32_t presentModeCount;
Ian Elliottc11750d2015-10-30 13:24:12 -0600926 err = m_fpGetPhysicalDeviceSurfacePresentModesKHR(m_device.phy().handle(),
927 m_surface,
Ian Elliott8b139792015-08-07 11:51:12 -0600928 &presentModeCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600929 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600930 VkPresentModeKHR *presentModes =
931 (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
Ian Elliott8b139792015-08-07 11:51:12 -0600932 assert(presentModes);
Ian Elliottc11750d2015-10-30 13:24:12 -0600933 err = m_fpGetPhysicalDeviceSurfacePresentModesKHR(m_device.phy().handle(),
934 m_surface,
Ian Elliott8b139792015-08-07 11:51:12 -0600935 &presentModeCount, presentModes);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600936 assert(!err);
937
Ian Elliott7e40db92015-08-21 15:09:33 -0600938 VkExtent2D swapchainExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600939 // width and height are either both -1, or both not -1.
Ian Elliottc11750d2015-10-30 13:24:12 -0600940 if (surfCapabilities.currentExtent.width == -1)
Tony Barbour6a3faf02015-07-23 10:36:18 -0600941 {
942 // If the surface size is undefined, the size is set to
943 // the size of the images requested.
Ian Elliott7e40db92015-08-21 15:09:33 -0600944 swapchainExtent.width = m_width;
945 swapchainExtent.height = m_height;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600946 }
947 else
948 {
949 // If the surface size is defined, the swap chain size must match
Ian Elliottc11750d2015-10-30 13:24:12 -0600950 swapchainExtent = surfCapabilities.currentExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600951 }
952
953 // If mailbox mode is available, use it, as is the lowest-latency non-
Ian Elliottae0e8242015-08-10 13:20:49 -0600954 // tearing mode. If not, try IMMEDIATE which will usually be available,
955 // and is fastest (though it tears). If not, fall back to FIFO which is
956 // always available.
Ian Elliott7e40db92015-08-21 15:09:33 -0600957 VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600958 for (size_t i = 0; i < presentModeCount; i++) {
Ian Elliott7e40db92015-08-21 15:09:33 -0600959 if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
960 swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600961 break;
962 }
Ian Elliott7e40db92015-08-21 15:09:33 -0600963 if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) &&
964 (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
965 swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
Ian Elliottae0e8242015-08-10 13:20:49 -0600966 }
Tony Barbour6a3faf02015-07-23 10:36:18 -0600967 }
968
969 // Determine the number of VkImage's to use in the swap chain (we desire to
970 // own only 1 image at a time, besides the images being displayed and
971 // queued for display):
Ian Elliottc11750d2015-10-30 13:24:12 -0600972 uint32_t desiredNumberOfSwapchainImages = surfCapabilities.minImageCount + 1;
973 if ((surfCapabilities.maxImageCount > 0) &&
974 (desiredNumberOfSwapchainImages > surfCapabilities.maxImageCount))
Tony Barbour6a3faf02015-07-23 10:36:18 -0600975 {
976 // Application must settle for fewer images than desired:
Ian Elliottc11750d2015-10-30 13:24:12 -0600977 desiredNumberOfSwapchainImages = surfCapabilities.maxImageCount;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600978 }
979
Ian Elliottc11750d2015-10-30 13:24:12 -0600980 VkSurfaceTransformFlagsKHR preTransform;
981 if (surfCapabilities.supportedTransforms & VK_SURFACE_TRANSFORM_NONE_BIT_KHR) {
982 preTransform = VK_SURFACE_TRANSFORM_NONE_BIT_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600983 } else {
Ian Elliottc11750d2015-10-30 13:24:12 -0600984 preTransform = surfCapabilities.currentTransform;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600985 }
Ian Elliott1a3845b2015-07-06 14:33:04 -0600986
Cody Northropdf5b0922015-08-28 16:22:48 -0600987 // We want to blit to the swap chain, ensure the driver supports it. Color is always supported, per WSI spec.
Ian Elliottc11750d2015-10-30 13:24:12 -0600988 assert((surfCapabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) != 0);
Cody Northropdf5b0922015-08-28 16:22:48 -0600989
Ian Elliott7e40db92015-08-21 15:09:33 -0600990 VkSwapchainCreateInfoKHR swap_chain = {};
Ian Elliotta257eea2015-09-22 10:20:23 -0600991 swap_chain.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600992 swap_chain.pNext = NULL;
Ian Elliottc11750d2015-10-30 13:24:12 -0600993 swap_chain.surface = m_surface;
Ian Elliott7e40db92015-08-21 15:09:33 -0600994 swap_chain.minImageCount = desiredNumberOfSwapchainImages;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600995 swap_chain.imageFormat = m_format;
Ian Elliott8b139792015-08-07 11:51:12 -0600996 swap_chain.imageColorSpace = m_color_space;
Ian Elliott7e40db92015-08-21 15:09:33 -0600997 swap_chain.imageExtent.width = swapchainExtent.width;
998 swap_chain.imageExtent.height = swapchainExtent.height;
Ian Elliottc11750d2015-10-30 13:24:12 -0600999 swap_chain.imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1000 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1001 swap_chain.preTransform = (VkSurfaceTransformFlagBitsKHR) preTransform;
1002 swap_chain.imageArrayLayers = 1;
1003 swap_chain.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
1004 swap_chain.queueFamilyIndexCount = 0;
Ian Elliott8b139792015-08-07 11:51:12 -06001005 swap_chain.pQueueFamilyIndices = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -06001006 swap_chain.presentMode = swapchainPresentMode;
Chia-I Wue2fc5522015-10-26 20:04:44 +08001007 swap_chain.oldSwapchain = VK_NULL_HANDLE;
Tony Barbour6a3faf02015-07-23 10:36:18 -06001008 swap_chain.clipped = true;
1009
1010 uint32_t i;
Chia-I Wuf8693382015-04-16 22:02:10 +08001011
Ian Elliottc11750d2015-10-30 13:24:12 -06001012 err = m_fpCreateSwapchainKHR(m_device.handle(), &swap_chain, NULL, &m_swap_chain);
Chia-I Wuf8693382015-04-16 22:02:10 +08001013 assert(!err);
1014
Ian Elliott7e40db92015-08-21 15:09:33 -06001015 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
1016 &m_swapchainImageCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -06001017 assert(!err);
1018
Ian Elliott7e40db92015-08-21 15:09:33 -06001019 VkImage* swapchainImages = (VkImage*)malloc(m_swapchainImageCount * sizeof(VkImage));
1020 assert(swapchainImages);
1021 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
1022 &m_swapchainImageCount, swapchainImages);
Tony Barbour6a3faf02015-07-23 10:36:18 -06001023 assert(!err);
1024
Ian Elliott7e40db92015-08-21 15:09:33 -06001025 m_buffers = (SwapchainBuffers*)malloc(sizeof(SwapchainBuffers)*m_swapchainImageCount);
Tony Barbour6a3faf02015-07-23 10:36:18 -06001026 assert(m_buffers);
1027
Ian Elliott7e40db92015-08-21 15:09:33 -06001028 for (i = 0; i < m_swapchainImageCount; i++) {
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -06001029 VkImageViewCreateInfo color_image_view = {};
1030 color_image_view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
1031 color_image_view.pNext = NULL;
1032 color_image_view.format = m_format;
Tony Barbourd800bbd2015-11-05 10:54:44 -07001033 color_image_view.components.r = VK_COMPONENT_SWIZZLE_R;
1034 color_image_view.components.g = VK_COMPONENT_SWIZZLE_G;
1035 color_image_view.components.b = VK_COMPONENT_SWIZZLE_B;
1036 color_image_view.components.a = VK_COMPONENT_SWIZZLE_A;
Courtney Goeltzenleuchterba724512015-09-10 17:58:54 -06001037 color_image_view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -06001038 color_image_view.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001039 color_image_view.subresourceRange.levelCount = 1;
Courtney Goeltzenleuchter4a261892015-09-10 16:38:41 -06001040 color_image_view.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001041 color_image_view.subresourceRange.layerCount = 1;
Tony Barbourd800bbd2015-11-05 10:54:44 -07001042 color_image_view.viewType = VK_IMAGE_VIEW_TYPE_2D;
1043 color_image_view.flags = 0;
Tony Barbour6a3faf02015-07-23 10:36:18 -06001044
Ian Elliott7e40db92015-08-21 15:09:33 -06001045 m_buffers[i].image = swapchainImages[i];
Tony Barbour6a3faf02015-07-23 10:36:18 -06001046
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -06001047 color_image_view.image = m_buffers[i].image;
1048 err = vkCreateImageView(m_device.handle(),
Chia-I Wuf7458c52015-10-26 21:10:41 +08001049 &color_image_view, NULL, &m_buffers[i].view);
Tony Barbour6a3faf02015-07-23 10:36:18 -06001050 assert(!err);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001051
1052 /* Set image layout to PRESENT_SOURCE_KHR so that before the copy, it can be set to */
1053 /* TRANSFER_DESTINATION_OPTIMAL */
1054 SetImageLayout(m_buffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT,
Ian Elliott1dcd1092015-11-17 17:29:40 -07001055 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001056
Tony Barbour6a3faf02015-07-23 10:36:18 -06001057 }
Tony Barbour96db8822015-02-25 12:28:39 -07001058}
Tony Barbourbd094ce2015-10-23 11:00:15 -06001059void TestFrameworkVkPresent::SetImageLayout(VkImage image, VkImageAspectFlags aspectMask,
1060 VkImageLayout old_image_layout, VkImageLayout new_image_layout)
1061{
1062 VkResult U_ASSERT_ONLY err;
1063
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001064 VkCommandBufferBeginInfo cmd_buf_info = {};
1065 cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001066 cmd_buf_info.pNext = NULL;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001067 cmd_buf_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001068 cmd_buf_info.renderPass = { VK_NULL_HANDLE };
1069 cmd_buf_info.subpass = 0;
1070 cmd_buf_info.framebuffer = { VK_NULL_HANDLE };
Chia-I Wub8d47ae2015-11-11 10:18:12 +08001071 cmd_buf_info.occlusionQueryEnable = VK_FALSE;
1072 cmd_buf_info.queryFlags = 0;
1073 cmd_buf_info.pipelineStatistics = 0;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001074
1075 err = vkBeginCommandBuffer(m_cmdbuf.handle(), &cmd_buf_info);
1076 assert(!err);
1077
1078 VkImageMemoryBarrier image_memory_barrier = {};
1079 image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
1080 image_memory_barrier.pNext = NULL;
Chia-I Wua4594202015-10-27 19:54:37 +08001081 image_memory_barrier.srcAccessMask = 0;
1082 image_memory_barrier.dstAccessMask = 0;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001083 image_memory_barrier.oldLayout = old_image_layout;
1084 image_memory_barrier.newLayout = new_image_layout;
1085 image_memory_barrier.image = image;
1086 image_memory_barrier.subresourceRange.aspectMask = aspectMask;
1087 image_memory_barrier.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001088 image_memory_barrier.subresourceRange.levelCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001089 image_memory_barrier.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001090 image_memory_barrier.subresourceRange.layerCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001091
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001092 if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
Tony Barbourbd094ce2015-10-23 11:00:15 -06001093 /* Make sure anything that was copying from this image has completed */
Chia-I Wua4594202015-10-27 19:54:37 +08001094 image_memory_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001095 }
1096
1097 if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
1098 /* Make sure any Copy or CPU writes to image are flushed */
Chia-I Wua4594202015-10-27 19:54:37 +08001099 image_memory_barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001100 }
1101
1102 VkImageMemoryBarrier *pmemory_barrier = &image_memory_barrier;
1103
1104 VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1105 VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1106
Chia-I Wu53534662015-10-26 17:08:33 +08001107 vkCmdPipelineBarrier(m_cmdbuf.handle(), src_stages, dest_stages, 0, 1, (const void * const*)&pmemory_barrier);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001108
1109 err = vkEndCommandBuffer(m_cmdbuf.handle());
1110 assert(!err);
1111
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001112 const VkCommandBuffer cmd_bufs[] = { m_cmdbuf.handle() };
Tony Barbourbd094ce2015-10-23 11:00:15 -06001113 VkFence nullFence = { VK_NULL_HANDLE };
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001114 VkSubmitInfo submit_info;
Chia-I Wuf9be13c2015-10-26 20:37:06 +08001115 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1116 submit_info.pNext = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001117 submit_info.waitSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001118 submit_info.pWaitSemaphores = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001119 submit_info.commandBufferCount = 1;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001120 submit_info.pCommandBuffers = cmd_bufs;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001121 submit_info.signalSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001122 submit_info.pSignalSemaphores = NULL;
1123
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -06001124 err = vkQueueSubmit(m_queue.handle(), 1, &submit_info, nullFence);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001125 assert(!err);
1126
1127 err = vkQueueWaitIdle(m_queue.handle());
1128 assert(!err);
1129
1130}
Tony Barbour96db8822015-02-25 12:28:39 -07001131
Jon Ashburn07daee72015-05-21 18:13:33 -06001132void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -07001133{
Ian Elliottc11750d2015-10-30 13:24:12 -06001134 m_instance = inst;
Ian Elliott7e40db92015-08-21 15:09:33 -06001135 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceSupportKHR);
Ian Elliottc11750d2015-10-30 13:24:12 -06001136 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceCapabilitiesKHR);
1137 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceFormatsKHR);
1138 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfacePresentModesKHR);
Tony Barbour2d6d54e2015-12-03 16:05:11 -07001139 GET_INSTANCE_PROC_ADDR(inst, DestroySurfaceKHR);
Ian Elliott7e40db92015-08-21 15:09:33 -06001140 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1141 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1142 GET_DEVICE_PROC_ADDR(m_device.handle(), DestroySwapchainKHR);
1143 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSwapchainImagesKHR);
1144 GET_DEVICE_PROC_ADDR(m_device.handle(), AcquireNextImageKHR);
1145 GET_DEVICE_PROC_ADDR(m_device.handle(), QueuePresentKHR);
Jon Ashburn07daee72015-05-21 18:13:33 -06001146
Tony Barbour96db8822015-02-25 12:28:39 -07001147 m_images = imagesIn;
1148}
1149
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001150#ifdef _WIN32
1151void TestFrameworkVkPresent::CreateMyWindow()
1152{
1153 WNDCLASSEX win_class;
1154 // const ::testing::TestInfo* const test_info =
1155 // ::testing::UnitTest::GetInstance()->current_test_info();
1156 m_connection = GetModuleHandle(NULL);
1157
1158 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1159 it != m_images.end(); it++) {
1160 if (m_width < it->m_width)
1161 m_width = it->m_width;
1162 if (m_height < it->m_height)
1163 m_height = it->m_height;
1164 }
1165 // Initialize the window class structure:
1166 win_class.cbSize = sizeof(WNDCLASSEX);
1167 win_class.style = CS_HREDRAW | CS_VREDRAW;
1168 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
1169 win_class.cbClsExtra = 0;
1170 win_class.cbWndExtra = 0;
1171 win_class.hInstance = m_connection; // hInstance
1172 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
1173 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
1174 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
1175 win_class.lpszMenuName = NULL;
1176 win_class.lpszClassName = "Test";
1177 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
1178 // Register window class:
1179 if (!RegisterClassEx(&win_class)) {
1180 // It didn't work, so try to give a useful error:
1181 printf("Unexpected error trying to start the application!\n");
1182 fflush(stdout);
1183 exit(1);
1184 }
1185 // Create window with the registered class:
Cody Northrop39582252015-08-05 15:39:31 -06001186 RECT wr = { 0, 0, m_width, m_height };
1187 AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001188 m_window = CreateWindowEx(0,
1189 "Test", // class name
1190 "Test", // app name
1191 WS_OVERLAPPEDWINDOW | // window style
1192 WS_VISIBLE |
1193 WS_SYSMENU,
1194 100,100, // x/y coords
Cody Northrop39582252015-08-05 15:39:31 -06001195 wr.right - wr.left, // width
1196 wr.bottom - wr.top, // height
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001197 NULL, // handle to parent
1198 NULL, // handle to menu
1199 m_connection, // hInstance
1200 NULL); // no extra parameters
1201
1202 if (!m_window) {
1203 // It didn't work, so try to give a useful error:
1204 DWORD error = GetLastError();
1205 char message[120];
1206 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
1207 MessageBox(NULL, message, "Error", MB_OK);
1208 exit(1);
1209 }
Tony-LunarG399dfca2015-05-19 14:08:26 -06001210 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
1211 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001212}
1213#else
Tony Barbour6918cd52015-04-09 12:58:51 -06001214void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -07001215{
Chia-I Wuf8693382015-04-16 22:02:10 +08001216 const xcb_setup_t *setup;
1217 xcb_screen_iterator_t iter;
1218 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -07001219 uint32_t value_mask, value_list[32];
1220
Chia-I Wuf8693382015-04-16 22:02:10 +08001221 m_connection = xcb_connect(NULL, &scr);
1222
1223 setup = xcb_get_setup(m_connection);
1224 iter = xcb_setup_roots_iterator(setup);
1225 while (scr-- > 0)
1226 xcb_screen_next(&iter);
1227
1228 m_screen = iter.data;
1229
1230 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1231 it != m_images.end(); it++) {
1232 if (m_width < it->m_width)
1233 m_width = it->m_width;
1234 if (m_height < it->m_height)
1235 m_height = it->m_height;
1236 }
1237
1238 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -07001239
1240 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +08001241 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -07001242 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
1243 XCB_EVENT_MASK_EXPOSURE |
1244 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
1245
Chia-I Wuf8693382015-04-16 22:02:10 +08001246 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -07001247 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001248 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -07001249 0, 0, m_width, m_height, 0,
1250 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001251 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -07001252 value_mask, value_list);
1253
1254 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +08001255 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -07001256 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +08001257 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001258
Chia-I Wuf8693382015-04-16 22:02:10 +08001259 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
1260 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001261
Chia-I Wuf8693382015-04-16 22:02:10 +08001262 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -07001263 m_window, (*reply).atom, 4, 32, 1,
1264 &(*m_atom_wm_delete_window).atom);
1265 free(reply);
1266
Chia-I Wuf8693382015-04-16 22:02:10 +08001267 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -07001268}
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001269#endif
Tony Barbour96db8822015-02-25 12:28:39 -07001270
Tony Barbour6918cd52015-04-09 12:58:51 -06001271void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -07001272{
Ian Elliottc11750d2015-10-30 13:24:12 -06001273 m_fpDestroySwapchainKHR(m_device.handle(), m_swap_chain, NULL);
Tony Barbour9226a822015-10-23 10:58:56 -06001274
1275 for (uint32_t i = 0; i < m_swapchainImageCount; i++) {
Chia-I Wuf7458c52015-10-26 21:10:41 +08001276 vkDestroyImageView(m_device.handle(), m_buffers[i].view, NULL);
Tony Barbour9226a822015-10-23 10:58:56 -06001277 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001278#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +08001279 xcb_destroy_window(m_connection, m_window);
1280 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001281#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001282}
1283
Tony Barboure1837292015-12-07 13:46:11 -07001284void TestFrameworkVkPresent::DestroyMyWindow()
Tony Barbour2d6d54e2015-12-03 16:05:11 -07001285{
1286#ifndef _WIN32
1287 xcb_destroy_window(m_connection, m_window);
1288 xcb_disconnect(m_connection);
1289#else
1290 DestroyWindow(m_window);
1291#endif
1292}
1293
Tony Barbour6918cd52015-04-09 12:58:51 -06001294void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001295{
1296 if (m_images.size() == 0) return;
1297
Chia-I Wuf8693382015-04-16 22:02:10 +08001298 vk_testing::Environment env;
1299 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -07001300 {
Chia-I Wuf8693382015-04-16 22:02:10 +08001301 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -07001302
Jon Ashburn07daee72015-05-21 18:13:33 -06001303 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001304 vkPresent.CreateMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -06001305 vkPresent.CreateSwapchain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001306 vkPresent.Run();
1307 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -07001308 }
Chia-I Wuf8693382015-04-16 22:02:10 +08001309 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001310}
1311
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001312//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001313// These are the default resources for TBuiltInResources, used for both
1314// - parsing this string for the case where the user didn't supply one
1315// - dumping out a template for user construction of a config file
1316//
1317static const char* DefaultConfig =
1318 "MaxLights 32\n"
1319 "MaxClipPlanes 6\n"
1320 "MaxTextureUnits 32\n"
1321 "MaxTextureCoords 32\n"
1322 "MaxVertexAttribs 64\n"
1323 "MaxVertexUniformComponents 4096\n"
1324 "MaxVaryingFloats 64\n"
1325 "MaxVertexTextureImageUnits 32\n"
1326 "MaxCombinedTextureImageUnits 80\n"
1327 "MaxTextureImageUnits 32\n"
1328 "MaxFragmentUniformComponents 4096\n"
1329 "MaxDrawBuffers 32\n"
1330 "MaxVertexUniformVectors 128\n"
1331 "MaxVaryingVectors 8\n"
1332 "MaxFragmentUniformVectors 16\n"
1333 "MaxVertexOutputVectors 16\n"
1334 "MaxFragmentInputVectors 15\n"
1335 "MinProgramTexelOffset -8\n"
1336 "MaxProgramTexelOffset 7\n"
1337 "MaxClipDistances 8\n"
1338 "MaxComputeWorkGroupCountX 65535\n"
1339 "MaxComputeWorkGroupCountY 65535\n"
1340 "MaxComputeWorkGroupCountZ 65535\n"
1341 "MaxComputeWorkGroupSizeX 1024\n"
1342 "MaxComputeWorkGroupSizeY 1024\n"
1343 "MaxComputeWorkGroupSizeZ 64\n"
1344 "MaxComputeUniformComponents 1024\n"
1345 "MaxComputeTextureImageUnits 16\n"
1346 "MaxComputeImageUniforms 8\n"
1347 "MaxComputeAtomicCounters 8\n"
1348 "MaxComputeAtomicCounterBuffers 1\n"
1349 "MaxVaryingComponents 60\n"
1350 "MaxVertexOutputComponents 64\n"
1351 "MaxGeometryInputComponents 64\n"
1352 "MaxGeometryOutputComponents 128\n"
1353 "MaxFragmentInputComponents 128\n"
1354 "MaxImageUnits 8\n"
1355 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
1356 "MaxCombinedShaderOutputResources 8\n"
1357 "MaxImageSamples 0\n"
1358 "MaxVertexImageUniforms 0\n"
1359 "MaxTessControlImageUniforms 0\n"
1360 "MaxTessEvaluationImageUniforms 0\n"
1361 "MaxGeometryImageUniforms 0\n"
1362 "MaxFragmentImageUniforms 8\n"
1363 "MaxCombinedImageUniforms 8\n"
1364 "MaxGeometryTextureImageUnits 16\n"
1365 "MaxGeometryOutputVertices 256\n"
1366 "MaxGeometryTotalOutputComponents 1024\n"
1367 "MaxGeometryUniformComponents 1024\n"
1368 "MaxGeometryVaryingComponents 64\n"
1369 "MaxTessControlInputComponents 128\n"
1370 "MaxTessControlOutputComponents 128\n"
1371 "MaxTessControlTextureImageUnits 16\n"
1372 "MaxTessControlUniformComponents 1024\n"
1373 "MaxTessControlTotalOutputComponents 4096\n"
1374 "MaxTessEvaluationInputComponents 128\n"
1375 "MaxTessEvaluationOutputComponents 128\n"
1376 "MaxTessEvaluationTextureImageUnits 16\n"
1377 "MaxTessEvaluationUniformComponents 1024\n"
1378 "MaxTessPatchComponents 120\n"
1379 "MaxPatchVertices 32\n"
1380 "MaxTessGenLevel 64\n"
1381 "MaxViewports 16\n"
1382 "MaxVertexAtomicCounters 0\n"
1383 "MaxTessControlAtomicCounters 0\n"
1384 "MaxTessEvaluationAtomicCounters 0\n"
1385 "MaxGeometryAtomicCounters 0\n"
1386 "MaxFragmentAtomicCounters 8\n"
1387 "MaxCombinedAtomicCounters 8\n"
1388 "MaxAtomicCounterBindings 1\n"
1389 "MaxVertexAtomicCounterBuffers 0\n"
1390 "MaxTessControlAtomicCounterBuffers 0\n"
1391 "MaxTessEvaluationAtomicCounterBuffers 0\n"
1392 "MaxGeometryAtomicCounterBuffers 0\n"
1393 "MaxFragmentAtomicCounterBuffers 1\n"
1394 "MaxCombinedAtomicCounterBuffers 1\n"
1395 "MaxAtomicCounterBufferSize 16384\n"
1396 "MaxTransformFeedbackBuffers 4\n"
1397 "MaxTransformFeedbackInterleavedComponents 64\n"
1398 "MaxCullDistances 8\n"
1399 "MaxCombinedClipAndCullDistances 8\n"
1400 "MaxSamples 4\n"
1401
1402 "nonInductiveForLoops 1\n"
1403 "whileLoops 1\n"
1404 "doWhileLoops 1\n"
1405 "generalUniformIndexing 1\n"
1406 "generalAttributeMatrixVectorIndexing 1\n"
1407 "generalVaryingIndexing 1\n"
1408 "generalSamplerIndexing 1\n"
1409 "generalVariableIndexing 1\n"
1410 "generalConstantMatrixVectorIndexing 1\n"
1411 ;
1412
1413//
1414// *.conf => this is a config file that can set limits/resources
1415//
Tony Barbour6918cd52015-04-09 12:58:51 -06001416bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001417{
1418 if (name.size() < 5)
1419 return false;
1420
1421 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
1422 ConfigFile = name;
1423 return true;
1424 }
1425
1426 return false;
1427}
1428
1429//
1430// Parse either a .conf file provided by the user or the default string above.
1431//
Tony Barbour6918cd52015-04-09 12:58:51 -06001432void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001433{
1434 char** configStrings = 0;
1435 char* config = 0;
1436 if (ConfigFile.size() > 0) {
1437 configStrings = ReadFileData(ConfigFile.c_str());
1438 if (configStrings)
1439 config = *configStrings;
1440 else {
1441 printf("Error opening configuration file; will instead use the default configuration\n");
1442 }
1443 }
1444
1445 if (config == 0) {
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001446 config = (char *) alloca(strlen(DefaultConfig) + 1);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001447 strcpy(config, DefaultConfig);
1448 }
1449
1450 const char* delims = " \t\n\r";
1451 const char* token = strtok(config, delims);
1452 while (token) {
1453 const char* valueStr = strtok(0, delims);
1454 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1455 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1456 return;
1457 }
1458 int value = atoi(valueStr);
1459
1460 if (strcmp(token, "MaxLights") == 0)
1461 Resources.maxLights = value;
1462 else if (strcmp(token, "MaxClipPlanes") == 0)
1463 Resources.maxClipPlanes = value;
1464 else if (strcmp(token, "MaxTextureUnits") == 0)
1465 Resources.maxTextureUnits = value;
1466 else if (strcmp(token, "MaxTextureCoords") == 0)
1467 Resources.maxTextureCoords = value;
1468 else if (strcmp(token, "MaxVertexAttribs") == 0)
1469 Resources.maxVertexAttribs = value;
1470 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1471 Resources.maxVertexUniformComponents = value;
1472 else if (strcmp(token, "MaxVaryingFloats") == 0)
1473 Resources.maxVaryingFloats = value;
1474 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1475 Resources.maxVertexTextureImageUnits = value;
1476 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1477 Resources.maxCombinedTextureImageUnits = value;
1478 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1479 Resources.maxTextureImageUnits = value;
1480 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1481 Resources.maxFragmentUniformComponents = value;
1482 else if (strcmp(token, "MaxDrawBuffers") == 0)
1483 Resources.maxDrawBuffers = value;
1484 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1485 Resources.maxVertexUniformVectors = value;
1486 else if (strcmp(token, "MaxVaryingVectors") == 0)
1487 Resources.maxVaryingVectors = value;
1488 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1489 Resources.maxFragmentUniformVectors = value;
1490 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1491 Resources.maxVertexOutputVectors = value;
1492 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1493 Resources.maxFragmentInputVectors = value;
1494 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1495 Resources.minProgramTexelOffset = value;
1496 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1497 Resources.maxProgramTexelOffset = value;
1498 else if (strcmp(token, "MaxClipDistances") == 0)
1499 Resources.maxClipDistances = value;
1500 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1501 Resources.maxComputeWorkGroupCountX = value;
1502 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1503 Resources.maxComputeWorkGroupCountY = value;
1504 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1505 Resources.maxComputeWorkGroupCountZ = value;
1506 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1507 Resources.maxComputeWorkGroupSizeX = value;
1508 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1509 Resources.maxComputeWorkGroupSizeY = value;
1510 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1511 Resources.maxComputeWorkGroupSizeZ = value;
1512 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1513 Resources.maxComputeUniformComponents = value;
1514 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1515 Resources.maxComputeTextureImageUnits = value;
1516 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1517 Resources.maxComputeImageUniforms = value;
1518 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1519 Resources.maxComputeAtomicCounters = value;
1520 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1521 Resources.maxComputeAtomicCounterBuffers = value;
1522 else if (strcmp(token, "MaxVaryingComponents") == 0)
1523 Resources.maxVaryingComponents = value;
1524 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1525 Resources.maxVertexOutputComponents = value;
1526 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1527 Resources.maxGeometryInputComponents = value;
1528 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1529 Resources.maxGeometryOutputComponents = value;
1530 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1531 Resources.maxFragmentInputComponents = value;
1532 else if (strcmp(token, "MaxImageUnits") == 0)
1533 Resources.maxImageUnits = value;
1534 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1535 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1536 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1537 Resources.maxCombinedShaderOutputResources = value;
1538 else if (strcmp(token, "MaxImageSamples") == 0)
1539 Resources.maxImageSamples = value;
1540 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1541 Resources.maxVertexImageUniforms = value;
1542 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1543 Resources.maxTessControlImageUniforms = value;
1544 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1545 Resources.maxTessEvaluationImageUniforms = value;
1546 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1547 Resources.maxGeometryImageUniforms = value;
1548 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1549 Resources.maxFragmentImageUniforms = value;
1550 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1551 Resources.maxCombinedImageUniforms = value;
1552 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1553 Resources.maxGeometryTextureImageUnits = value;
1554 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1555 Resources.maxGeometryOutputVertices = value;
1556 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1557 Resources.maxGeometryTotalOutputComponents = value;
1558 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1559 Resources.maxGeometryUniformComponents = value;
1560 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1561 Resources.maxGeometryVaryingComponents = value;
1562 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1563 Resources.maxTessControlInputComponents = value;
1564 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1565 Resources.maxTessControlOutputComponents = value;
1566 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1567 Resources.maxTessControlTextureImageUnits = value;
1568 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1569 Resources.maxTessControlUniformComponents = value;
1570 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1571 Resources.maxTessControlTotalOutputComponents = value;
1572 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1573 Resources.maxTessEvaluationInputComponents = value;
1574 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1575 Resources.maxTessEvaluationOutputComponents = value;
1576 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1577 Resources.maxTessEvaluationTextureImageUnits = value;
1578 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1579 Resources.maxTessEvaluationUniformComponents = value;
1580 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1581 Resources.maxTessPatchComponents = value;
1582 else if (strcmp(token, "MaxPatchVertices") == 0)
1583 Resources.maxPatchVertices = value;
1584 else if (strcmp(token, "MaxTessGenLevel") == 0)
1585 Resources.maxTessGenLevel = value;
1586 else if (strcmp(token, "MaxViewports") == 0)
1587 Resources.maxViewports = value;
1588 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1589 Resources.maxVertexAtomicCounters = value;
1590 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1591 Resources.maxTessControlAtomicCounters = value;
1592 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1593 Resources.maxTessEvaluationAtomicCounters = value;
1594 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1595 Resources.maxGeometryAtomicCounters = value;
1596 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1597 Resources.maxFragmentAtomicCounters = value;
1598 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1599 Resources.maxCombinedAtomicCounters = value;
1600 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1601 Resources.maxAtomicCounterBindings = value;
1602 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1603 Resources.maxVertexAtomicCounterBuffers = value;
1604 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1605 Resources.maxTessControlAtomicCounterBuffers = value;
1606 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1607 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1608 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1609 Resources.maxGeometryAtomicCounterBuffers = value;
1610 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1611 Resources.maxFragmentAtomicCounterBuffers = value;
1612 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1613 Resources.maxCombinedAtomicCounterBuffers = value;
1614 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1615 Resources.maxAtomicCounterBufferSize = value;
1616 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1617 Resources.maxTransformFeedbackBuffers = value;
1618 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1619 Resources.maxTransformFeedbackInterleavedComponents = value;
1620 else if (strcmp(token, "MaxCullDistances") == 0)
1621 Resources.maxCullDistances = value;
1622 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1623 Resources.maxCombinedClipAndCullDistances = value;
1624 else if (strcmp(token, "MaxSamples") == 0)
1625 Resources.maxSamples = value;
1626
1627 else if (strcmp(token, "nonInductiveForLoops") == 0)
1628 Resources.limits.nonInductiveForLoops = (value != 0);
1629 else if (strcmp(token, "whileLoops") == 0)
1630 Resources.limits.whileLoops = (value != 0);
1631 else if (strcmp(token, "doWhileLoops") == 0)
1632 Resources.limits.doWhileLoops = (value != 0);
1633 else if (strcmp(token, "generalUniformIndexing") == 0)
1634 Resources.limits.generalUniformIndexing = (value != 0);
1635 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1636 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1637 else if (strcmp(token, "generalVaryingIndexing") == 0)
1638 Resources.limits.generalVaryingIndexing = (value != 0);
1639 else if (strcmp(token, "generalSamplerIndexing") == 0)
1640 Resources.limits.generalSamplerIndexing = (value != 0);
1641 else if (strcmp(token, "generalVariableIndexing") == 0)
1642 Resources.limits.generalVariableIndexing = (value != 0);
1643 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1644 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1645 else
1646 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1647
1648 token = strtok(0, delims);
1649 }
1650 if (configStrings)
1651 FreeFileData(configStrings);
1652}
1653
Tony Barbour6918cd52015-04-09 12:58:51 -06001654void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001655{
1656 if (m_compile_options & EOptionRelaxedErrors)
1657 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1658 if (m_compile_options & EOptionIntermediate)
1659 messages = (EShMessages)(messages | EShMsgAST);
1660 if (m_compile_options & EOptionSuppressWarnings)
1661 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1662}
1663
1664//
1665// Malloc a string of sufficient size and read a string into it.
1666//
Tony Barbour6918cd52015-04-09 12:58:51 -06001667char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001668{
1669 FILE *in;
1670 #if defined(_WIN32) && defined(__GNUC__)
1671 in = fopen(fileName, "r");
1672 int errorCode = in ? 0 : 1;
1673 #else
1674 int errorCode = fopen_s(&in, fileName, "r");
1675 #endif
1676
1677 char *fdata;
1678 int count = 0;
1679 const int maxSourceStrings = 5;
1680 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1681
1682 if (errorCode) {
1683 printf("Error: unable to open input file: %s\n", fileName);
1684 return 0;
1685 }
1686
1687 while (fgetc(in) != EOF)
1688 count++;
1689
1690 fseek(in, 0, SEEK_SET);
1691
1692 if (!(fdata = (char*)malloc(count+2))) {
1693 printf("Error allocating memory\n");
1694 return 0;
1695 }
1696 if (fread(fdata,1,count, in)!=count) {
1697 printf("Error reading input file: %s\n", fileName);
1698 return 0;
1699 }
1700 fdata[count] = '\0';
1701 fclose(in);
1702 if (count == 0) {
1703 return_data[0]=(char*)malloc(count+2);
1704 return_data[0][0]='\0';
1705 m_num_shader_strings = 0;
1706 return return_data;
1707 } else
1708 m_num_shader_strings = 1;
1709
1710 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1711 int ptr_len=0,i=0;
1712 while(count>0){
1713 return_data[i]=(char*)malloc(len+2);
1714 memcpy(return_data[i],fdata+ptr_len,len);
1715 return_data[i][len]='\0';
1716 count-=(len);
1717 ptr_len+=(len);
1718 if(count<len){
1719 if(count==0){
1720 m_num_shader_strings=(i+1);
1721 break;
1722 }
1723 len = count;
1724 }
1725 ++i;
1726 }
1727 return return_data;
1728}
1729
Tony Barbour6918cd52015-04-09 12:58:51 -06001730void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001731{
1732 for(int i=0;i<m_num_shader_strings;i++)
1733 free(data[i]);
1734}
1735
1736//
1737// Deduce the language from the filename. Files must end in one of the
1738// following extensions:
1739//
1740// .vert = vertex
1741// .tesc = tessellation control
1742// .tese = tessellation evaluation
1743// .geom = geometry
1744// .frag = fragment
1745// .comp = compute
1746//
Tony Barbour6918cd52015-04-09 12:58:51 -06001747EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001748{
1749 size_t ext = name.rfind('.');
1750 if (ext == std::string::npos) {
1751 return EShLangVertex;
1752 }
1753
1754 std::string suffix = name.substr(ext + 1, std::string::npos);
1755 if (suffix == "vert")
1756 return EShLangVertex;
1757 else if (suffix == "tesc")
1758 return EShLangTessControl;
1759 else if (suffix == "tese")
1760 return EShLangTessEvaluation;
1761 else if (suffix == "geom")
1762 return EShLangGeometry;
1763 else if (suffix == "frag")
1764 return EShLangFragment;
1765 else if (suffix == "comp")
1766 return EShLangCompute;
1767
1768 return EShLangVertex;
1769}
1770
1771//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001772// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001773//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001774EShLanguage VkTestFramework::FindLanguage(const VkShaderStageFlagBits shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001775{
1776 switch (shader_type) {
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001777 case VK_SHADER_STAGE_VERTEX_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001778 return EShLangVertex;
1779
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001780 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001781 return EShLangTessControl;
1782
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001783 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001784 return EShLangTessEvaluation;
1785
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001786 case VK_SHADER_STAGE_GEOMETRY_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001787 return EShLangGeometry;
1788
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001789 case VK_SHADER_STAGE_FRAGMENT_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001790 return EShLangFragment;
1791
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001792 case VK_SHADER_STAGE_COMPUTE_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001793 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001794
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001795 default:
1796 return EShLangVertex;
1797 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001798}
1799
1800
1801//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001802// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001803// Return value of false means an error was encountered.
1804//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001805bool VkTestFramework::GLSLtoSPV(const VkShaderStageFlagBits shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001806 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001807 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001808{
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001809 glslang::TProgram program;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001810 const char *shaderStrings[1];
1811
1812 // TODO: Do we want to load a special config file depending on the
1813 // shader source? Optional name maybe?
1814 // SetConfigFile(fileName);
1815
1816 ProcessConfigFile();
1817
1818 EShMessages messages = EShMsgDefault;
1819 SetMessageOptions(messages);
1820
1821 EShLanguage stage = FindLanguage(shader_type);
1822 glslang::TShader* shader = new glslang::TShader(stage);
1823
1824 shaderStrings[0] = pshader;
1825 shader->setStrings(shaderStrings, 1);
1826
1827 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1828
Cody Northrop195d6622014-11-03 12:54:37 -07001829 if (! (m_compile_options & EOptionSuppressInfolog)) {
1830 puts(shader->getInfoLog());
1831 puts(shader->getInfoDebugLog());
1832 }
1833
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001834 return false; // something didn't work
1835 }
1836
1837 program.addShader(shader);
1838
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001839
1840 //
1841 // Program-level processing...
1842 //
1843
Cody Northrop195d6622014-11-03 12:54:37 -07001844 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001845
Cody Northrop195d6622014-11-03 12:54:37 -07001846 if (! (m_compile_options & EOptionSuppressInfolog)) {
1847 puts(shader->getInfoLog());
1848 puts(shader->getInfoDebugLog());
1849 }
1850
1851 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001852 }
1853
1854 if (m_compile_options & EOptionDumpReflection) {
1855 program.buildReflection();
1856 program.dumpReflection();
1857 }
1858
Cody Northrop5a95b472015-06-03 13:01:54 -06001859 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1860
1861 //
1862 // Test the different modes of SPIR-V modification
1863 //
1864 if (this->m_canonicalize_spv) {
1865 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1866 }
1867
1868 if (this->m_strip_spv) {
1869 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1870 }
1871
1872 if (this->m_do_everything_spv) {
1873 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1874 }
1875
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001876 delete shader;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001877
1878 return true;
1879}
1880
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001881
1882
Tony Barbour6918cd52015-04-09 12:58:51 -06001883VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001884 m_width( 0 ),
1885 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001886 m_data( NULL ),
1887 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001888{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001889}
1890
Tony Barbour6918cd52015-04-09 12:58:51 -06001891VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001892{
1893
1894}
1895
Tony Barbour6918cd52015-04-09 12:58:51 -06001896VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001897{
1898 m_title = copyin.m_title;
1899 m_width = copyin.m_width;
1900 m_height = copyin.m_height;
1901 m_data_size = copyin.m_data_size;
1902 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1903}
1904
Tony Barbour6918cd52015-04-09 12:58:51 -06001905ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001906{
Tony Barbour6918cd52015-04-09 12:58:51 -06001907 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1908 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001909 return output;
1910}
1911
Tony Barbour6918cd52015-04-09 12:58:51 -06001912VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001913{
1914 m_title = rhs.m_title;
1915 m_width = rhs.m_width;
1916 m_height = rhs.m_height;
1917 m_data_size = rhs.m_data_size;
1918 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001919 return *this;
1920}
1921
Tony Barbour6918cd52015-04-09 12:58:51 -06001922int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001923{
1924 if( this->m_data != rhs.m_data) return 0;
1925 return 1;
1926}
1927
1928// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001929int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001930{
1931 if( this->m_data_size < rhs.m_data_size ) return 1;
1932 return 0;
1933}
1934