blob: be017a7b2830a5b0f5719f8386c693f97a105bec [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"
Cody Northrop5a95b472015-06-03 13:01:54 -060028#include "SPIRV/GlslangToSpv.h"
29#include "SPIRV/SPVRemapper.h"
Tony Barbour4ab45422014-12-10 17:00:20 -070030#include <limits.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060031#include <math.h>
Chia-I Wuec664fa2014-12-02 11:54:24 +080032#include <wand/MagickWand.h>
Ian Elliottc11750d2015-10-30 13:24:12 -060033// FIXME: CAN PROBABLY GET RID OF THE FOLLOWING #include
Tony Barbourfeb61962015-09-21 15:17:33 -060034#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +080035#include <xcb/xcb.h>
Tony Barbourfeb61962015-09-21 15:17:33 -060036#endif
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060037
Tony Barbour3d69c9e2015-05-20 16:53:31 -060038#if defined(PATH_MAX) && !defined(MAX_PATH)
39#define MAX_PATH PATH_MAX
40#endif
41
Tony Barbour6a3faf02015-07-23 10:36:18 -060042#ifdef _WIN32
43#define ERR_EXIT(err_msg, err_class) \
44 do { \
45 MessageBox(NULL, err_msg, err_class, MB_OK); \
46 exit(1); \
47 } while (0)
48#else // _WIN32
49
50#define ERR_EXIT(err_msg, err_class) \
51 do { \
52 printf(err_msg); \
53 fflush(stdout); \
54 exit(1); \
55 } while (0)
56#endif // _WIN32
57
58#define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \
59{ \
60 m_fp##entrypoint = (PFN_vk##entrypoint) vkGetInstanceProcAddr(inst, "vk"#entrypoint); \
61 if (m_fp##entrypoint == NULL) { \
62 ERR_EXIT("vkGetInstanceProcAddr failed to find vk"#entrypoint, \
63 "vkGetInstanceProcAddr Failure"); \
64 } \
65}
66
67#define GET_DEVICE_PROC_ADDR(dev, entrypoint) \
68{ \
69 m_fp##entrypoint = (PFN_vk##entrypoint) vkGetDeviceProcAddr(dev, "vk"#entrypoint); \
70 if (m_fp##entrypoint == NULL) { \
71 ERR_EXIT("vkGetDeviceProcAddr failed to find vk"#entrypoint, \
72 "vkGetDeviceProcAddr Failure"); \
73 } \
74}
75
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060076// Command-line options
77enum TOptions {
78 EOptionNone = 0x000,
79 EOptionIntermediate = 0x001,
80 EOptionSuppressInfolog = 0x002,
81 EOptionMemoryLeakMode = 0x004,
82 EOptionRelaxedErrors = 0x008,
83 EOptionGiveWarnings = 0x010,
84 EOptionLinkProgram = 0x020,
85 EOptionMultiThreaded = 0x040,
86 EOptionDumpConfig = 0x080,
87 EOptionDumpReflection = 0x100,
88 EOptionSuppressWarnings = 0x200,
89 EOptionDumpVersions = 0x400,
Cody Northrop3bfd27c2015-03-17 15:55:58 -060090 EOptionSpv = 0x800,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060091 EOptionDefaultDesktop = 0x1000,
92};
93
Ian Elliott7e40db92015-08-21 15:09:33 -060094typedef struct _SwapchainBuffers {
Tony Barbour6a3faf02015-07-23 10:36:18 -060095 VkImage image;
Chia-I Wu3432a0c2015-10-27 18:04:07 +080096 VkCommandBuffer cmd;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -060097 VkImageView view;
Ian Elliott7e40db92015-08-21 15:09:33 -060098} SwapchainBuffers;
Tony Barbour6a3faf02015-07-23 10:36:18 -060099
Chia-I Wuf8693382015-04-16 22:02:10 +0800100class TestFrameworkVkPresent
101{
102public:
103 TestFrameworkVkPresent(vk_testing::Device &device);
104
105 void Run();
Jon Ashburn07daee72015-05-21 18:13:33 -0600106 void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst);
Chia-I Wuf8693382015-04-16 22:02:10 +0800107 void CreateMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -0600108 void CreateSwapchain();
Tony Barbourbd094ce2015-10-23 11:00:15 -0600109 void SetImageLayout(VkImage image, VkImageAspectFlags aspectMask,
110 VkImageLayout old_image_layout, VkImageLayout new_image_layout);
Chia-I Wuf8693382015-04-16 22:02:10 +0800111 void TearDown();
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600112#ifdef _WIN32
113 static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
114#endif
115
Chia-I Wuf8693382015-04-16 22:02:10 +0800116
117protected:
118 vk_testing::Device &m_device;
119 vk_testing::Queue &m_queue;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800120 vk_testing::CommandPool m_cmdpool;
121 vk_testing::CommandBuffer m_cmdbuf;
Chia-I Wuf8693382015-04-16 22:02:10 +0800122
123private:
Ian Elliottc11750d2015-10-30 13:24:12 -0600124 VkInstance m_instance;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600125#ifdef _WIN32
126 HINSTANCE m_connection; // hInstance - Windows Instance
127 HWND m_window; // hWnd - window handle
128
129#else
Chia-I Wuf8693382015-04-16 22:02:10 +0800130 xcb_connection_t *m_connection;
131 xcb_screen_t *m_screen;
132 xcb_window_t m_window;
133 xcb_intern_atom_reply_t *m_atom_wm_delete_window;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600134#endif
Ian Elliottc11750d2015-10-30 13:24:12 -0600135 VkSurfaceKHR m_surface;
Courtney Goeltzenleuchterd6079ec2015-04-22 10:09:35 -0600136 std::list<VkTestImageRecord> m_images;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600137 uint32_t m_present_queue_node_index;
Chia-I Wuf8693382015-04-16 22:02:10 +0800138
Ian Elliott7e40db92015-08-21 15:09:33 -0600139 PFN_vkGetPhysicalDeviceSurfaceSupportKHR m_fpGetPhysicalDeviceSurfaceSupportKHR;
Ian Elliottc11750d2015-10-30 13:24:12 -0600140 PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR m_fpGetPhysicalDeviceSurfaceCapabilitiesKHR;
141 PFN_vkGetPhysicalDeviceSurfaceFormatsKHR m_fpGetPhysicalDeviceSurfaceFormatsKHR;
142 PFN_vkGetPhysicalDeviceSurfacePresentModesKHR m_fpGetPhysicalDeviceSurfacePresentModesKHR;
Ian Elliott7e40db92015-08-21 15:09:33 -0600143 PFN_vkCreateSwapchainKHR m_fpCreateSwapchainKHR;
144 PFN_vkDestroySwapchainKHR m_fpDestroySwapchainKHR;
145 PFN_vkGetSwapchainImagesKHR m_fpGetSwapchainImagesKHR;
146 PFN_vkAcquireNextImageKHR m_fpAcquireNextImageKHR;
147 PFN_vkQueuePresentKHR m_fpQueuePresentKHR;
Ian Elliott7e40db92015-08-21 15:09:33 -0600148 uint32_t m_swapchainImageCount;
149 VkSwapchainKHR m_swap_chain;
150 SwapchainBuffers *m_buffers;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600151 VkFormat m_format;
Ian Elliott7e40db92015-08-21 15:09:33 -0600152 VkColorSpaceKHR m_color_space;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600153
154 uint32_t m_current_buffer;
Chia-I Wuf8693382015-04-16 22:02:10 +0800155
156 bool m_quit;
157 bool m_pause;
158
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600159 int m_width;
160 int m_height;
Chia-I Wuf8693382015-04-16 22:02:10 +0800161
162 std::list<VkTestImageRecord>::iterator m_display_image;
163
164 void Display();
Tony Barbourfeb61962015-09-21 15:17:33 -0600165#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800166 void HandleEvent(xcb_generic_event_t *event);
Tony Barbourfeb61962015-09-21 15:17:33 -0600167#endif
Chia-I Wuf8693382015-04-16 22:02:10 +0800168};
169
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600170#ifndef _WIN32
171
172#include <errno.h>
173
174int fopen_s(
175 FILE** pFile,
176 const char* filename,
177 const char* mode
178)
179{
180 if (!pFile || !filename || !mode) {
181 return EINVAL;
182 }
183
184 FILE* f = fopen(filename, mode);
185 if (! f) {
186 if (errno != 0) {
187 return errno;
188 } else {
189 return ENOENT;
190 }
191 }
192 *pFile = f;
193
194 return 0;
195}
196
197#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600198
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600199
200
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600201// Set up environment for GLSL compiler
202// Must be done once per process
203void TestEnvironment::SetUp()
204{
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600205 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600206 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800207
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600208 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600209}
210
211void TestEnvironment::TearDown()
212{
213 glslang::FinalizeProcess();
214}
215
Tony Barbour6918cd52015-04-09 12:58:51 -0600216VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600217 m_compile_options( 0 ),
218 m_num_shader_strings( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600219{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600220
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600221}
222
Tony Barbour6918cd52015-04-09 12:58:51 -0600223VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600224{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600225
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600226}
227
228// Define all the static elements
Cody Northropa3673cf2015-06-09 13:00:45 -0600229bool VkTestFramework::m_show_images = false;
230bool VkTestFramework::m_save_images = false;
231bool VkTestFramework::m_compare_images = false;
232bool VkTestFramework::m_use_glsl = false;
233bool VkTestFramework::m_canonicalize_spv = false;
234bool VkTestFramework::m_strip_spv = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600235bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour6918cd52015-04-09 12:58:51 -0600236int VkTestFramework::m_width = 0;
237int VkTestFramework::m_height = 0;
238std::list<VkTestImageRecord> VkTestFramework::m_images;
239std::list<VkTestImageRecord>::iterator VkTestFramework::m_display_image;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600240int m_display_image_idx = 0;
241
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600242bool VkTestFramework::optionMatch(const char* option, char* optionLine)
243{
244 if (strncmp(option, optionLine, strlen(option)) == 0)
245 return true;
246 else
247 return false;
248}
249
Tony Barbour6918cd52015-04-09 12:58:51 -0600250void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600251{
252 int i, n;
253
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600254 for (i=1, n=1; i< *argc; i++) {
255 if (optionMatch("--show-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600256 m_show_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600257 else if (optionMatch("--save-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600258 m_save_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600259 else if (optionMatch("--no-SPV", argv[i]))
260 m_use_glsl = true;
261 else if (optionMatch("--strip-SPV", argv[i]))
262 m_strip_spv = true;
263 else if (optionMatch("--canonicalize-SPV", argv[i]))
264 m_canonicalize_spv = true;
265 else if (optionMatch("--compare-images", argv[i]))
Tony Barbour247bf372014-10-30 14:29:04 -0600266 m_compare_images = true;
Tony Barbour247bf372014-10-30 14:29:04 -0600267
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600268 else if (optionMatch("--help", argv[i]) ||
269 optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700270 printf("\nOther options:\n");
271 printf("\t--show-images\n"
272 "\t\tDisplay test images in viewer after tests complete.\n");
273 printf("\t--save-images\n"
274 "\t\tSave tests images as ppm files in current working directory.\n"
275 "\t\tUsed to generate golden images for compare-images.\n");
276 printf("\t--compare-images\n"
277 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barboura98d3932014-12-11 09:52:49 -0700278 "\t\tAlso saves the generated test image in current working\n"
279 "\t\t\tdirectory but only if the image is different from the golden\n"
280 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
281 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700282 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600283 printf("\t--no-SPV\n"
284 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600285 printf("\t--strip-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600286 "\t\tStrip SPIR-V debug information (line numbers, names, etc).\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600287 printf("\t--canonicalize-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600288 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600289 exit(0);
290 } else {
291 printf("\nUnrecognized option: %s\n", argv[i]);
292 printf("\nUse --help or -h for option list.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700293 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700294 }
295
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600296 /*
297 * Since the above "consume" inputs, update argv
298 * so that it contains the trimmed list of args for glutInit
299 */
300
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600301 argv[n] = argv[i];
302 n++;
303 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600304}
305
Tony Barbour6918cd52015-04-09 12:58:51 -0600306void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600307{
308 string filename;
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600309 uint32_t x, y;
Tony Barbour6918cd52015-04-09 12:58:51 -0600310 VkImageObj displayImage(image->device());
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600311 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbour84d448c2015-04-02 14:02:33 -0600312
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800313 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 -0600314 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600315
316 filename.append(basename);
317 filename.append(".ppm");
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600318
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600319 const VkImageSubresource sr = {
Courtney Goeltzenleuchter908e7672015-10-21 17:00:51 -0600320 VK_IMAGE_ASPECT_COLOR_BIT, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600321 };
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600322 VkSubresourceLayout sr_layout;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600323
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600324 vkGetImageSubresourceLayout(image->device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600325
Tony Barbour84d448c2015-04-02 14:02:33 -0600326 char *ptr;
Chia-I Wu681d7a02015-07-03 13:44:34 +0800327 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600328 ptr += sr_layout.offset;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600329 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600330 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
331
332 file << "P6\n";
Tony Barbourfeb61962015-09-21 15:17:33 -0600333 file << displayImage.width() << " ";
Tony Barbour84d448c2015-04-02 14:02:33 -0600334 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600335 file << 255 << "\n";
336
Tony Barbour84d448c2015-04-02 14:02:33 -0600337 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700338 const int *row = (const int *) ptr;
339 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600340
Tony Barbourd1c35722015-04-16 15:59:00 -0600341 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700342 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600343 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700344 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
345 file.write((char *) &swapped, 3);
346 row++;
347 }
348 }
Tony Barbourd1c35722015-04-16 15:59:00 -0600349 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700350 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600351 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700352 file.write((char *) row, 3);
353 row++;
354 }
355 }
356 else {
357 printf("Unrecognized image format - will not write image files");
358 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600359 }
360
361 ptr += sr_layout.rowPitch;
362 }
363
364 file.close();
Chia-I Wu681d7a02015-07-03 13:44:34 +0800365 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600366}
367
Tony Barbour6918cd52015-04-09 12:58:51 -0600368void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour247bf372014-10-30 14:29:04 -0600369{
370
371 MagickWand *magick_wand_1;
372 MagickWand *magick_wand_2;
373 MagickWand *compare_wand;
374 MagickBooleanType status;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600375 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600376 double differenz;
377
Tony Barbour4ab45422014-12-10 17:00:20 -0700378 if (getenv("RENDERTEST_GOLDEN_DIR"))
379 {
380 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
381 }
382
Tony Barbour247bf372014-10-30 14:29:04 -0600383 MagickWandGenesis();
384 magick_wand_1=NewMagickWand();
385 sprintf(testimage,"%s.ppm",basename);
386 status=MagickReadImage(magick_wand_1,testimage);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600387 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour247bf372014-10-30 14:29:04 -0600388
389
390 MagickWandGenesis();
391 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700392 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600393 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600394 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour247bf372014-10-30 14:29:04 -0600395
Tony Barbour247bf372014-10-30 14:29:04 -0600396 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
397 if (differenz != 0.0)
398 {
399 char difference[256];
400
401 sprintf(difference,"%s-diff.ppm",basename);
402 status = MagickWriteImage(compare_wand, difference);
403 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
404 }
405 DestroyMagickWand(compare_wand);
406
407 DestroyMagickWand(magick_wand_1);
408 DestroyMagickWand(magick_wand_2);
409 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700410
411 if (differenz == 0.0)
412 {
413 /*
414 * If test image and golden image match, we do not need to
415 * keep around the test image.
416 */
417 remove(testimage);
418 }
Tony Barbour247bf372014-10-30 14:29:04 -0600419}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600420
Tony Barbour6918cd52015-04-09 12:58:51 -0600421void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600422{
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600423 VkSubresourceLayout sr_layout;
424 char *ptr;
425 VkTestImageRecord record;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600426 VkImageObj displayImage(image->device());
427 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
428
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800429 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 -0600430
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600431 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600432
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600433 const VkImageSubresource sr = {
Courtney Goeltzenleuchter908e7672015-10-21 17:00:51 -0600434 VK_IMAGE_ASPECT_COLOR_BIT, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600435 };
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600436
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600437 vkGetImageSubresourceLayout(displayImage.device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600438
Chia-I Wu681d7a02015-07-03 13:44:34 +0800439 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600440 ptr += sr_layout.offset;
441
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600442 record.m_title.append(comment);
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600443 record.m_width = displayImage.width();
444 record.m_height = displayImage.height();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600445 // TODO: Need to make this more robust to handle different image formats
Tony-LunarG399dfca2015-05-19 14:08:26 -0600446 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600447 record.m_data = malloc(record.m_data_size);
448 memcpy(record.m_data, ptr, record.m_data_size);
449 m_images.push_back(record);
450 m_display_image = --m_images.end();
451
Chia-I Wu681d7a02015-07-03 13:44:34 +0800452 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600453}
454
Tony Barbour6918cd52015-04-09 12:58:51 -0600455void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600456{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600457 for (int32_t i = 0; i < images.size(); i++) {
458 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600459 }
460}
461
Tony Barbour6918cd52015-04-09 12:58:51 -0600462void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600463{
464 const ::testing::TestInfo* const test_info =
465 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600466 ostringstream filestream;
467 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600468
Tony Barbour247bf372014-10-30 14:29:04 -0600469 m_width = 40;
470
471 if (strcmp(test_info->name(), m_testName.c_str())) {
472 filestream << test_info->name();
473 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700474 m_frameNum = 2;
475 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600476 }
477 else {
478 filestream << test_info->name() << "-" << m_frameNum;
479 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700480 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600481 }
482
Tony Barbour247bf372014-10-30 14:29:04 -0600483 // ToDo - scrub string for bad characters
484
485 if (m_save_images || m_compare_images) {
486 WritePPM(filename.c_str(), image);
487 if (m_compare_images) {
488 Compare(filename.c_str(), image);
489 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600490 }
491
492 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600493 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600494 }
495}
496
Chia-I Wuf8693382015-04-16 22:02:10 +0800497TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
498 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700499 m_queue(*m_device.graphics_queues()[0]),
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800500 m_cmdpool(m_device, vk_testing::CommandPool::create_info(m_device.graphics_queue_node_index_)),
501 m_cmdbuf(m_device, vk_testing::CommandBuffer::create_info(m_cmdpool.handle()))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600502{
Tony Barbour96db8822015-02-25 12:28:39 -0700503 m_quit = false;
504 m_pause = false;
505 m_width = 0;
506 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600507}
508
Tony Barbour6918cd52015-04-09 12:58:51 -0600509void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600510{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600511 VkResult U_ASSERT_ONLY err;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600512 vk_testing::Buffer buf;
513 void *dest_ptr;
514
Tony Barbour6a3faf02015-07-23 10:36:18 -0600515 VkSemaphore presentCompleteSemaphore;
516 VkSemaphoreCreateInfo presentCompleteSemaphoreCreateInfo = {};
517 presentCompleteSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
518 presentCompleteSemaphoreCreateInfo.pNext = NULL;
519 presentCompleteSemaphoreCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
520
521
522 err = vkCreateSemaphore(m_device.handle(),
523 &presentCompleteSemaphoreCreateInfo,
Chia-I Wuf7458c52015-10-26 21:10:41 +0800524 NULL, &presentCompleteSemaphore);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600525 assert(!err);
526
527 // Get the index of the next available swapchain image:
Ian Elliott7e40db92015-08-21 15:09:33 -0600528 err = m_fpAcquireNextImageKHR(m_device.handle(), m_swap_chain,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600529 UINT64_MAX,
530 presentCompleteSemaphore,
Ian Elliottc11750d2015-10-30 13:24:12 -0600531 VK_NULL_HANDLE,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600532 &m_current_buffer);
Ian Elliott7e40db92015-08-21 15:09:33 -0600533 // TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
Tony Barbour6a3faf02015-07-23 10:36:18 -0600534 // return codes
535 assert(!err);
536
Tony-LunarG399dfca2015-05-19 14:08:26 -0600537 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Cody Northrop7fb43862015-06-22 14:56:14 -0600538 buf.init_as_src(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800539 dest_ptr = buf.memory().map();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600540 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800541 buf.memory().unmap();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600542
543 m_cmdbuf.begin();
Tony Barbourbd094ce2015-10-23 11:00:15 -0600544 VkImageMemoryBarrier memoryBarrier = {};
545 memoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
546 memoryBarrier.pNext = NULL;
Tony Barbourd800bbd2015-11-05 10:54:44 -0700547 memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
Chia-I Wua4594202015-10-27 19:54:37 +0800548 memoryBarrier.dstAccessMask = 0;
Ian Elliott1dcd1092015-11-17 17:29:40 -0700549 memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800550 memoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600551 memoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800552 memoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600553 memoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
554 memoryBarrier.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800555 memoryBarrier.subresourceRange.levelCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600556 memoryBarrier.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800557 memoryBarrier.subresourceRange.layerCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600558 memoryBarrier.image = m_buffers[m_current_buffer].image;
559 VkImageMemoryBarrier *pmemory_barrier = &memoryBarrier;
Chia-I Wu89d0f942015-10-31 00:31:16 +0800560 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 +0800561 0, 1, (const void * const*)&pmemory_barrier);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600562
563 VkBufferImageCopy region = {};
Tony Barbourd800bbd2015-11-05 10:54:44 -0700564 region.bufferRowLength = m_display_image->m_width;
565 region.bufferImageHeight = m_display_image->m_height;
566 region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
567 region.imageSubresource.layerCount = 1;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600568 region.imageExtent.height = m_display_image->m_height;
569 region.imageExtent.width = m_display_image->m_width;
570 region.imageExtent.depth = 1;
571
Chia-I Wube2b9172015-07-03 11:49:42 +0800572 vkCmdCopyBufferToImage(m_cmdbuf.handle(),
Chia-I Wu681d7a02015-07-03 13:44:34 +0800573 buf.handle(),
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800574 m_buffers[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600575 1, &region);
Tony Barbourbd094ce2015-10-23 11:00:15 -0600576
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800577 memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
Ian Elliott1dcd1092015-11-17 17:29:40 -0700578 memoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
Chia-I Wu89d0f942015-10-31 00:31:16 +0800579 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 +0800580 0, 1, (const void * const*)&pmemory_barrier);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600581 m_cmdbuf.end();
582
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800583 VkCommandBuffer cmdBufs[1];
Chia-I Wube2b9172015-07-03 11:49:42 +0800584 cmdBufs[0] = m_cmdbuf.handle();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600585
Chia-I Wua690b412015-10-29 22:01:53 +0800586 // Wait for the present complete semaphore to be signaled to ensure
587 // that the image won't be rendered to until the presentation
588 // engine has fully released ownership to the application, and it is
589 // okay to render to the image.
Tony Barbour67e99152015-07-10 14:10:27 -0600590 VkFence nullFence = { VK_NULL_HANDLE };
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600591 VkSubmitInfo submit_info;
Chia-I Wuf9be13c2015-10-26 20:37:06 +0800592 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
593 submit_info.pNext = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +0800594 submit_info.waitSemaphoreCount = 1;
Chia-I Wua690b412015-10-29 22:01:53 +0800595 submit_info.pWaitSemaphores = &presentCompleteSemaphore,
Chia-I Wud50a7d72015-10-26 20:48:51 +0800596 submit_info.commandBufferCount = 1;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600597 submit_info.pCommandBuffers = cmdBufs;
Chia-I Wud50a7d72015-10-26 20:48:51 +0800598 submit_info.signalSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600599 submit_info.pSignalSemaphores = NULL;
600
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -0600601 vkQueueSubmit(m_queue.handle(), 1, &submit_info, nullFence);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600602 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700603
Chia-I Wuf7458c52015-10-26 21:10:41 +0800604 vkDestroySemaphore(m_device.handle(), presentCompleteSemaphore, NULL);
Chia-I Wua690b412015-10-29 22:01:53 +0800605
Ian Elliott7e40db92015-08-21 15:09:33 -0600606 VkPresentInfoKHR present = {};
607 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600608 present.pNext = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600609 present.swapchainCount = 1;
Ian Elliottc11750d2015-10-30 13:24:12 -0600610 present.pSwapchains = & m_swap_chain;
611 present.pImageIndices = &m_current_buffer;
Tony Barbour96db8822015-02-25 12:28:39 -0700612
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600613#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800614 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700615 XCB_PROP_MODE_REPLACE,
616 m_window,
617 XCB_ATOM_WM_NAME,
618 XCB_ATOM_STRING,
619 8,
620 m_display_image->m_title.size(),
621 m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600622#endif
Jon Ashburn07daee72015-05-21 18:13:33 -0600623
Ian Elliott7e40db92015-08-21 15:09:33 -0600624 err = m_fpQueuePresentKHR(m_queue.handle(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700625 assert(!err);
626
627 m_queue.wait();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600628 m_current_buffer = (m_current_buffer + 1) % 2;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600629}
630
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600631#ifdef _WIN32
Tony-LunarG399dfca2015-05-19 14:08:26 -0600632# define PREVIOUSLY_DOWN 1<<29
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600633// MS-Windows event handling function:
634LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
635 UINT uMsg,
636 WPARAM wParam,
637 LPARAM lParam)
638{
639
640 switch(uMsg)
641 {
642 case WM_CLOSE:
643 PostQuitMessage(0);
644 break;
645
646 case WM_PAINT:
647 {
648 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
649 if (me) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600650 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600651 me->Display();
652 }
653 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600654 break;
655
656 case WM_KEYDOWN:
657 {
658 if (lParam & (PREVIOUSLY_DOWN)){
659 break;
660 }
661 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
662 // the window, we put the this pointer into the window's user data so we could get it back now
663 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
664 switch (wParam)
665 {
666 case VK_ESCAPE: me->m_quit = true;
667 break;
668
669 case VK_LEFT: // left arrow key
670 if (me->m_display_image == me->m_images.begin()) {
671 me->m_display_image = --me->m_images.end();
672 }
673 else {
674 --me->m_display_image;
675 }
676 break;
677
678 case VK_RIGHT: // right arrow key
679 ++me->m_display_image;
680 if (me->m_display_image == me->m_images.end()) {
681 me->m_display_image = me->m_images.begin();
682 }
683 break;
684
685 default:
686 break;
687 }
688 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
689 me->Display();
690 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600691 }
692 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
693}
694
695void TestFrameworkVkPresent::Run()
696{
697 MSG msg; // message
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600698
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600699 /* main message loop*/
Tony-LunarG399dfca2015-05-19 14:08:26 -0600700 while(! m_quit) {
701 GetMessage(&msg, m_window, 0, 0);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600702 if (msg.message == WM_QUIT) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600703 m_quit = true; //if found, quit app
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600704 } else {
705 /* Translate and dispatch to event queue*/
706 TranslateMessage(&msg);
707 DispatchMessage(&msg);
708 }
709 }
710}
711
712#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600713void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600714{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600715 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700716 switch (event_code) {
717 case XCB_EXPOSE:
718 Display(); // TODO: handle resize
719 break;
720 case XCB_CLIENT_MESSAGE:
721 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
722 (m_atom_wm_delete_window)->atom) {
723 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600724 }
725 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700726 case XCB_KEY_RELEASE:
727 {
728 const xcb_key_release_event_t *key =
729 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600730
Tony Barbour96db8822015-02-25 12:28:39 -0700731 switch (key->detail) {
732 case 0x9: // Escape
733 m_quit = true;
734 break;
735 case 0x71: // left arrow key
736 if (m_display_image == m_images.begin()) {
737 m_display_image = --m_images.end();
738 } else {
739 --m_display_image;
740 }
741 break;
742 case 0x72: // right arrow key
743 ++m_display_image;
744 if (m_display_image == m_images.end()) {
745 m_display_image = m_images.begin();
746 }
747 break;
748 case 0x41:
749 m_pause = !m_pause;
750 break;
751 }
752 Display();
753 }
754 break;
755 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600756 break;
757 }
Tony Barbour96db8822015-02-25 12:28:39 -0700758}
759
Tony Barbour6918cd52015-04-09 12:58:51 -0600760void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700761{
Chia-I Wuf8693382015-04-16 22:02:10 +0800762 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700763
764 while (! m_quit) {
765 xcb_generic_event_t *event;
766
767 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800768 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700769 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800770 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700771 }
772 if (event) {
773 HandleEvent(event);
774 free(event);
775 }
776 }
777}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600778#endif // _WIN32
Tony Barbour96db8822015-02-25 12:28:39 -0700779
Ian Elliott7e40db92015-08-21 15:09:33 -0600780void TestFrameworkVkPresent::CreateSwapchain()
Tony Barbour96db8822015-02-25 12:28:39 -0700781{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600782 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700783
Tony-LunarG399dfca2015-05-19 14:08:26 -0600784 m_display_image = m_images.begin();
785 m_current_buffer = 0;
786
Ian Elliottc11750d2015-10-30 13:24:12 -0600787 // Create the WSI surface:
Ian Elliott1a3845b2015-07-06 14:33:04 -0600788#ifdef _WIN32
Ian Elliottc11750d2015-10-30 13:24:12 -0600789 err = vkCreateWin32SurfaceKHR(m_instance, m_connection,
790 m_window, NULL, &m_surface);
Ian Elliott1a3845b2015-07-06 14:33:04 -0600791#else // _WIN32
Ian Elliottc11750d2015-10-30 13:24:12 -0600792 err = vkCreateXcbSurfaceKHR(m_instance, m_connection,
793 m_window, NULL, &m_surface);
Ian Elliott1a3845b2015-07-06 14:33:04 -0600794#endif // _WIN32
Ian Elliottc11750d2015-10-30 13:24:12 -0600795 assert(!err);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600796
797 // Iterate over each queue to learn whether it supports presenting to WSI:
798 VkBool32 supportsPresent;
799 m_present_queue_node_index = UINT32_MAX;
800 std::vector<vk_testing::Queue *> queues = m_device.graphics_queues();
801 for (int i=0; i < queues.size(); i++)
802 {
803 int family_index = queues[i]->get_family_index();
Ian Elliott7e40db92015-08-21 15:09:33 -0600804 m_fpGetPhysicalDeviceSurfaceSupportKHR(m_device.phy().handle(),
Tony Barbour6a3faf02015-07-23 10:36:18 -0600805 family_index,
Ian Elliottc11750d2015-10-30 13:24:12 -0600806 m_surface,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600807 &supportsPresent);
808 if (supportsPresent) {
809 m_present_queue_node_index = family_index;
810 }
811 }
812
813 assert(m_present_queue_node_index != UINT32_MAX);
814
815
816 // Get the list of VkFormat's that are supported:
Ian Elliott8b139792015-08-07 11:51:12 -0600817 uint32_t formatCount;
Ian Elliottc11750d2015-10-30 13:24:12 -0600818 err = m_fpGetPhysicalDeviceSurfaceFormatsKHR(m_device.phy().handle(),
819 m_surface,
Ian Elliott8b139792015-08-07 11:51:12 -0600820 &formatCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600821 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600822 VkSurfaceFormatKHR *surfFormats =
823 (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
Ian Elliottc11750d2015-10-30 13:24:12 -0600824 err = m_fpGetPhysicalDeviceSurfaceFormatsKHR(m_device.phy().handle(),
825 m_surface,
Ian Elliott8b139792015-08-07 11:51:12 -0600826 &formatCount, surfFormats);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600827 assert(!err);
828 // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
829 // the surface has no preferred format. Otherwise, at least one
830 // supported format will be returned.
Tony Barbour6a3faf02015-07-23 10:36:18 -0600831 if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED)
832 {
833 m_format = VK_FORMAT_B8G8R8A8_UNORM;
834 }
835 else
836 {
837 assert(formatCount >= 1);
838 m_format = surfFormats[0].format;
839 }
Ian Elliott8b139792015-08-07 11:51:12 -0600840 m_color_space = surfFormats[0].colorSpace;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600841
Ian Elliottc11750d2015-10-30 13:24:12 -0600842 // Check the surface capabilities and formats
843 VkSurfaceCapabilitiesKHR surfCapabilities;
844 err = m_fpGetPhysicalDeviceSurfaceCapabilitiesKHR(m_device.phy().handle(),
845 m_surface,
846 &surfCapabilities);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600847 assert(!err);
848
Ian Elliott8b139792015-08-07 11:51:12 -0600849 uint32_t presentModeCount;
Ian Elliottc11750d2015-10-30 13:24:12 -0600850 err = m_fpGetPhysicalDeviceSurfacePresentModesKHR(m_device.phy().handle(),
851 m_surface,
Ian Elliott8b139792015-08-07 11:51:12 -0600852 &presentModeCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600853 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600854 VkPresentModeKHR *presentModes =
855 (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
Ian Elliott8b139792015-08-07 11:51:12 -0600856 assert(presentModes);
Ian Elliottc11750d2015-10-30 13:24:12 -0600857 err = m_fpGetPhysicalDeviceSurfacePresentModesKHR(m_device.phy().handle(),
858 m_surface,
Ian Elliott8b139792015-08-07 11:51:12 -0600859 &presentModeCount, presentModes);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600860 assert(!err);
861
Ian Elliott7e40db92015-08-21 15:09:33 -0600862 VkExtent2D swapchainExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600863 // width and height are either both -1, or both not -1.
Ian Elliottc11750d2015-10-30 13:24:12 -0600864 if (surfCapabilities.currentExtent.width == -1)
Tony Barbour6a3faf02015-07-23 10:36:18 -0600865 {
866 // If the surface size is undefined, the size is set to
867 // the size of the images requested.
Ian Elliott7e40db92015-08-21 15:09:33 -0600868 swapchainExtent.width = m_width;
869 swapchainExtent.height = m_height;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600870 }
871 else
872 {
873 // If the surface size is defined, the swap chain size must match
Ian Elliottc11750d2015-10-30 13:24:12 -0600874 swapchainExtent = surfCapabilities.currentExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600875 }
876
877 // If mailbox mode is available, use it, as is the lowest-latency non-
Ian Elliottae0e8242015-08-10 13:20:49 -0600878 // tearing mode. If not, try IMMEDIATE which will usually be available,
879 // and is fastest (though it tears). If not, fall back to FIFO which is
880 // always available.
Ian Elliott7e40db92015-08-21 15:09:33 -0600881 VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600882 for (size_t i = 0; i < presentModeCount; i++) {
Ian Elliott7e40db92015-08-21 15:09:33 -0600883 if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
884 swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600885 break;
886 }
Ian Elliott7e40db92015-08-21 15:09:33 -0600887 if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) &&
888 (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
889 swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
Ian Elliottae0e8242015-08-10 13:20:49 -0600890 }
Tony Barbour6a3faf02015-07-23 10:36:18 -0600891 }
892
893 // Determine the number of VkImage's to use in the swap chain (we desire to
894 // own only 1 image at a time, besides the images being displayed and
895 // queued for display):
Ian Elliottc11750d2015-10-30 13:24:12 -0600896 uint32_t desiredNumberOfSwapchainImages = surfCapabilities.minImageCount + 1;
897 if ((surfCapabilities.maxImageCount > 0) &&
898 (desiredNumberOfSwapchainImages > surfCapabilities.maxImageCount))
Tony Barbour6a3faf02015-07-23 10:36:18 -0600899 {
900 // Application must settle for fewer images than desired:
Ian Elliottc11750d2015-10-30 13:24:12 -0600901 desiredNumberOfSwapchainImages = surfCapabilities.maxImageCount;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600902 }
903
Ian Elliottc11750d2015-10-30 13:24:12 -0600904 VkSurfaceTransformFlagsKHR preTransform;
905 if (surfCapabilities.supportedTransforms & VK_SURFACE_TRANSFORM_NONE_BIT_KHR) {
906 preTransform = VK_SURFACE_TRANSFORM_NONE_BIT_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600907 } else {
Ian Elliottc11750d2015-10-30 13:24:12 -0600908 preTransform = surfCapabilities.currentTransform;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600909 }
Ian Elliott1a3845b2015-07-06 14:33:04 -0600910
Cody Northropdf5b0922015-08-28 16:22:48 -0600911 // 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 -0600912 assert((surfCapabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) != 0);
Cody Northropdf5b0922015-08-28 16:22:48 -0600913
Ian Elliott7e40db92015-08-21 15:09:33 -0600914 VkSwapchainCreateInfoKHR swap_chain = {};
Ian Elliotta257eea2015-09-22 10:20:23 -0600915 swap_chain.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600916 swap_chain.pNext = NULL;
Ian Elliottc11750d2015-10-30 13:24:12 -0600917 swap_chain.surface = m_surface;
Ian Elliott7e40db92015-08-21 15:09:33 -0600918 swap_chain.minImageCount = desiredNumberOfSwapchainImages;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600919 swap_chain.imageFormat = m_format;
Ian Elliott8b139792015-08-07 11:51:12 -0600920 swap_chain.imageColorSpace = m_color_space;
Ian Elliott7e40db92015-08-21 15:09:33 -0600921 swap_chain.imageExtent.width = swapchainExtent.width;
922 swap_chain.imageExtent.height = swapchainExtent.height;
Ian Elliottc11750d2015-10-30 13:24:12 -0600923 swap_chain.imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT |
924 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
925 swap_chain.preTransform = (VkSurfaceTransformFlagBitsKHR) preTransform;
926 swap_chain.imageArrayLayers = 1;
927 swap_chain.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
928 swap_chain.queueFamilyIndexCount = 0;
Ian Elliott8b139792015-08-07 11:51:12 -0600929 swap_chain.pQueueFamilyIndices = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600930 swap_chain.presentMode = swapchainPresentMode;
Chia-I Wue2fc5522015-10-26 20:04:44 +0800931 swap_chain.oldSwapchain = VK_NULL_HANDLE;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600932 swap_chain.clipped = true;
933
934 uint32_t i;
Chia-I Wuf8693382015-04-16 22:02:10 +0800935
Ian Elliottc11750d2015-10-30 13:24:12 -0600936 err = m_fpCreateSwapchainKHR(m_device.handle(), &swap_chain, NULL, &m_swap_chain);
Chia-I Wuf8693382015-04-16 22:02:10 +0800937 assert(!err);
938
Ian Elliott7e40db92015-08-21 15:09:33 -0600939 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
940 &m_swapchainImageCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600941 assert(!err);
942
Ian Elliott7e40db92015-08-21 15:09:33 -0600943 VkImage* swapchainImages = (VkImage*)malloc(m_swapchainImageCount * sizeof(VkImage));
944 assert(swapchainImages);
945 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
946 &m_swapchainImageCount, swapchainImages);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600947 assert(!err);
948
Ian Elliott7e40db92015-08-21 15:09:33 -0600949 m_buffers = (SwapchainBuffers*)malloc(sizeof(SwapchainBuffers)*m_swapchainImageCount);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600950 assert(m_buffers);
951
Ian Elliott7e40db92015-08-21 15:09:33 -0600952 for (i = 0; i < m_swapchainImageCount; i++) {
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600953 VkImageViewCreateInfo color_image_view = {};
954 color_image_view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
955 color_image_view.pNext = NULL;
956 color_image_view.format = m_format;
Tony Barbourd800bbd2015-11-05 10:54:44 -0700957 color_image_view.components.r = VK_COMPONENT_SWIZZLE_R;
958 color_image_view.components.g = VK_COMPONENT_SWIZZLE_G;
959 color_image_view.components.b = VK_COMPONENT_SWIZZLE_B;
960 color_image_view.components.a = VK_COMPONENT_SWIZZLE_A;
Courtney Goeltzenleuchterba724512015-09-10 17:58:54 -0600961 color_image_view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600962 color_image_view.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800963 color_image_view.subresourceRange.levelCount = 1;
Courtney Goeltzenleuchter4a261892015-09-10 16:38:41 -0600964 color_image_view.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800965 color_image_view.subresourceRange.layerCount = 1;
Tony Barbourd800bbd2015-11-05 10:54:44 -0700966 color_image_view.viewType = VK_IMAGE_VIEW_TYPE_2D;
967 color_image_view.flags = 0;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600968
Ian Elliott7e40db92015-08-21 15:09:33 -0600969 m_buffers[i].image = swapchainImages[i];
Tony Barbour6a3faf02015-07-23 10:36:18 -0600970
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600971 color_image_view.image = m_buffers[i].image;
972 err = vkCreateImageView(m_device.handle(),
Chia-I Wuf7458c52015-10-26 21:10:41 +0800973 &color_image_view, NULL, &m_buffers[i].view);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600974 assert(!err);
Tony Barbourbd094ce2015-10-23 11:00:15 -0600975
976 /* Set image layout to PRESENT_SOURCE_KHR so that before the copy, it can be set to */
977 /* TRANSFER_DESTINATION_OPTIMAL */
978 SetImageLayout(m_buffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT,
Ian Elliott1dcd1092015-11-17 17:29:40 -0700979 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
Tony Barbourbd094ce2015-10-23 11:00:15 -0600980
Tony Barbour6a3faf02015-07-23 10:36:18 -0600981 }
Tony Barbour96db8822015-02-25 12:28:39 -0700982}
Tony Barbourbd094ce2015-10-23 11:00:15 -0600983void TestFrameworkVkPresent::SetImageLayout(VkImage image, VkImageAspectFlags aspectMask,
984 VkImageLayout old_image_layout, VkImageLayout new_image_layout)
985{
986 VkResult U_ASSERT_ONLY err;
987
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800988 VkCommandBufferBeginInfo cmd_buf_info = {};
989 cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600990 cmd_buf_info.pNext = NULL;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800991 cmd_buf_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600992 cmd_buf_info.renderPass = { VK_NULL_HANDLE };
993 cmd_buf_info.subpass = 0;
994 cmd_buf_info.framebuffer = { VK_NULL_HANDLE };
Chia-I Wub8d47ae2015-11-11 10:18:12 +0800995 cmd_buf_info.occlusionQueryEnable = VK_FALSE;
996 cmd_buf_info.queryFlags = 0;
997 cmd_buf_info.pipelineStatistics = 0;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600998
999 err = vkBeginCommandBuffer(m_cmdbuf.handle(), &cmd_buf_info);
1000 assert(!err);
1001
1002 VkImageMemoryBarrier image_memory_barrier = {};
1003 image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
1004 image_memory_barrier.pNext = NULL;
Chia-I Wua4594202015-10-27 19:54:37 +08001005 image_memory_barrier.srcAccessMask = 0;
1006 image_memory_barrier.dstAccessMask = 0;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001007 image_memory_barrier.oldLayout = old_image_layout;
1008 image_memory_barrier.newLayout = new_image_layout;
1009 image_memory_barrier.image = image;
1010 image_memory_barrier.subresourceRange.aspectMask = aspectMask;
1011 image_memory_barrier.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001012 image_memory_barrier.subresourceRange.levelCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001013 image_memory_barrier.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001014 image_memory_barrier.subresourceRange.layerCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001015
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001016 if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
Tony Barbourbd094ce2015-10-23 11:00:15 -06001017 /* Make sure anything that was copying from this image has completed */
Chia-I Wua4594202015-10-27 19:54:37 +08001018 image_memory_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001019 }
1020
1021 if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
1022 /* Make sure any Copy or CPU writes to image are flushed */
Chia-I Wua4594202015-10-27 19:54:37 +08001023 image_memory_barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001024 }
1025
1026 VkImageMemoryBarrier *pmemory_barrier = &image_memory_barrier;
1027
1028 VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1029 VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1030
Chia-I Wu53534662015-10-26 17:08:33 +08001031 vkCmdPipelineBarrier(m_cmdbuf.handle(), src_stages, dest_stages, 0, 1, (const void * const*)&pmemory_barrier);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001032
1033 err = vkEndCommandBuffer(m_cmdbuf.handle());
1034 assert(!err);
1035
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001036 const VkCommandBuffer cmd_bufs[] = { m_cmdbuf.handle() };
Tony Barbourbd094ce2015-10-23 11:00:15 -06001037 VkFence nullFence = { VK_NULL_HANDLE };
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001038 VkSubmitInfo submit_info;
Chia-I Wuf9be13c2015-10-26 20:37:06 +08001039 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1040 submit_info.pNext = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001041 submit_info.waitSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001042 submit_info.pWaitSemaphores = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001043 submit_info.commandBufferCount = 1;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001044 submit_info.pCommandBuffers = cmd_bufs;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001045 submit_info.signalSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001046 submit_info.pSignalSemaphores = NULL;
1047
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -06001048 err = vkQueueSubmit(m_queue.handle(), 1, &submit_info, nullFence);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001049 assert(!err);
1050
1051 err = vkQueueWaitIdle(m_queue.handle());
1052 assert(!err);
1053
1054}
Tony Barbour96db8822015-02-25 12:28:39 -07001055
Jon Ashburn07daee72015-05-21 18:13:33 -06001056void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -07001057{
Ian Elliottc11750d2015-10-30 13:24:12 -06001058 m_instance = inst;
Ian Elliott7e40db92015-08-21 15:09:33 -06001059 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceSupportKHR);
Ian Elliottc11750d2015-10-30 13:24:12 -06001060 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceCapabilitiesKHR);
1061 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceFormatsKHR);
1062 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfacePresentModesKHR);
Ian Elliott7e40db92015-08-21 15:09:33 -06001063 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1064 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1065 GET_DEVICE_PROC_ADDR(m_device.handle(), DestroySwapchainKHR);
1066 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSwapchainImagesKHR);
1067 GET_DEVICE_PROC_ADDR(m_device.handle(), AcquireNextImageKHR);
1068 GET_DEVICE_PROC_ADDR(m_device.handle(), QueuePresentKHR);
Jon Ashburn07daee72015-05-21 18:13:33 -06001069
Tony Barbour96db8822015-02-25 12:28:39 -07001070 m_images = imagesIn;
1071}
1072
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001073#ifdef _WIN32
1074void TestFrameworkVkPresent::CreateMyWindow()
1075{
1076 WNDCLASSEX win_class;
1077 // const ::testing::TestInfo* const test_info =
1078 // ::testing::UnitTest::GetInstance()->current_test_info();
1079 m_connection = GetModuleHandle(NULL);
1080
1081 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1082 it != m_images.end(); it++) {
1083 if (m_width < it->m_width)
1084 m_width = it->m_width;
1085 if (m_height < it->m_height)
1086 m_height = it->m_height;
1087 }
1088 // Initialize the window class structure:
1089 win_class.cbSize = sizeof(WNDCLASSEX);
1090 win_class.style = CS_HREDRAW | CS_VREDRAW;
1091 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
1092 win_class.cbClsExtra = 0;
1093 win_class.cbWndExtra = 0;
1094 win_class.hInstance = m_connection; // hInstance
1095 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
1096 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
1097 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
1098 win_class.lpszMenuName = NULL;
1099 win_class.lpszClassName = "Test";
1100 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
1101 // Register window class:
1102 if (!RegisterClassEx(&win_class)) {
1103 // It didn't work, so try to give a useful error:
1104 printf("Unexpected error trying to start the application!\n");
1105 fflush(stdout);
1106 exit(1);
1107 }
1108 // Create window with the registered class:
Cody Northrop39582252015-08-05 15:39:31 -06001109 RECT wr = { 0, 0, m_width, m_height };
1110 AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001111 m_window = CreateWindowEx(0,
1112 "Test", // class name
1113 "Test", // app name
1114 WS_OVERLAPPEDWINDOW | // window style
1115 WS_VISIBLE |
1116 WS_SYSMENU,
1117 100,100, // x/y coords
Cody Northrop39582252015-08-05 15:39:31 -06001118 wr.right - wr.left, // width
1119 wr.bottom - wr.top, // height
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001120 NULL, // handle to parent
1121 NULL, // handle to menu
1122 m_connection, // hInstance
1123 NULL); // no extra parameters
1124
1125 if (!m_window) {
1126 // It didn't work, so try to give a useful error:
1127 DWORD error = GetLastError();
1128 char message[120];
1129 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
1130 MessageBox(NULL, message, "Error", MB_OK);
1131 exit(1);
1132 }
Tony-LunarG399dfca2015-05-19 14:08:26 -06001133 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
1134 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001135}
1136#else
Tony Barbour6918cd52015-04-09 12:58:51 -06001137void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -07001138{
Chia-I Wuf8693382015-04-16 22:02:10 +08001139 const xcb_setup_t *setup;
1140 xcb_screen_iterator_t iter;
1141 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -07001142 uint32_t value_mask, value_list[32];
1143
Chia-I Wuf8693382015-04-16 22:02:10 +08001144 m_connection = xcb_connect(NULL, &scr);
1145
1146 setup = xcb_get_setup(m_connection);
1147 iter = xcb_setup_roots_iterator(setup);
1148 while (scr-- > 0)
1149 xcb_screen_next(&iter);
1150
1151 m_screen = iter.data;
1152
1153 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1154 it != m_images.end(); it++) {
1155 if (m_width < it->m_width)
1156 m_width = it->m_width;
1157 if (m_height < it->m_height)
1158 m_height = it->m_height;
1159 }
1160
1161 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -07001162
1163 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +08001164 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -07001165 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
1166 XCB_EVENT_MASK_EXPOSURE |
1167 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
1168
Chia-I Wuf8693382015-04-16 22:02:10 +08001169 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -07001170 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001171 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -07001172 0, 0, m_width, m_height, 0,
1173 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001174 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -07001175 value_mask, value_list);
1176
1177 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +08001178 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -07001179 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +08001180 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001181
Chia-I Wuf8693382015-04-16 22:02:10 +08001182 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
1183 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001184
Chia-I Wuf8693382015-04-16 22:02:10 +08001185 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -07001186 m_window, (*reply).atom, 4, 32, 1,
1187 &(*m_atom_wm_delete_window).atom);
1188 free(reply);
1189
Chia-I Wuf8693382015-04-16 22:02:10 +08001190 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -07001191}
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001192#endif
Tony Barbour96db8822015-02-25 12:28:39 -07001193
Tony Barbour6918cd52015-04-09 12:58:51 -06001194void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -07001195{
Ian Elliottc11750d2015-10-30 13:24:12 -06001196 m_fpDestroySwapchainKHR(m_device.handle(), m_swap_chain, NULL);
Tony Barbour9226a822015-10-23 10:58:56 -06001197
1198 for (uint32_t i = 0; i < m_swapchainImageCount; i++) {
Chia-I Wuf7458c52015-10-26 21:10:41 +08001199 vkDestroyImageView(m_device.handle(), m_buffers[i].view, NULL);
Tony Barbour9226a822015-10-23 10:58:56 -06001200 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001201#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +08001202 xcb_destroy_window(m_connection, m_window);
1203 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001204#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001205}
1206
Tony Barbour6918cd52015-04-09 12:58:51 -06001207void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001208{
1209 if (m_images.size() == 0) return;
1210
Chia-I Wuf8693382015-04-16 22:02:10 +08001211 vk_testing::Environment env;
1212 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -07001213 {
Chia-I Wuf8693382015-04-16 22:02:10 +08001214 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -07001215
Jon Ashburn07daee72015-05-21 18:13:33 -06001216 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001217 vkPresent.CreateMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -06001218 vkPresent.CreateSwapchain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001219 vkPresent.Run();
1220 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -07001221 }
Chia-I Wuf8693382015-04-16 22:02:10 +08001222 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001223}
1224
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001225//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001226// These are the default resources for TBuiltInResources, used for both
1227// - parsing this string for the case where the user didn't supply one
1228// - dumping out a template for user construction of a config file
1229//
1230static const char* DefaultConfig =
1231 "MaxLights 32\n"
1232 "MaxClipPlanes 6\n"
1233 "MaxTextureUnits 32\n"
1234 "MaxTextureCoords 32\n"
1235 "MaxVertexAttribs 64\n"
1236 "MaxVertexUniformComponents 4096\n"
1237 "MaxVaryingFloats 64\n"
1238 "MaxVertexTextureImageUnits 32\n"
1239 "MaxCombinedTextureImageUnits 80\n"
1240 "MaxTextureImageUnits 32\n"
1241 "MaxFragmentUniformComponents 4096\n"
1242 "MaxDrawBuffers 32\n"
1243 "MaxVertexUniformVectors 128\n"
1244 "MaxVaryingVectors 8\n"
1245 "MaxFragmentUniformVectors 16\n"
1246 "MaxVertexOutputVectors 16\n"
1247 "MaxFragmentInputVectors 15\n"
1248 "MinProgramTexelOffset -8\n"
1249 "MaxProgramTexelOffset 7\n"
1250 "MaxClipDistances 8\n"
1251 "MaxComputeWorkGroupCountX 65535\n"
1252 "MaxComputeWorkGroupCountY 65535\n"
1253 "MaxComputeWorkGroupCountZ 65535\n"
1254 "MaxComputeWorkGroupSizeX 1024\n"
1255 "MaxComputeWorkGroupSizeY 1024\n"
1256 "MaxComputeWorkGroupSizeZ 64\n"
1257 "MaxComputeUniformComponents 1024\n"
1258 "MaxComputeTextureImageUnits 16\n"
1259 "MaxComputeImageUniforms 8\n"
1260 "MaxComputeAtomicCounters 8\n"
1261 "MaxComputeAtomicCounterBuffers 1\n"
1262 "MaxVaryingComponents 60\n"
1263 "MaxVertexOutputComponents 64\n"
1264 "MaxGeometryInputComponents 64\n"
1265 "MaxGeometryOutputComponents 128\n"
1266 "MaxFragmentInputComponents 128\n"
1267 "MaxImageUnits 8\n"
1268 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
1269 "MaxCombinedShaderOutputResources 8\n"
1270 "MaxImageSamples 0\n"
1271 "MaxVertexImageUniforms 0\n"
1272 "MaxTessControlImageUniforms 0\n"
1273 "MaxTessEvaluationImageUniforms 0\n"
1274 "MaxGeometryImageUniforms 0\n"
1275 "MaxFragmentImageUniforms 8\n"
1276 "MaxCombinedImageUniforms 8\n"
1277 "MaxGeometryTextureImageUnits 16\n"
1278 "MaxGeometryOutputVertices 256\n"
1279 "MaxGeometryTotalOutputComponents 1024\n"
1280 "MaxGeometryUniformComponents 1024\n"
1281 "MaxGeometryVaryingComponents 64\n"
1282 "MaxTessControlInputComponents 128\n"
1283 "MaxTessControlOutputComponents 128\n"
1284 "MaxTessControlTextureImageUnits 16\n"
1285 "MaxTessControlUniformComponents 1024\n"
1286 "MaxTessControlTotalOutputComponents 4096\n"
1287 "MaxTessEvaluationInputComponents 128\n"
1288 "MaxTessEvaluationOutputComponents 128\n"
1289 "MaxTessEvaluationTextureImageUnits 16\n"
1290 "MaxTessEvaluationUniformComponents 1024\n"
1291 "MaxTessPatchComponents 120\n"
1292 "MaxPatchVertices 32\n"
1293 "MaxTessGenLevel 64\n"
1294 "MaxViewports 16\n"
1295 "MaxVertexAtomicCounters 0\n"
1296 "MaxTessControlAtomicCounters 0\n"
1297 "MaxTessEvaluationAtomicCounters 0\n"
1298 "MaxGeometryAtomicCounters 0\n"
1299 "MaxFragmentAtomicCounters 8\n"
1300 "MaxCombinedAtomicCounters 8\n"
1301 "MaxAtomicCounterBindings 1\n"
1302 "MaxVertexAtomicCounterBuffers 0\n"
1303 "MaxTessControlAtomicCounterBuffers 0\n"
1304 "MaxTessEvaluationAtomicCounterBuffers 0\n"
1305 "MaxGeometryAtomicCounterBuffers 0\n"
1306 "MaxFragmentAtomicCounterBuffers 1\n"
1307 "MaxCombinedAtomicCounterBuffers 1\n"
1308 "MaxAtomicCounterBufferSize 16384\n"
1309 "MaxTransformFeedbackBuffers 4\n"
1310 "MaxTransformFeedbackInterleavedComponents 64\n"
1311 "MaxCullDistances 8\n"
1312 "MaxCombinedClipAndCullDistances 8\n"
1313 "MaxSamples 4\n"
1314
1315 "nonInductiveForLoops 1\n"
1316 "whileLoops 1\n"
1317 "doWhileLoops 1\n"
1318 "generalUniformIndexing 1\n"
1319 "generalAttributeMatrixVectorIndexing 1\n"
1320 "generalVaryingIndexing 1\n"
1321 "generalSamplerIndexing 1\n"
1322 "generalVariableIndexing 1\n"
1323 "generalConstantMatrixVectorIndexing 1\n"
1324 ;
1325
1326//
1327// *.conf => this is a config file that can set limits/resources
1328//
Tony Barbour6918cd52015-04-09 12:58:51 -06001329bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001330{
1331 if (name.size() < 5)
1332 return false;
1333
1334 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
1335 ConfigFile = name;
1336 return true;
1337 }
1338
1339 return false;
1340}
1341
1342//
1343// Parse either a .conf file provided by the user or the default string above.
1344//
Tony Barbour6918cd52015-04-09 12:58:51 -06001345void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001346{
1347 char** configStrings = 0;
1348 char* config = 0;
1349 if (ConfigFile.size() > 0) {
1350 configStrings = ReadFileData(ConfigFile.c_str());
1351 if (configStrings)
1352 config = *configStrings;
1353 else {
1354 printf("Error opening configuration file; will instead use the default configuration\n");
1355 }
1356 }
1357
1358 if (config == 0) {
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001359 config = (char *) alloca(strlen(DefaultConfig) + 1);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001360 strcpy(config, DefaultConfig);
1361 }
1362
1363 const char* delims = " \t\n\r";
1364 const char* token = strtok(config, delims);
1365 while (token) {
1366 const char* valueStr = strtok(0, delims);
1367 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1368 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1369 return;
1370 }
1371 int value = atoi(valueStr);
1372
1373 if (strcmp(token, "MaxLights") == 0)
1374 Resources.maxLights = value;
1375 else if (strcmp(token, "MaxClipPlanes") == 0)
1376 Resources.maxClipPlanes = value;
1377 else if (strcmp(token, "MaxTextureUnits") == 0)
1378 Resources.maxTextureUnits = value;
1379 else if (strcmp(token, "MaxTextureCoords") == 0)
1380 Resources.maxTextureCoords = value;
1381 else if (strcmp(token, "MaxVertexAttribs") == 0)
1382 Resources.maxVertexAttribs = value;
1383 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1384 Resources.maxVertexUniformComponents = value;
1385 else if (strcmp(token, "MaxVaryingFloats") == 0)
1386 Resources.maxVaryingFloats = value;
1387 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1388 Resources.maxVertexTextureImageUnits = value;
1389 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1390 Resources.maxCombinedTextureImageUnits = value;
1391 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1392 Resources.maxTextureImageUnits = value;
1393 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1394 Resources.maxFragmentUniformComponents = value;
1395 else if (strcmp(token, "MaxDrawBuffers") == 0)
1396 Resources.maxDrawBuffers = value;
1397 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1398 Resources.maxVertexUniformVectors = value;
1399 else if (strcmp(token, "MaxVaryingVectors") == 0)
1400 Resources.maxVaryingVectors = value;
1401 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1402 Resources.maxFragmentUniformVectors = value;
1403 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1404 Resources.maxVertexOutputVectors = value;
1405 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1406 Resources.maxFragmentInputVectors = value;
1407 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1408 Resources.minProgramTexelOffset = value;
1409 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1410 Resources.maxProgramTexelOffset = value;
1411 else if (strcmp(token, "MaxClipDistances") == 0)
1412 Resources.maxClipDistances = value;
1413 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1414 Resources.maxComputeWorkGroupCountX = value;
1415 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1416 Resources.maxComputeWorkGroupCountY = value;
1417 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1418 Resources.maxComputeWorkGroupCountZ = value;
1419 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1420 Resources.maxComputeWorkGroupSizeX = value;
1421 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1422 Resources.maxComputeWorkGroupSizeY = value;
1423 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1424 Resources.maxComputeWorkGroupSizeZ = value;
1425 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1426 Resources.maxComputeUniformComponents = value;
1427 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1428 Resources.maxComputeTextureImageUnits = value;
1429 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1430 Resources.maxComputeImageUniforms = value;
1431 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1432 Resources.maxComputeAtomicCounters = value;
1433 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1434 Resources.maxComputeAtomicCounterBuffers = value;
1435 else if (strcmp(token, "MaxVaryingComponents") == 0)
1436 Resources.maxVaryingComponents = value;
1437 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1438 Resources.maxVertexOutputComponents = value;
1439 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1440 Resources.maxGeometryInputComponents = value;
1441 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1442 Resources.maxGeometryOutputComponents = value;
1443 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1444 Resources.maxFragmentInputComponents = value;
1445 else if (strcmp(token, "MaxImageUnits") == 0)
1446 Resources.maxImageUnits = value;
1447 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1448 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1449 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1450 Resources.maxCombinedShaderOutputResources = value;
1451 else if (strcmp(token, "MaxImageSamples") == 0)
1452 Resources.maxImageSamples = value;
1453 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1454 Resources.maxVertexImageUniforms = value;
1455 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1456 Resources.maxTessControlImageUniforms = value;
1457 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1458 Resources.maxTessEvaluationImageUniforms = value;
1459 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1460 Resources.maxGeometryImageUniforms = value;
1461 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1462 Resources.maxFragmentImageUniforms = value;
1463 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1464 Resources.maxCombinedImageUniforms = value;
1465 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1466 Resources.maxGeometryTextureImageUnits = value;
1467 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1468 Resources.maxGeometryOutputVertices = value;
1469 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1470 Resources.maxGeometryTotalOutputComponents = value;
1471 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1472 Resources.maxGeometryUniformComponents = value;
1473 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1474 Resources.maxGeometryVaryingComponents = value;
1475 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1476 Resources.maxTessControlInputComponents = value;
1477 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1478 Resources.maxTessControlOutputComponents = value;
1479 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1480 Resources.maxTessControlTextureImageUnits = value;
1481 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1482 Resources.maxTessControlUniformComponents = value;
1483 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1484 Resources.maxTessControlTotalOutputComponents = value;
1485 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1486 Resources.maxTessEvaluationInputComponents = value;
1487 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1488 Resources.maxTessEvaluationOutputComponents = value;
1489 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1490 Resources.maxTessEvaluationTextureImageUnits = value;
1491 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1492 Resources.maxTessEvaluationUniformComponents = value;
1493 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1494 Resources.maxTessPatchComponents = value;
1495 else if (strcmp(token, "MaxPatchVertices") == 0)
1496 Resources.maxPatchVertices = value;
1497 else if (strcmp(token, "MaxTessGenLevel") == 0)
1498 Resources.maxTessGenLevel = value;
1499 else if (strcmp(token, "MaxViewports") == 0)
1500 Resources.maxViewports = value;
1501 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1502 Resources.maxVertexAtomicCounters = value;
1503 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1504 Resources.maxTessControlAtomicCounters = value;
1505 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1506 Resources.maxTessEvaluationAtomicCounters = value;
1507 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1508 Resources.maxGeometryAtomicCounters = value;
1509 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1510 Resources.maxFragmentAtomicCounters = value;
1511 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1512 Resources.maxCombinedAtomicCounters = value;
1513 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1514 Resources.maxAtomicCounterBindings = value;
1515 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1516 Resources.maxVertexAtomicCounterBuffers = value;
1517 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1518 Resources.maxTessControlAtomicCounterBuffers = value;
1519 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1520 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1521 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1522 Resources.maxGeometryAtomicCounterBuffers = value;
1523 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1524 Resources.maxFragmentAtomicCounterBuffers = value;
1525 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1526 Resources.maxCombinedAtomicCounterBuffers = value;
1527 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1528 Resources.maxAtomicCounterBufferSize = value;
1529 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1530 Resources.maxTransformFeedbackBuffers = value;
1531 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1532 Resources.maxTransformFeedbackInterleavedComponents = value;
1533 else if (strcmp(token, "MaxCullDistances") == 0)
1534 Resources.maxCullDistances = value;
1535 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1536 Resources.maxCombinedClipAndCullDistances = value;
1537 else if (strcmp(token, "MaxSamples") == 0)
1538 Resources.maxSamples = value;
1539
1540 else if (strcmp(token, "nonInductiveForLoops") == 0)
1541 Resources.limits.nonInductiveForLoops = (value != 0);
1542 else if (strcmp(token, "whileLoops") == 0)
1543 Resources.limits.whileLoops = (value != 0);
1544 else if (strcmp(token, "doWhileLoops") == 0)
1545 Resources.limits.doWhileLoops = (value != 0);
1546 else if (strcmp(token, "generalUniformIndexing") == 0)
1547 Resources.limits.generalUniformIndexing = (value != 0);
1548 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1549 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1550 else if (strcmp(token, "generalVaryingIndexing") == 0)
1551 Resources.limits.generalVaryingIndexing = (value != 0);
1552 else if (strcmp(token, "generalSamplerIndexing") == 0)
1553 Resources.limits.generalSamplerIndexing = (value != 0);
1554 else if (strcmp(token, "generalVariableIndexing") == 0)
1555 Resources.limits.generalVariableIndexing = (value != 0);
1556 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1557 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1558 else
1559 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1560
1561 token = strtok(0, delims);
1562 }
1563 if (configStrings)
1564 FreeFileData(configStrings);
1565}
1566
Tony Barbour6918cd52015-04-09 12:58:51 -06001567void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001568{
1569 if (m_compile_options & EOptionRelaxedErrors)
1570 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1571 if (m_compile_options & EOptionIntermediate)
1572 messages = (EShMessages)(messages | EShMsgAST);
1573 if (m_compile_options & EOptionSuppressWarnings)
1574 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1575}
1576
1577//
1578// Malloc a string of sufficient size and read a string into it.
1579//
Tony Barbour6918cd52015-04-09 12:58:51 -06001580char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001581{
1582 FILE *in;
1583 #if defined(_WIN32) && defined(__GNUC__)
1584 in = fopen(fileName, "r");
1585 int errorCode = in ? 0 : 1;
1586 #else
1587 int errorCode = fopen_s(&in, fileName, "r");
1588 #endif
1589
1590 char *fdata;
1591 int count = 0;
1592 const int maxSourceStrings = 5;
1593 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1594
1595 if (errorCode) {
1596 printf("Error: unable to open input file: %s\n", fileName);
1597 return 0;
1598 }
1599
1600 while (fgetc(in) != EOF)
1601 count++;
1602
1603 fseek(in, 0, SEEK_SET);
1604
1605 if (!(fdata = (char*)malloc(count+2))) {
1606 printf("Error allocating memory\n");
1607 return 0;
1608 }
1609 if (fread(fdata,1,count, in)!=count) {
1610 printf("Error reading input file: %s\n", fileName);
1611 return 0;
1612 }
1613 fdata[count] = '\0';
1614 fclose(in);
1615 if (count == 0) {
1616 return_data[0]=(char*)malloc(count+2);
1617 return_data[0][0]='\0';
1618 m_num_shader_strings = 0;
1619 return return_data;
1620 } else
1621 m_num_shader_strings = 1;
1622
1623 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1624 int ptr_len=0,i=0;
1625 while(count>0){
1626 return_data[i]=(char*)malloc(len+2);
1627 memcpy(return_data[i],fdata+ptr_len,len);
1628 return_data[i][len]='\0';
1629 count-=(len);
1630 ptr_len+=(len);
1631 if(count<len){
1632 if(count==0){
1633 m_num_shader_strings=(i+1);
1634 break;
1635 }
1636 len = count;
1637 }
1638 ++i;
1639 }
1640 return return_data;
1641}
1642
Tony Barbour6918cd52015-04-09 12:58:51 -06001643void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001644{
1645 for(int i=0;i<m_num_shader_strings;i++)
1646 free(data[i]);
1647}
1648
1649//
1650// Deduce the language from the filename. Files must end in one of the
1651// following extensions:
1652//
1653// .vert = vertex
1654// .tesc = tessellation control
1655// .tese = tessellation evaluation
1656// .geom = geometry
1657// .frag = fragment
1658// .comp = compute
1659//
Tony Barbour6918cd52015-04-09 12:58:51 -06001660EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001661{
1662 size_t ext = name.rfind('.');
1663 if (ext == std::string::npos) {
1664 return EShLangVertex;
1665 }
1666
1667 std::string suffix = name.substr(ext + 1, std::string::npos);
1668 if (suffix == "vert")
1669 return EShLangVertex;
1670 else if (suffix == "tesc")
1671 return EShLangTessControl;
1672 else if (suffix == "tese")
1673 return EShLangTessEvaluation;
1674 else if (suffix == "geom")
1675 return EShLangGeometry;
1676 else if (suffix == "frag")
1677 return EShLangFragment;
1678 else if (suffix == "comp")
1679 return EShLangCompute;
1680
1681 return EShLangVertex;
1682}
1683
1684//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001685// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001686//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001687EShLanguage VkTestFramework::FindLanguage(const VkShaderStageFlagBits shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001688{
1689 switch (shader_type) {
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001690 case VK_SHADER_STAGE_VERTEX_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001691 return EShLangVertex;
1692
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001693 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001694 return EShLangTessControl;
1695
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001696 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001697 return EShLangTessEvaluation;
1698
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001699 case VK_SHADER_STAGE_GEOMETRY_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001700 return EShLangGeometry;
1701
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001702 case VK_SHADER_STAGE_FRAGMENT_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001703 return EShLangFragment;
1704
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001705 case VK_SHADER_STAGE_COMPUTE_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001706 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001707
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001708 default:
1709 return EShLangVertex;
1710 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001711}
1712
1713
1714//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001715// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001716// Return value of false means an error was encountered.
1717//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001718bool VkTestFramework::GLSLtoSPV(const VkShaderStageFlagBits shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001719 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001720 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001721{
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001722 glslang::TProgram program;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001723 const char *shaderStrings[1];
1724
1725 // TODO: Do we want to load a special config file depending on the
1726 // shader source? Optional name maybe?
1727 // SetConfigFile(fileName);
1728
1729 ProcessConfigFile();
1730
1731 EShMessages messages = EShMsgDefault;
1732 SetMessageOptions(messages);
1733
1734 EShLanguage stage = FindLanguage(shader_type);
1735 glslang::TShader* shader = new glslang::TShader(stage);
1736
1737 shaderStrings[0] = pshader;
1738 shader->setStrings(shaderStrings, 1);
1739
1740 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1741
Cody Northrop195d6622014-11-03 12:54:37 -07001742 if (! (m_compile_options & EOptionSuppressInfolog)) {
1743 puts(shader->getInfoLog());
1744 puts(shader->getInfoDebugLog());
1745 }
1746
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001747 return false; // something didn't work
1748 }
1749
1750 program.addShader(shader);
1751
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001752
1753 //
1754 // Program-level processing...
1755 //
1756
Cody Northrop195d6622014-11-03 12:54:37 -07001757 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001758
Cody Northrop195d6622014-11-03 12:54:37 -07001759 if (! (m_compile_options & EOptionSuppressInfolog)) {
1760 puts(shader->getInfoLog());
1761 puts(shader->getInfoDebugLog());
1762 }
1763
1764 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001765 }
1766
1767 if (m_compile_options & EOptionDumpReflection) {
1768 program.buildReflection();
1769 program.dumpReflection();
1770 }
1771
Cody Northrop5a95b472015-06-03 13:01:54 -06001772 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1773
1774 //
1775 // Test the different modes of SPIR-V modification
1776 //
1777 if (this->m_canonicalize_spv) {
1778 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1779 }
1780
1781 if (this->m_strip_spv) {
1782 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1783 }
1784
1785 if (this->m_do_everything_spv) {
1786 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1787 }
1788
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001789 delete shader;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001790
1791 return true;
1792}
1793
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001794
1795
Tony Barbour6918cd52015-04-09 12:58:51 -06001796VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001797 m_width( 0 ),
1798 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001799 m_data( NULL ),
1800 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001801{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001802}
1803
Tony Barbour6918cd52015-04-09 12:58:51 -06001804VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001805{
1806
1807}
1808
Tony Barbour6918cd52015-04-09 12:58:51 -06001809VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001810{
1811 m_title = copyin.m_title;
1812 m_width = copyin.m_width;
1813 m_height = copyin.m_height;
1814 m_data_size = copyin.m_data_size;
1815 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1816}
1817
Tony Barbour6918cd52015-04-09 12:58:51 -06001818ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001819{
Tony Barbour6918cd52015-04-09 12:58:51 -06001820 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1821 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001822 return output;
1823}
1824
Tony Barbour6918cd52015-04-09 12:58:51 -06001825VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001826{
1827 m_title = rhs.m_title;
1828 m_width = rhs.m_width;
1829 m_height = rhs.m_height;
1830 m_data_size = rhs.m_data_size;
1831 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001832 return *this;
1833}
1834
Tony Barbour6918cd52015-04-09 12:58:51 -06001835int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001836{
1837 if( this->m_data != rhs.m_data) return 0;
1838 return 1;
1839}
1840
1841// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001842int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001843{
1844 if( this->m_data_size < rhs.m_data_size ) return 1;
1845 return 0;
1846}
1847