blob: 3793f3493b5d40c6b3599f1b46c17c1601d2bc7d [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>
Tony Barbourfeb61962015-09-21 15:17:33 -060033#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +080034#include <xcb/xcb.h>
Tony Barbourfeb61962015-09-21 15:17:33 -060035#endif
Ian Elliott1dcd1092015-11-17 17:29:40 -070036#include "vulkan/VK_KHR_surface.h"
37#include "vulkan/VK_KHR_swapchain.h"
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060038
Tony Barbour3d69c9e2015-05-20 16:53:31 -060039#if defined(PATH_MAX) && !defined(MAX_PATH)
40#define MAX_PATH PATH_MAX
41#endif
42
Tony Barbour6a3faf02015-07-23 10:36:18 -060043#ifdef _WIN32
44#define ERR_EXIT(err_msg, err_class) \
45 do { \
46 MessageBox(NULL, err_msg, err_class, MB_OK); \
47 exit(1); \
48 } while (0)
49#else // _WIN32
50
51#define ERR_EXIT(err_msg, err_class) \
52 do { \
53 printf(err_msg); \
54 fflush(stdout); \
55 exit(1); \
56 } while (0)
57#endif // _WIN32
58
59#define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \
60{ \
61 m_fp##entrypoint = (PFN_vk##entrypoint) vkGetInstanceProcAddr(inst, "vk"#entrypoint); \
62 if (m_fp##entrypoint == NULL) { \
63 ERR_EXIT("vkGetInstanceProcAddr failed to find vk"#entrypoint, \
64 "vkGetInstanceProcAddr Failure"); \
65 } \
66}
67
68#define GET_DEVICE_PROC_ADDR(dev, entrypoint) \
69{ \
70 m_fp##entrypoint = (PFN_vk##entrypoint) vkGetDeviceProcAddr(dev, "vk"#entrypoint); \
71 if (m_fp##entrypoint == NULL) { \
72 ERR_EXIT("vkGetDeviceProcAddr failed to find vk"#entrypoint, \
73 "vkGetDeviceProcAddr Failure"); \
74 } \
75}
76
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060077// Command-line options
78enum TOptions {
79 EOptionNone = 0x000,
80 EOptionIntermediate = 0x001,
81 EOptionSuppressInfolog = 0x002,
82 EOptionMemoryLeakMode = 0x004,
83 EOptionRelaxedErrors = 0x008,
84 EOptionGiveWarnings = 0x010,
85 EOptionLinkProgram = 0x020,
86 EOptionMultiThreaded = 0x040,
87 EOptionDumpConfig = 0x080,
88 EOptionDumpReflection = 0x100,
89 EOptionSuppressWarnings = 0x200,
90 EOptionDumpVersions = 0x400,
Cody Northrop3bfd27c2015-03-17 15:55:58 -060091 EOptionSpv = 0x800,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060092 EOptionDefaultDesktop = 0x1000,
93};
94
Ian Elliott7e40db92015-08-21 15:09:33 -060095typedef struct _SwapchainBuffers {
Tony Barbour6a3faf02015-07-23 10:36:18 -060096 VkImage image;
Chia-I Wu3432a0c2015-10-27 18:04:07 +080097 VkCommandBuffer cmd;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -060098 VkImageView view;
Ian Elliott7e40db92015-08-21 15:09:33 -060099} SwapchainBuffers;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600100
Chia-I Wuf8693382015-04-16 22:02:10 +0800101class TestFrameworkVkPresent
102{
103public:
104 TestFrameworkVkPresent(vk_testing::Device &device);
105
106 void Run();
Jon Ashburn07daee72015-05-21 18:13:33 -0600107 void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst);
Chia-I Wuf8693382015-04-16 22:02:10 +0800108 void CreateMyWindow();
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:
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;
Ian Elliott7e40db92015-08-21 15:09:33 -0600134 VkPlatformHandleXcbKHR m_platform_handle_xcb;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600135#endif
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 Elliott1dcd1092015-11-17 17:29:40 -0700140 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;
148 VkSurfaceDescriptionWindowKHR m_surface_description;
149 uint32_t m_swapchainImageCount;
150 VkSwapchainKHR m_swap_chain;
151 SwapchainBuffers *m_buffers;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600152 VkFormat m_format;
Ian Elliott7e40db92015-08-21 15:09:33 -0600153 VkColorSpaceKHR m_color_space;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600154
155 uint32_t m_current_buffer;
Chia-I Wuf8693382015-04-16 22:02:10 +0800156
157 bool m_quit;
158 bool m_pause;
159
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600160 int m_width;
161 int m_height;
Chia-I Wuf8693382015-04-16 22:02:10 +0800162
163 std::list<VkTestImageRecord>::iterator m_display_image;
164
165 void Display();
Tony Barbourfeb61962015-09-21 15:17:33 -0600166#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800167 void HandleEvent(xcb_generic_event_t *event);
Tony Barbourfeb61962015-09-21 15:17:33 -0600168#endif
Chia-I Wuf8693382015-04-16 22:02:10 +0800169};
170
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600171#ifndef _WIN32
172
173#include <errno.h>
174
175int fopen_s(
176 FILE** pFile,
177 const char* filename,
178 const char* mode
179)
180{
181 if (!pFile || !filename || !mode) {
182 return EINVAL;
183 }
184
185 FILE* f = fopen(filename, mode);
186 if (! f) {
187 if (errno != 0) {
188 return errno;
189 } else {
190 return ENOENT;
191 }
192 }
193 *pFile = f;
194
195 return 0;
196}
197
198#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600199
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600200
201
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600202// Set up environment for GLSL compiler
203// Must be done once per process
204void TestEnvironment::SetUp()
205{
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600206 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600207 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800208
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600209 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600210}
211
212void TestEnvironment::TearDown()
213{
214 glslang::FinalizeProcess();
215}
216
Tony Barbour6918cd52015-04-09 12:58:51 -0600217VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600218 m_compile_options( 0 ),
219 m_num_shader_strings( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600220{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600221
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600222}
223
Tony Barbour6918cd52015-04-09 12:58:51 -0600224VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600225{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600226
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600227}
228
229// Define all the static elements
Cody Northropa3673cf2015-06-09 13:00:45 -0600230bool VkTestFramework::m_show_images = false;
231bool VkTestFramework::m_save_images = false;
232bool VkTestFramework::m_compare_images = false;
233bool VkTestFramework::m_use_glsl = false;
234bool VkTestFramework::m_canonicalize_spv = false;
235bool VkTestFramework::m_strip_spv = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600236bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour6918cd52015-04-09 12:58:51 -0600237int VkTestFramework::m_width = 0;
238int VkTestFramework::m_height = 0;
239std::list<VkTestImageRecord> VkTestFramework::m_images;
240std::list<VkTestImageRecord>::iterator VkTestFramework::m_display_image;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600241int m_display_image_idx = 0;
242
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600243bool VkTestFramework::optionMatch(const char* option, char* optionLine)
244{
245 if (strncmp(option, optionLine, strlen(option)) == 0)
246 return true;
247 else
248 return false;
249}
250
Tony Barbour6918cd52015-04-09 12:58:51 -0600251void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600252{
253 int i, n;
254
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600255 for (i=1, n=1; i< *argc; i++) {
256 if (optionMatch("--show-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600257 m_show_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600258 else if (optionMatch("--save-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600259 m_save_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600260 else if (optionMatch("--no-SPV", argv[i]))
261 m_use_glsl = true;
262 else if (optionMatch("--strip-SPV", argv[i]))
263 m_strip_spv = true;
264 else if (optionMatch("--canonicalize-SPV", argv[i]))
265 m_canonicalize_spv = true;
266 else if (optionMatch("--compare-images", argv[i]))
Tony Barbour247bf372014-10-30 14:29:04 -0600267 m_compare_images = true;
Tony Barbour247bf372014-10-30 14:29:04 -0600268
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600269 else if (optionMatch("--help", argv[i]) ||
270 optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700271 printf("\nOther options:\n");
272 printf("\t--show-images\n"
273 "\t\tDisplay test images in viewer after tests complete.\n");
274 printf("\t--save-images\n"
275 "\t\tSave tests images as ppm files in current working directory.\n"
276 "\t\tUsed to generate golden images for compare-images.\n");
277 printf("\t--compare-images\n"
278 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barboura98d3932014-12-11 09:52:49 -0700279 "\t\tAlso saves the generated test image in current working\n"
280 "\t\t\tdirectory but only if the image is different from the golden\n"
281 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
282 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700283 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600284 printf("\t--no-SPV\n"
285 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600286 printf("\t--strip-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600287 "\t\tStrip SPIR-V debug information (line numbers, names, etc).\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600288 printf("\t--canonicalize-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600289 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600290 exit(0);
291 } else {
292 printf("\nUnrecognized option: %s\n", argv[i]);
293 printf("\nUse --help or -h for option list.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700294 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700295 }
296
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600297 /*
298 * Since the above "consume" inputs, update argv
299 * so that it contains the trimmed list of args for glutInit
300 */
301
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600302 argv[n] = argv[i];
303 n++;
304 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600305}
306
Tony Barbour6918cd52015-04-09 12:58:51 -0600307void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600308{
309 string filename;
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600310 uint32_t x, y;
Tony Barbour6918cd52015-04-09 12:58:51 -0600311 VkImageObj displayImage(image->device());
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600312 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbour84d448c2015-04-02 14:02:33 -0600313
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800314 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 -0600315 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600316
317 filename.append(basename);
318 filename.append(".ppm");
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600319
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600320 const VkImageSubresource sr = {
Courtney Goeltzenleuchter908e7672015-10-21 17:00:51 -0600321 VK_IMAGE_ASPECT_COLOR_BIT, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600322 };
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600323 VkSubresourceLayout sr_layout;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600324
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600325 vkGetImageSubresourceLayout(image->device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600326
Tony Barbour84d448c2015-04-02 14:02:33 -0600327 char *ptr;
Chia-I Wu681d7a02015-07-03 13:44:34 +0800328 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600329 ptr += sr_layout.offset;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600330 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600331 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
332
333 file << "P6\n";
Tony Barbourfeb61962015-09-21 15:17:33 -0600334 file << displayImage.width() << " ";
Tony Barbour84d448c2015-04-02 14:02:33 -0600335 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600336 file << 255 << "\n";
337
Tony Barbour84d448c2015-04-02 14:02:33 -0600338 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700339 const int *row = (const int *) ptr;
340 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600341
Tony Barbourd1c35722015-04-16 15:59:00 -0600342 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700343 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600344 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700345 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
346 file.write((char *) &swapped, 3);
347 row++;
348 }
349 }
Tony Barbourd1c35722015-04-16 15:59:00 -0600350 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700351 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600352 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700353 file.write((char *) row, 3);
354 row++;
355 }
356 }
357 else {
358 printf("Unrecognized image format - will not write image files");
359 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600360 }
361
362 ptr += sr_layout.rowPitch;
363 }
364
365 file.close();
Chia-I Wu681d7a02015-07-03 13:44:34 +0800366 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600367}
368
Tony Barbour6918cd52015-04-09 12:58:51 -0600369void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour247bf372014-10-30 14:29:04 -0600370{
371
372 MagickWand *magick_wand_1;
373 MagickWand *magick_wand_2;
374 MagickWand *compare_wand;
375 MagickBooleanType status;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600376 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600377 double differenz;
378
Tony Barbour4ab45422014-12-10 17:00:20 -0700379 if (getenv("RENDERTEST_GOLDEN_DIR"))
380 {
381 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
382 }
383
Tony Barbour247bf372014-10-30 14:29:04 -0600384 MagickWandGenesis();
385 magick_wand_1=NewMagickWand();
386 sprintf(testimage,"%s.ppm",basename);
387 status=MagickReadImage(magick_wand_1,testimage);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600388 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour247bf372014-10-30 14:29:04 -0600389
390
391 MagickWandGenesis();
392 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700393 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600394 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600395 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour247bf372014-10-30 14:29:04 -0600396
Tony Barbour247bf372014-10-30 14:29:04 -0600397 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
398 if (differenz != 0.0)
399 {
400 char difference[256];
401
402 sprintf(difference,"%s-diff.ppm",basename);
403 status = MagickWriteImage(compare_wand, difference);
404 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
405 }
406 DestroyMagickWand(compare_wand);
407
408 DestroyMagickWand(magick_wand_1);
409 DestroyMagickWand(magick_wand_2);
410 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700411
412 if (differenz == 0.0)
413 {
414 /*
415 * If test image and golden image match, we do not need to
416 * keep around the test image.
417 */
418 remove(testimage);
419 }
Tony Barbour247bf372014-10-30 14:29:04 -0600420}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600421
Tony Barbour6918cd52015-04-09 12:58:51 -0600422void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600423{
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600424 VkSubresourceLayout sr_layout;
425 char *ptr;
426 VkTestImageRecord record;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600427 VkImageObj displayImage(image->device());
428 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
429
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800430 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 -0600431
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600432 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600433
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600434 const VkImageSubresource sr = {
Courtney Goeltzenleuchter908e7672015-10-21 17:00:51 -0600435 VK_IMAGE_ASPECT_COLOR_BIT, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600436 };
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600437
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600438 vkGetImageSubresourceLayout(displayImage.device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600439
Chia-I Wu681d7a02015-07-03 13:44:34 +0800440 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600441 ptr += sr_layout.offset;
442
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600443 record.m_title.append(comment);
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600444 record.m_width = displayImage.width();
445 record.m_height = displayImage.height();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600446 // TODO: Need to make this more robust to handle different image formats
Tony-LunarG399dfca2015-05-19 14:08:26 -0600447 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600448 record.m_data = malloc(record.m_data_size);
449 memcpy(record.m_data, ptr, record.m_data_size);
450 m_images.push_back(record);
451 m_display_image = --m_images.end();
452
Chia-I Wu681d7a02015-07-03 13:44:34 +0800453 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600454}
455
Tony Barbour6918cd52015-04-09 12:58:51 -0600456void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600457{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600458 for (int32_t i = 0; i < images.size(); i++) {
459 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600460 }
461}
462
Tony Barbour6918cd52015-04-09 12:58:51 -0600463void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600464{
465 const ::testing::TestInfo* const test_info =
466 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600467 ostringstream filestream;
468 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600469
Tony Barbour247bf372014-10-30 14:29:04 -0600470 m_width = 40;
471
472 if (strcmp(test_info->name(), m_testName.c_str())) {
473 filestream << test_info->name();
474 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700475 m_frameNum = 2;
476 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600477 }
478 else {
479 filestream << test_info->name() << "-" << m_frameNum;
480 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700481 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600482 }
483
Tony Barbour247bf372014-10-30 14:29:04 -0600484 // ToDo - scrub string for bad characters
485
486 if (m_save_images || m_compare_images) {
487 WritePPM(filename.c_str(), image);
488 if (m_compare_images) {
489 Compare(filename.c_str(), image);
490 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600491 }
492
493 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600494 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600495 }
496}
497
Chia-I Wuf8693382015-04-16 22:02:10 +0800498TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
499 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700500 m_queue(*m_device.graphics_queues()[0]),
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800501 m_cmdpool(m_device, vk_testing::CommandPool::create_info(m_device.graphics_queue_node_index_)),
502 m_cmdbuf(m_device, vk_testing::CommandBuffer::create_info(m_cmdpool.handle()))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600503{
Tony Barbour96db8822015-02-25 12:28:39 -0700504 m_quit = false;
505 m_pause = false;
506 m_width = 0;
507 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600508}
509
Tony Barbour6918cd52015-04-09 12:58:51 -0600510void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600511{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600512 VkResult U_ASSERT_ONLY err;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600513 vk_testing::Buffer buf;
514 void *dest_ptr;
515
Tony Barbour6a3faf02015-07-23 10:36:18 -0600516 VkSemaphore presentCompleteSemaphore;
517 VkSemaphoreCreateInfo presentCompleteSemaphoreCreateInfo = {};
518 presentCompleteSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
519 presentCompleteSemaphoreCreateInfo.pNext = NULL;
520 presentCompleteSemaphoreCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
521
522
523 err = vkCreateSemaphore(m_device.handle(),
524 &presentCompleteSemaphoreCreateInfo,
Chia-I Wuf7458c52015-10-26 21:10:41 +0800525 NULL, &presentCompleteSemaphore);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600526 assert(!err);
527
528 // Get the index of the next available swapchain image:
Ian Elliott7e40db92015-08-21 15:09:33 -0600529 err = m_fpAcquireNextImageKHR(m_device.handle(), m_swap_chain,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600530 UINT64_MAX,
531 presentCompleteSemaphore,
532 &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;
610 present.swapchains = & m_swap_chain;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600611 present.imageIndices = &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
Tony Barbour6a3faf02015-07-23 10:36:18 -0600787 // Construct the WSI surface description:
Ian Elliott7e40db92015-08-21 15:09:33 -0600788 m_surface_description.sType = VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600789 m_surface_description.pNext = NULL;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600790#ifdef _WIN32
Ian Elliott7e40db92015-08-21 15:09:33 -0600791 m_surface_description.platform = VK_PLATFORM_WIN32_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600792 m_surface_description.pPlatformHandle = m_connection;
793 m_surface_description.pPlatformWindow = m_window;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600794#else // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -0600795 m_platform_handle_xcb.connection = m_connection;
796 m_platform_handle_xcb.root = m_screen->root;
Ian Elliott7e40db92015-08-21 15:09:33 -0600797 m_surface_description.platform = VK_PLATFORM_XCB_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600798 m_surface_description.pPlatformHandle = &m_platform_handle_xcb;
799 m_surface_description.pPlatformWindow = &m_window;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600800#endif // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -0600801
802 // Iterate over each queue to learn whether it supports presenting to WSI:
803 VkBool32 supportsPresent;
804 m_present_queue_node_index = UINT32_MAX;
805 std::vector<vk_testing::Queue *> queues = m_device.graphics_queues();
806 for (int i=0; i < queues.size(); i++)
807 {
808 int family_index = queues[i]->get_family_index();
Ian Elliott7e40db92015-08-21 15:09:33 -0600809 m_fpGetPhysicalDeviceSurfaceSupportKHR(m_device.phy().handle(),
Tony Barbour6a3faf02015-07-23 10:36:18 -0600810 family_index,
Ian Elliott7e40db92015-08-21 15:09:33 -0600811 (VkSurfaceDescriptionKHR *) &m_surface_description,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600812 &supportsPresent);
813 if (supportsPresent) {
814 m_present_queue_node_index = family_index;
815 }
816 }
817
818 assert(m_present_queue_node_index != UINT32_MAX);
819
820
821 // Get the list of VkFormat's that are supported:
Ian Elliott8b139792015-08-07 11:51:12 -0600822 uint32_t formatCount;
Ian Elliott1dcd1092015-11-17 17:29:40 -0700823 err = m_fpGetPhysicalDeviceSurfaceFormatsKHR(m_device.handle(),
Ian Elliott7e40db92015-08-21 15:09:33 -0600824 (VkSurfaceDescriptionKHR *) &m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600825 &formatCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600826 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600827 VkSurfaceFormatKHR *surfFormats =
828 (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
Ian Elliott1dcd1092015-11-17 17:29:40 -0700829 err = m_fpGetPhysicalDeviceSurfaceFormatsKHR(m_device.handle(),
Ian Elliott7e40db92015-08-21 15:09:33 -0600830 (VkSurfaceDescriptionKHR *) &m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600831 &formatCount, surfFormats);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600832 assert(!err);
833 // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
834 // the surface has no preferred format. Otherwise, at least one
835 // supported format will be returned.
Tony Barbour6a3faf02015-07-23 10:36:18 -0600836 if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED)
837 {
838 m_format = VK_FORMAT_B8G8R8A8_UNORM;
839 }
840 else
841 {
842 assert(formatCount >= 1);
843 m_format = surfFormats[0].format;
844 }
Ian Elliott8b139792015-08-07 11:51:12 -0600845 m_color_space = surfFormats[0].colorSpace;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600846
847 // Check the surface proprties and formats
Ian Elliott1dcd1092015-11-17 17:29:40 -0700848 VkSurfaceCapabilitiesKHR surfProperties;
849 err = m_fpGetPhysicalDeviceSurfaceCapabilitiesKHR(m_device.handle(),
Ian Elliott7e40db92015-08-21 15:09:33 -0600850 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600851 &surfProperties);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600852 assert(!err);
853
Ian Elliott8b139792015-08-07 11:51:12 -0600854 uint32_t presentModeCount;
Ian Elliott1dcd1092015-11-17 17:29:40 -0700855 err = m_fpGetPhysicalDeviceSurfacePresentModesKHR(m_device.handle(),
Ian Elliott7e40db92015-08-21 15:09:33 -0600856 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600857 &presentModeCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600858 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600859 VkPresentModeKHR *presentModes =
860 (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
Ian Elliott8b139792015-08-07 11:51:12 -0600861 assert(presentModes);
Ian Elliott1dcd1092015-11-17 17:29:40 -0700862 err = m_fpGetPhysicalDeviceSurfacePresentModesKHR(m_device.handle(),
Ian Elliott7e40db92015-08-21 15:09:33 -0600863 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600864 &presentModeCount, presentModes);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600865 assert(!err);
866
Ian Elliott7e40db92015-08-21 15:09:33 -0600867 VkExtent2D swapchainExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600868 // width and height are either both -1, or both not -1.
Ian Elliott8b139792015-08-07 11:51:12 -0600869 if (surfProperties.currentExtent.width == -1)
Tony Barbour6a3faf02015-07-23 10:36:18 -0600870 {
871 // If the surface size is undefined, the size is set to
872 // the size of the images requested.
Ian Elliott7e40db92015-08-21 15:09:33 -0600873 swapchainExtent.width = m_width;
874 swapchainExtent.height = m_height;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600875 }
876 else
877 {
878 // If the surface size is defined, the swap chain size must match
Ian Elliott7e40db92015-08-21 15:09:33 -0600879 swapchainExtent = surfProperties.currentExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600880 }
881
882 // If mailbox mode is available, use it, as is the lowest-latency non-
Ian Elliottae0e8242015-08-10 13:20:49 -0600883 // tearing mode. If not, try IMMEDIATE which will usually be available,
884 // and is fastest (though it tears). If not, fall back to FIFO which is
885 // always available.
Ian Elliott7e40db92015-08-21 15:09:33 -0600886 VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600887 for (size_t i = 0; i < presentModeCount; i++) {
Ian Elliott7e40db92015-08-21 15:09:33 -0600888 if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
889 swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600890 break;
891 }
Ian Elliott7e40db92015-08-21 15:09:33 -0600892 if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) &&
893 (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
894 swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
Ian Elliottae0e8242015-08-10 13:20:49 -0600895 }
Tony Barbour6a3faf02015-07-23 10:36:18 -0600896 }
897
898 // Determine the number of VkImage's to use in the swap chain (we desire to
899 // own only 1 image at a time, besides the images being displayed and
900 // queued for display):
Ian Elliott7e40db92015-08-21 15:09:33 -0600901 uint32_t desiredNumberOfSwapchainImages = surfProperties.minImageCount + 1;
Ian Elliott8b139792015-08-07 11:51:12 -0600902 if ((surfProperties.maxImageCount > 0) &&
Ian Elliott7e40db92015-08-21 15:09:33 -0600903 (desiredNumberOfSwapchainImages > surfProperties.maxImageCount))
Tony Barbour6a3faf02015-07-23 10:36:18 -0600904 {
905 // Application must settle for fewer images than desired:
Ian Elliott7e40db92015-08-21 15:09:33 -0600906 desiredNumberOfSwapchainImages = surfProperties.maxImageCount;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600907 }
908
Ian Elliott7e40db92015-08-21 15:09:33 -0600909 VkSurfaceTransformKHR preTransform;
910 if (surfProperties.supportedTransforms & VK_SURFACE_TRANSFORM_NONE_BIT_KHR) {
911 preTransform = VK_SURFACE_TRANSFORM_NONE_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600912 } else {
Ian Elliott8b139792015-08-07 11:51:12 -0600913 preTransform = surfProperties.currentTransform;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600914 }
Ian Elliott1a3845b2015-07-06 14:33:04 -0600915
Cody Northropdf5b0922015-08-28 16:22:48 -0600916 // We want to blit to the swap chain, ensure the driver supports it. Color is always supported, per WSI spec.
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800917 assert((surfProperties.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) != 0);
Cody Northropdf5b0922015-08-28 16:22:48 -0600918
Ian Elliott7e40db92015-08-21 15:09:33 -0600919 VkSwapchainCreateInfoKHR swap_chain = {};
Ian Elliotta257eea2015-09-22 10:20:23 -0600920 swap_chain.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600921 swap_chain.pNext = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600922 swap_chain.pSurfaceDescription = (const VkSurfaceDescriptionKHR *)&m_surface_description;
923 swap_chain.minImageCount = desiredNumberOfSwapchainImages;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600924 swap_chain.imageFormat = m_format;
Ian Elliott8b139792015-08-07 11:51:12 -0600925 swap_chain.imageColorSpace = m_color_space;
Ian Elliott7e40db92015-08-21 15:09:33 -0600926 swap_chain.imageExtent.width = swapchainExtent.width;
927 swap_chain.imageExtent.height = swapchainExtent.height;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800928 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DST_BIT |
Cody Northropdf8f42a2015-08-05 15:38:39 -0600929 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600930 swap_chain.preTransform = preTransform;
Chia-I Wuf8693382015-04-16 22:02:10 +0800931 swap_chain.imageArraySize = 1;
Ian Elliott8b139792015-08-07 11:51:12 -0600932 swap_chain.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
933 swap_chain.queueFamilyCount = 0;
934 swap_chain.pQueueFamilyIndices = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600935 swap_chain.presentMode = swapchainPresentMode;
Chia-I Wue2fc5522015-10-26 20:04:44 +0800936 swap_chain.oldSwapchain = VK_NULL_HANDLE;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600937 swap_chain.clipped = true;
938
939 uint32_t i;
Chia-I Wuf8693382015-04-16 22:02:10 +0800940
Ian Elliott7e40db92015-08-21 15:09:33 -0600941 err = m_fpCreateSwapchainKHR(m_device.handle(), &swap_chain, &m_swap_chain);
Chia-I Wuf8693382015-04-16 22:02:10 +0800942 assert(!err);
943
Ian Elliott7e40db92015-08-21 15:09:33 -0600944 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
945 &m_swapchainImageCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600946 assert(!err);
947
Ian Elliott7e40db92015-08-21 15:09:33 -0600948 VkImage* swapchainImages = (VkImage*)malloc(m_swapchainImageCount * sizeof(VkImage));
949 assert(swapchainImages);
950 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
951 &m_swapchainImageCount, swapchainImages);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600952 assert(!err);
953
Ian Elliott7e40db92015-08-21 15:09:33 -0600954 m_buffers = (SwapchainBuffers*)malloc(sizeof(SwapchainBuffers)*m_swapchainImageCount);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600955 assert(m_buffers);
956
Ian Elliott7e40db92015-08-21 15:09:33 -0600957 for (i = 0; i < m_swapchainImageCount; i++) {
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600958 VkImageViewCreateInfo color_image_view = {};
959 color_image_view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
960 color_image_view.pNext = NULL;
961 color_image_view.format = m_format;
Tony Barbourd800bbd2015-11-05 10:54:44 -0700962 color_image_view.components.r = VK_COMPONENT_SWIZZLE_R;
963 color_image_view.components.g = VK_COMPONENT_SWIZZLE_G;
964 color_image_view.components.b = VK_COMPONENT_SWIZZLE_B;
965 color_image_view.components.a = VK_COMPONENT_SWIZZLE_A;
Courtney Goeltzenleuchterba724512015-09-10 17:58:54 -0600966 color_image_view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600967 color_image_view.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800968 color_image_view.subresourceRange.levelCount = 1;
Courtney Goeltzenleuchter4a261892015-09-10 16:38:41 -0600969 color_image_view.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800970 color_image_view.subresourceRange.layerCount = 1;
Tony Barbourd800bbd2015-11-05 10:54:44 -0700971 color_image_view.viewType = VK_IMAGE_VIEW_TYPE_2D;
972 color_image_view.flags = 0;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600973
Ian Elliott7e40db92015-08-21 15:09:33 -0600974 m_buffers[i].image = swapchainImages[i];
Tony Barbour6a3faf02015-07-23 10:36:18 -0600975
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600976 color_image_view.image = m_buffers[i].image;
977 err = vkCreateImageView(m_device.handle(),
Chia-I Wuf7458c52015-10-26 21:10:41 +0800978 &color_image_view, NULL, &m_buffers[i].view);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600979 assert(!err);
Tony Barbourbd094ce2015-10-23 11:00:15 -0600980
981 /* Set image layout to PRESENT_SOURCE_KHR so that before the copy, it can be set to */
982 /* TRANSFER_DESTINATION_OPTIMAL */
983 SetImageLayout(m_buffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT,
Ian Elliott1dcd1092015-11-17 17:29:40 -0700984 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
Tony Barbourbd094ce2015-10-23 11:00:15 -0600985
Tony Barbour6a3faf02015-07-23 10:36:18 -0600986 }
Tony Barbour96db8822015-02-25 12:28:39 -0700987}
Tony Barbourbd094ce2015-10-23 11:00:15 -0600988void TestFrameworkVkPresent::SetImageLayout(VkImage image, VkImageAspectFlags aspectMask,
989 VkImageLayout old_image_layout, VkImageLayout new_image_layout)
990{
991 VkResult U_ASSERT_ONLY err;
992
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800993 VkCommandBufferBeginInfo cmd_buf_info = {};
994 cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600995 cmd_buf_info.pNext = NULL;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800996 cmd_buf_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600997 cmd_buf_info.renderPass = { VK_NULL_HANDLE };
998 cmd_buf_info.subpass = 0;
999 cmd_buf_info.framebuffer = { VK_NULL_HANDLE };
Chia-I Wub8d47ae2015-11-11 10:18:12 +08001000 cmd_buf_info.occlusionQueryEnable = VK_FALSE;
1001 cmd_buf_info.queryFlags = 0;
1002 cmd_buf_info.pipelineStatistics = 0;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001003
1004 err = vkBeginCommandBuffer(m_cmdbuf.handle(), &cmd_buf_info);
1005 assert(!err);
1006
1007 VkImageMemoryBarrier image_memory_barrier = {};
1008 image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
1009 image_memory_barrier.pNext = NULL;
Chia-I Wua4594202015-10-27 19:54:37 +08001010 image_memory_barrier.srcAccessMask = 0;
1011 image_memory_barrier.dstAccessMask = 0;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001012 image_memory_barrier.oldLayout = old_image_layout;
1013 image_memory_barrier.newLayout = new_image_layout;
1014 image_memory_barrier.image = image;
1015 image_memory_barrier.subresourceRange.aspectMask = aspectMask;
1016 image_memory_barrier.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001017 image_memory_barrier.subresourceRange.levelCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001018 image_memory_barrier.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001019 image_memory_barrier.subresourceRange.layerCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001020
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001021 if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
Tony Barbourbd094ce2015-10-23 11:00:15 -06001022 /* Make sure anything that was copying from this image has completed */
Chia-I Wua4594202015-10-27 19:54:37 +08001023 image_memory_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001024 }
1025
1026 if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
1027 /* Make sure any Copy or CPU writes to image are flushed */
Chia-I Wua4594202015-10-27 19:54:37 +08001028 image_memory_barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001029 }
1030
1031 VkImageMemoryBarrier *pmemory_barrier = &image_memory_barrier;
1032
1033 VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1034 VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1035
Chia-I Wu53534662015-10-26 17:08:33 +08001036 vkCmdPipelineBarrier(m_cmdbuf.handle(), src_stages, dest_stages, 0, 1, (const void * const*)&pmemory_barrier);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001037
1038 err = vkEndCommandBuffer(m_cmdbuf.handle());
1039 assert(!err);
1040
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001041 const VkCommandBuffer cmd_bufs[] = { m_cmdbuf.handle() };
Tony Barbourbd094ce2015-10-23 11:00:15 -06001042 VkFence nullFence = { VK_NULL_HANDLE };
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001043 VkSubmitInfo submit_info;
Chia-I Wuf9be13c2015-10-26 20:37:06 +08001044 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1045 submit_info.pNext = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001046 submit_info.waitSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001047 submit_info.pWaitSemaphores = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001048 submit_info.commandBufferCount = 1;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001049 submit_info.pCommandBuffers = cmd_bufs;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001050 submit_info.signalSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001051 submit_info.pSignalSemaphores = NULL;
1052
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -06001053 err = vkQueueSubmit(m_queue.handle(), 1, &submit_info, nullFence);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001054 assert(!err);
1055
1056 err = vkQueueWaitIdle(m_queue.handle());
1057 assert(!err);
1058
1059}
Tony Barbour96db8822015-02-25 12:28:39 -07001060
Jon Ashburn07daee72015-05-21 18:13:33 -06001061void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -07001062{
Ian Elliott7e40db92015-08-21 15:09:33 -06001063 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceSupportKHR);
Ian Elliott1dcd1092015-11-17 17:29:40 -07001064 GET_DEVICE_PROC_ADDR(m_device.handle(), GetPhysicalDeviceSurfaceCapabilitiesKHR);
1065 GET_DEVICE_PROC_ADDR(m_device.handle(), GetPhysicalDeviceSurfaceFormatsKHR);
1066 GET_DEVICE_PROC_ADDR(m_device.handle(), GetPhysicalDeviceSurfacePresentModesKHR);
Ian Elliott7e40db92015-08-21 15:09:33 -06001067 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1068 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1069 GET_DEVICE_PROC_ADDR(m_device.handle(), DestroySwapchainKHR);
1070 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSwapchainImagesKHR);
1071 GET_DEVICE_PROC_ADDR(m_device.handle(), AcquireNextImageKHR);
1072 GET_DEVICE_PROC_ADDR(m_device.handle(), QueuePresentKHR);
Jon Ashburn07daee72015-05-21 18:13:33 -06001073
Tony Barbour96db8822015-02-25 12:28:39 -07001074 m_images = imagesIn;
1075}
1076
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001077#ifdef _WIN32
1078void TestFrameworkVkPresent::CreateMyWindow()
1079{
1080 WNDCLASSEX win_class;
1081 // const ::testing::TestInfo* const test_info =
1082 // ::testing::UnitTest::GetInstance()->current_test_info();
1083 m_connection = GetModuleHandle(NULL);
1084
1085 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1086 it != m_images.end(); it++) {
1087 if (m_width < it->m_width)
1088 m_width = it->m_width;
1089 if (m_height < it->m_height)
1090 m_height = it->m_height;
1091 }
1092 // Initialize the window class structure:
1093 win_class.cbSize = sizeof(WNDCLASSEX);
1094 win_class.style = CS_HREDRAW | CS_VREDRAW;
1095 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
1096 win_class.cbClsExtra = 0;
1097 win_class.cbWndExtra = 0;
1098 win_class.hInstance = m_connection; // hInstance
1099 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
1100 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
1101 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
1102 win_class.lpszMenuName = NULL;
1103 win_class.lpszClassName = "Test";
1104 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
1105 // Register window class:
1106 if (!RegisterClassEx(&win_class)) {
1107 // It didn't work, so try to give a useful error:
1108 printf("Unexpected error trying to start the application!\n");
1109 fflush(stdout);
1110 exit(1);
1111 }
1112 // Create window with the registered class:
Cody Northrop39582252015-08-05 15:39:31 -06001113 RECT wr = { 0, 0, m_width, m_height };
1114 AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001115 m_window = CreateWindowEx(0,
1116 "Test", // class name
1117 "Test", // app name
1118 WS_OVERLAPPEDWINDOW | // window style
1119 WS_VISIBLE |
1120 WS_SYSMENU,
1121 100,100, // x/y coords
Cody Northrop39582252015-08-05 15:39:31 -06001122 wr.right - wr.left, // width
1123 wr.bottom - wr.top, // height
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001124 NULL, // handle to parent
1125 NULL, // handle to menu
1126 m_connection, // hInstance
1127 NULL); // no extra parameters
1128
1129 if (!m_window) {
1130 // It didn't work, so try to give a useful error:
1131 DWORD error = GetLastError();
1132 char message[120];
1133 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
1134 MessageBox(NULL, message, "Error", MB_OK);
1135 exit(1);
1136 }
Tony-LunarG399dfca2015-05-19 14:08:26 -06001137 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
1138 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001139}
1140#else
Tony Barbour6918cd52015-04-09 12:58:51 -06001141void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -07001142{
Chia-I Wuf8693382015-04-16 22:02:10 +08001143 const xcb_setup_t *setup;
1144 xcb_screen_iterator_t iter;
1145 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -07001146 uint32_t value_mask, value_list[32];
1147
Chia-I Wuf8693382015-04-16 22:02:10 +08001148 m_connection = xcb_connect(NULL, &scr);
1149
1150 setup = xcb_get_setup(m_connection);
1151 iter = xcb_setup_roots_iterator(setup);
1152 while (scr-- > 0)
1153 xcb_screen_next(&iter);
1154
1155 m_screen = iter.data;
1156
1157 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1158 it != m_images.end(); it++) {
1159 if (m_width < it->m_width)
1160 m_width = it->m_width;
1161 if (m_height < it->m_height)
1162 m_height = it->m_height;
1163 }
1164
1165 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -07001166
1167 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +08001168 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -07001169 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
1170 XCB_EVENT_MASK_EXPOSURE |
1171 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
1172
Chia-I Wuf8693382015-04-16 22:02:10 +08001173 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -07001174 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001175 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -07001176 0, 0, m_width, m_height, 0,
1177 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001178 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -07001179 value_mask, value_list);
1180
1181 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +08001182 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -07001183 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +08001184 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001185
Chia-I Wuf8693382015-04-16 22:02:10 +08001186 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
1187 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001188
Chia-I Wuf8693382015-04-16 22:02:10 +08001189 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -07001190 m_window, (*reply).atom, 4, 32, 1,
1191 &(*m_atom_wm_delete_window).atom);
1192 free(reply);
1193
Chia-I Wuf8693382015-04-16 22:02:10 +08001194 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -07001195}
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001196#endif
Tony Barbour96db8822015-02-25 12:28:39 -07001197
Tony Barbour6918cd52015-04-09 12:58:51 -06001198void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -07001199{
Ian Elliott7e40db92015-08-21 15:09:33 -06001200 m_fpDestroySwapchainKHR(m_device.handle(), m_swap_chain);
Tony Barbour9226a822015-10-23 10:58:56 -06001201
1202 for (uint32_t i = 0; i < m_swapchainImageCount; i++) {
Chia-I Wuf7458c52015-10-26 21:10:41 +08001203 vkDestroyImageView(m_device.handle(), m_buffers[i].view, NULL);
Tony Barbour9226a822015-10-23 10:58:56 -06001204 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001205#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +08001206 xcb_destroy_window(m_connection, m_window);
1207 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001208#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001209}
1210
Tony Barbour6918cd52015-04-09 12:58:51 -06001211void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001212{
1213 if (m_images.size() == 0) return;
1214
Chia-I Wuf8693382015-04-16 22:02:10 +08001215 vk_testing::Environment env;
1216 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -07001217 {
Chia-I Wuf8693382015-04-16 22:02:10 +08001218 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -07001219
Jon Ashburn07daee72015-05-21 18:13:33 -06001220 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001221 vkPresent.CreateMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -06001222 vkPresent.CreateSwapchain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001223 vkPresent.Run();
1224 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -07001225 }
Chia-I Wuf8693382015-04-16 22:02:10 +08001226 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001227}
1228
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001229//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001230// These are the default resources for TBuiltInResources, used for both
1231// - parsing this string for the case where the user didn't supply one
1232// - dumping out a template for user construction of a config file
1233//
1234static const char* DefaultConfig =
1235 "MaxLights 32\n"
1236 "MaxClipPlanes 6\n"
1237 "MaxTextureUnits 32\n"
1238 "MaxTextureCoords 32\n"
1239 "MaxVertexAttribs 64\n"
1240 "MaxVertexUniformComponents 4096\n"
1241 "MaxVaryingFloats 64\n"
1242 "MaxVertexTextureImageUnits 32\n"
1243 "MaxCombinedTextureImageUnits 80\n"
1244 "MaxTextureImageUnits 32\n"
1245 "MaxFragmentUniformComponents 4096\n"
1246 "MaxDrawBuffers 32\n"
1247 "MaxVertexUniformVectors 128\n"
1248 "MaxVaryingVectors 8\n"
1249 "MaxFragmentUniformVectors 16\n"
1250 "MaxVertexOutputVectors 16\n"
1251 "MaxFragmentInputVectors 15\n"
1252 "MinProgramTexelOffset -8\n"
1253 "MaxProgramTexelOffset 7\n"
1254 "MaxClipDistances 8\n"
1255 "MaxComputeWorkGroupCountX 65535\n"
1256 "MaxComputeWorkGroupCountY 65535\n"
1257 "MaxComputeWorkGroupCountZ 65535\n"
1258 "MaxComputeWorkGroupSizeX 1024\n"
1259 "MaxComputeWorkGroupSizeY 1024\n"
1260 "MaxComputeWorkGroupSizeZ 64\n"
1261 "MaxComputeUniformComponents 1024\n"
1262 "MaxComputeTextureImageUnits 16\n"
1263 "MaxComputeImageUniforms 8\n"
1264 "MaxComputeAtomicCounters 8\n"
1265 "MaxComputeAtomicCounterBuffers 1\n"
1266 "MaxVaryingComponents 60\n"
1267 "MaxVertexOutputComponents 64\n"
1268 "MaxGeometryInputComponents 64\n"
1269 "MaxGeometryOutputComponents 128\n"
1270 "MaxFragmentInputComponents 128\n"
1271 "MaxImageUnits 8\n"
1272 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
1273 "MaxCombinedShaderOutputResources 8\n"
1274 "MaxImageSamples 0\n"
1275 "MaxVertexImageUniforms 0\n"
1276 "MaxTessControlImageUniforms 0\n"
1277 "MaxTessEvaluationImageUniforms 0\n"
1278 "MaxGeometryImageUniforms 0\n"
1279 "MaxFragmentImageUniforms 8\n"
1280 "MaxCombinedImageUniforms 8\n"
1281 "MaxGeometryTextureImageUnits 16\n"
1282 "MaxGeometryOutputVertices 256\n"
1283 "MaxGeometryTotalOutputComponents 1024\n"
1284 "MaxGeometryUniformComponents 1024\n"
1285 "MaxGeometryVaryingComponents 64\n"
1286 "MaxTessControlInputComponents 128\n"
1287 "MaxTessControlOutputComponents 128\n"
1288 "MaxTessControlTextureImageUnits 16\n"
1289 "MaxTessControlUniformComponents 1024\n"
1290 "MaxTessControlTotalOutputComponents 4096\n"
1291 "MaxTessEvaluationInputComponents 128\n"
1292 "MaxTessEvaluationOutputComponents 128\n"
1293 "MaxTessEvaluationTextureImageUnits 16\n"
1294 "MaxTessEvaluationUniformComponents 1024\n"
1295 "MaxTessPatchComponents 120\n"
1296 "MaxPatchVertices 32\n"
1297 "MaxTessGenLevel 64\n"
1298 "MaxViewports 16\n"
1299 "MaxVertexAtomicCounters 0\n"
1300 "MaxTessControlAtomicCounters 0\n"
1301 "MaxTessEvaluationAtomicCounters 0\n"
1302 "MaxGeometryAtomicCounters 0\n"
1303 "MaxFragmentAtomicCounters 8\n"
1304 "MaxCombinedAtomicCounters 8\n"
1305 "MaxAtomicCounterBindings 1\n"
1306 "MaxVertexAtomicCounterBuffers 0\n"
1307 "MaxTessControlAtomicCounterBuffers 0\n"
1308 "MaxTessEvaluationAtomicCounterBuffers 0\n"
1309 "MaxGeometryAtomicCounterBuffers 0\n"
1310 "MaxFragmentAtomicCounterBuffers 1\n"
1311 "MaxCombinedAtomicCounterBuffers 1\n"
1312 "MaxAtomicCounterBufferSize 16384\n"
1313 "MaxTransformFeedbackBuffers 4\n"
1314 "MaxTransformFeedbackInterleavedComponents 64\n"
1315 "MaxCullDistances 8\n"
1316 "MaxCombinedClipAndCullDistances 8\n"
1317 "MaxSamples 4\n"
1318
1319 "nonInductiveForLoops 1\n"
1320 "whileLoops 1\n"
1321 "doWhileLoops 1\n"
1322 "generalUniformIndexing 1\n"
1323 "generalAttributeMatrixVectorIndexing 1\n"
1324 "generalVaryingIndexing 1\n"
1325 "generalSamplerIndexing 1\n"
1326 "generalVariableIndexing 1\n"
1327 "generalConstantMatrixVectorIndexing 1\n"
1328 ;
1329
1330//
1331// *.conf => this is a config file that can set limits/resources
1332//
Tony Barbour6918cd52015-04-09 12:58:51 -06001333bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001334{
1335 if (name.size() < 5)
1336 return false;
1337
1338 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
1339 ConfigFile = name;
1340 return true;
1341 }
1342
1343 return false;
1344}
1345
1346//
1347// Parse either a .conf file provided by the user or the default string above.
1348//
Tony Barbour6918cd52015-04-09 12:58:51 -06001349void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001350{
1351 char** configStrings = 0;
1352 char* config = 0;
1353 if (ConfigFile.size() > 0) {
1354 configStrings = ReadFileData(ConfigFile.c_str());
1355 if (configStrings)
1356 config = *configStrings;
1357 else {
1358 printf("Error opening configuration file; will instead use the default configuration\n");
1359 }
1360 }
1361
1362 if (config == 0) {
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001363 config = (char *) alloca(strlen(DefaultConfig) + 1);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001364 strcpy(config, DefaultConfig);
1365 }
1366
1367 const char* delims = " \t\n\r";
1368 const char* token = strtok(config, delims);
1369 while (token) {
1370 const char* valueStr = strtok(0, delims);
1371 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1372 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1373 return;
1374 }
1375 int value = atoi(valueStr);
1376
1377 if (strcmp(token, "MaxLights") == 0)
1378 Resources.maxLights = value;
1379 else if (strcmp(token, "MaxClipPlanes") == 0)
1380 Resources.maxClipPlanes = value;
1381 else if (strcmp(token, "MaxTextureUnits") == 0)
1382 Resources.maxTextureUnits = value;
1383 else if (strcmp(token, "MaxTextureCoords") == 0)
1384 Resources.maxTextureCoords = value;
1385 else if (strcmp(token, "MaxVertexAttribs") == 0)
1386 Resources.maxVertexAttribs = value;
1387 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1388 Resources.maxVertexUniformComponents = value;
1389 else if (strcmp(token, "MaxVaryingFloats") == 0)
1390 Resources.maxVaryingFloats = value;
1391 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1392 Resources.maxVertexTextureImageUnits = value;
1393 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1394 Resources.maxCombinedTextureImageUnits = value;
1395 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1396 Resources.maxTextureImageUnits = value;
1397 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1398 Resources.maxFragmentUniformComponents = value;
1399 else if (strcmp(token, "MaxDrawBuffers") == 0)
1400 Resources.maxDrawBuffers = value;
1401 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1402 Resources.maxVertexUniformVectors = value;
1403 else if (strcmp(token, "MaxVaryingVectors") == 0)
1404 Resources.maxVaryingVectors = value;
1405 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1406 Resources.maxFragmentUniformVectors = value;
1407 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1408 Resources.maxVertexOutputVectors = value;
1409 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1410 Resources.maxFragmentInputVectors = value;
1411 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1412 Resources.minProgramTexelOffset = value;
1413 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1414 Resources.maxProgramTexelOffset = value;
1415 else if (strcmp(token, "MaxClipDistances") == 0)
1416 Resources.maxClipDistances = value;
1417 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1418 Resources.maxComputeWorkGroupCountX = value;
1419 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1420 Resources.maxComputeWorkGroupCountY = value;
1421 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1422 Resources.maxComputeWorkGroupCountZ = value;
1423 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1424 Resources.maxComputeWorkGroupSizeX = value;
1425 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1426 Resources.maxComputeWorkGroupSizeY = value;
1427 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1428 Resources.maxComputeWorkGroupSizeZ = value;
1429 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1430 Resources.maxComputeUniformComponents = value;
1431 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1432 Resources.maxComputeTextureImageUnits = value;
1433 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1434 Resources.maxComputeImageUniforms = value;
1435 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1436 Resources.maxComputeAtomicCounters = value;
1437 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1438 Resources.maxComputeAtomicCounterBuffers = value;
1439 else if (strcmp(token, "MaxVaryingComponents") == 0)
1440 Resources.maxVaryingComponents = value;
1441 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1442 Resources.maxVertexOutputComponents = value;
1443 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1444 Resources.maxGeometryInputComponents = value;
1445 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1446 Resources.maxGeometryOutputComponents = value;
1447 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1448 Resources.maxFragmentInputComponents = value;
1449 else if (strcmp(token, "MaxImageUnits") == 0)
1450 Resources.maxImageUnits = value;
1451 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1452 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1453 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1454 Resources.maxCombinedShaderOutputResources = value;
1455 else if (strcmp(token, "MaxImageSamples") == 0)
1456 Resources.maxImageSamples = value;
1457 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1458 Resources.maxVertexImageUniforms = value;
1459 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1460 Resources.maxTessControlImageUniforms = value;
1461 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1462 Resources.maxTessEvaluationImageUniforms = value;
1463 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1464 Resources.maxGeometryImageUniforms = value;
1465 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1466 Resources.maxFragmentImageUniforms = value;
1467 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1468 Resources.maxCombinedImageUniforms = value;
1469 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1470 Resources.maxGeometryTextureImageUnits = value;
1471 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1472 Resources.maxGeometryOutputVertices = value;
1473 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1474 Resources.maxGeometryTotalOutputComponents = value;
1475 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1476 Resources.maxGeometryUniformComponents = value;
1477 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1478 Resources.maxGeometryVaryingComponents = value;
1479 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1480 Resources.maxTessControlInputComponents = value;
1481 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1482 Resources.maxTessControlOutputComponents = value;
1483 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1484 Resources.maxTessControlTextureImageUnits = value;
1485 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1486 Resources.maxTessControlUniformComponents = value;
1487 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1488 Resources.maxTessControlTotalOutputComponents = value;
1489 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1490 Resources.maxTessEvaluationInputComponents = value;
1491 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1492 Resources.maxTessEvaluationOutputComponents = value;
1493 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1494 Resources.maxTessEvaluationTextureImageUnits = value;
1495 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1496 Resources.maxTessEvaluationUniformComponents = value;
1497 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1498 Resources.maxTessPatchComponents = value;
1499 else if (strcmp(token, "MaxPatchVertices") == 0)
1500 Resources.maxPatchVertices = value;
1501 else if (strcmp(token, "MaxTessGenLevel") == 0)
1502 Resources.maxTessGenLevel = value;
1503 else if (strcmp(token, "MaxViewports") == 0)
1504 Resources.maxViewports = value;
1505 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1506 Resources.maxVertexAtomicCounters = value;
1507 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1508 Resources.maxTessControlAtomicCounters = value;
1509 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1510 Resources.maxTessEvaluationAtomicCounters = value;
1511 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1512 Resources.maxGeometryAtomicCounters = value;
1513 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1514 Resources.maxFragmentAtomicCounters = value;
1515 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1516 Resources.maxCombinedAtomicCounters = value;
1517 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1518 Resources.maxAtomicCounterBindings = value;
1519 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1520 Resources.maxVertexAtomicCounterBuffers = value;
1521 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1522 Resources.maxTessControlAtomicCounterBuffers = value;
1523 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1524 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1525 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1526 Resources.maxGeometryAtomicCounterBuffers = value;
1527 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1528 Resources.maxFragmentAtomicCounterBuffers = value;
1529 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1530 Resources.maxCombinedAtomicCounterBuffers = value;
1531 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1532 Resources.maxAtomicCounterBufferSize = value;
1533 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1534 Resources.maxTransformFeedbackBuffers = value;
1535 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1536 Resources.maxTransformFeedbackInterleavedComponents = value;
1537 else if (strcmp(token, "MaxCullDistances") == 0)
1538 Resources.maxCullDistances = value;
1539 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1540 Resources.maxCombinedClipAndCullDistances = value;
1541 else if (strcmp(token, "MaxSamples") == 0)
1542 Resources.maxSamples = value;
1543
1544 else if (strcmp(token, "nonInductiveForLoops") == 0)
1545 Resources.limits.nonInductiveForLoops = (value != 0);
1546 else if (strcmp(token, "whileLoops") == 0)
1547 Resources.limits.whileLoops = (value != 0);
1548 else if (strcmp(token, "doWhileLoops") == 0)
1549 Resources.limits.doWhileLoops = (value != 0);
1550 else if (strcmp(token, "generalUniformIndexing") == 0)
1551 Resources.limits.generalUniformIndexing = (value != 0);
1552 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1553 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1554 else if (strcmp(token, "generalVaryingIndexing") == 0)
1555 Resources.limits.generalVaryingIndexing = (value != 0);
1556 else if (strcmp(token, "generalSamplerIndexing") == 0)
1557 Resources.limits.generalSamplerIndexing = (value != 0);
1558 else if (strcmp(token, "generalVariableIndexing") == 0)
1559 Resources.limits.generalVariableIndexing = (value != 0);
1560 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1561 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1562 else
1563 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1564
1565 token = strtok(0, delims);
1566 }
1567 if (configStrings)
1568 FreeFileData(configStrings);
1569}
1570
Tony Barbour6918cd52015-04-09 12:58:51 -06001571void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001572{
1573 if (m_compile_options & EOptionRelaxedErrors)
1574 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1575 if (m_compile_options & EOptionIntermediate)
1576 messages = (EShMessages)(messages | EShMsgAST);
1577 if (m_compile_options & EOptionSuppressWarnings)
1578 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1579}
1580
1581//
1582// Malloc a string of sufficient size and read a string into it.
1583//
Tony Barbour6918cd52015-04-09 12:58:51 -06001584char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001585{
1586 FILE *in;
1587 #if defined(_WIN32) && defined(__GNUC__)
1588 in = fopen(fileName, "r");
1589 int errorCode = in ? 0 : 1;
1590 #else
1591 int errorCode = fopen_s(&in, fileName, "r");
1592 #endif
1593
1594 char *fdata;
1595 int count = 0;
1596 const int maxSourceStrings = 5;
1597 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1598
1599 if (errorCode) {
1600 printf("Error: unable to open input file: %s\n", fileName);
1601 return 0;
1602 }
1603
1604 while (fgetc(in) != EOF)
1605 count++;
1606
1607 fseek(in, 0, SEEK_SET);
1608
1609 if (!(fdata = (char*)malloc(count+2))) {
1610 printf("Error allocating memory\n");
1611 return 0;
1612 }
1613 if (fread(fdata,1,count, in)!=count) {
1614 printf("Error reading input file: %s\n", fileName);
1615 return 0;
1616 }
1617 fdata[count] = '\0';
1618 fclose(in);
1619 if (count == 0) {
1620 return_data[0]=(char*)malloc(count+2);
1621 return_data[0][0]='\0';
1622 m_num_shader_strings = 0;
1623 return return_data;
1624 } else
1625 m_num_shader_strings = 1;
1626
1627 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1628 int ptr_len=0,i=0;
1629 while(count>0){
1630 return_data[i]=(char*)malloc(len+2);
1631 memcpy(return_data[i],fdata+ptr_len,len);
1632 return_data[i][len]='\0';
1633 count-=(len);
1634 ptr_len+=(len);
1635 if(count<len){
1636 if(count==0){
1637 m_num_shader_strings=(i+1);
1638 break;
1639 }
1640 len = count;
1641 }
1642 ++i;
1643 }
1644 return return_data;
1645}
1646
Tony Barbour6918cd52015-04-09 12:58:51 -06001647void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001648{
1649 for(int i=0;i<m_num_shader_strings;i++)
1650 free(data[i]);
1651}
1652
1653//
1654// Deduce the language from the filename. Files must end in one of the
1655// following extensions:
1656//
1657// .vert = vertex
1658// .tesc = tessellation control
1659// .tese = tessellation evaluation
1660// .geom = geometry
1661// .frag = fragment
1662// .comp = compute
1663//
Tony Barbour6918cd52015-04-09 12:58:51 -06001664EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001665{
1666 size_t ext = name.rfind('.');
1667 if (ext == std::string::npos) {
1668 return EShLangVertex;
1669 }
1670
1671 std::string suffix = name.substr(ext + 1, std::string::npos);
1672 if (suffix == "vert")
1673 return EShLangVertex;
1674 else if (suffix == "tesc")
1675 return EShLangTessControl;
1676 else if (suffix == "tese")
1677 return EShLangTessEvaluation;
1678 else if (suffix == "geom")
1679 return EShLangGeometry;
1680 else if (suffix == "frag")
1681 return EShLangFragment;
1682 else if (suffix == "comp")
1683 return EShLangCompute;
1684
1685 return EShLangVertex;
1686}
1687
1688//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001689// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001690//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001691EShLanguage VkTestFramework::FindLanguage(const VkShaderStageFlagBits shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001692{
1693 switch (shader_type) {
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001694 case VK_SHADER_STAGE_VERTEX_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001695 return EShLangVertex;
1696
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001697 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001698 return EShLangTessControl;
1699
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001700 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001701 return EShLangTessEvaluation;
1702
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001703 case VK_SHADER_STAGE_GEOMETRY_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001704 return EShLangGeometry;
1705
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001706 case VK_SHADER_STAGE_FRAGMENT_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001707 return EShLangFragment;
1708
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001709 case VK_SHADER_STAGE_COMPUTE_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001710 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001711
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001712 default:
1713 return EShLangVertex;
1714 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001715}
1716
1717
1718//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001719// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001720// Return value of false means an error was encountered.
1721//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001722bool VkTestFramework::GLSLtoSPV(const VkShaderStageFlagBits shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001723 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001724 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001725{
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001726 glslang::TProgram program;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001727 const char *shaderStrings[1];
1728
1729 // TODO: Do we want to load a special config file depending on the
1730 // shader source? Optional name maybe?
1731 // SetConfigFile(fileName);
1732
1733 ProcessConfigFile();
1734
1735 EShMessages messages = EShMsgDefault;
1736 SetMessageOptions(messages);
1737
1738 EShLanguage stage = FindLanguage(shader_type);
1739 glslang::TShader* shader = new glslang::TShader(stage);
1740
1741 shaderStrings[0] = pshader;
1742 shader->setStrings(shaderStrings, 1);
1743
1744 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1745
Cody Northrop195d6622014-11-03 12:54:37 -07001746 if (! (m_compile_options & EOptionSuppressInfolog)) {
1747 puts(shader->getInfoLog());
1748 puts(shader->getInfoDebugLog());
1749 }
1750
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001751 return false; // something didn't work
1752 }
1753
1754 program.addShader(shader);
1755
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001756
1757 //
1758 // Program-level processing...
1759 //
1760
Cody Northrop195d6622014-11-03 12:54:37 -07001761 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001762
Cody Northrop195d6622014-11-03 12:54:37 -07001763 if (! (m_compile_options & EOptionSuppressInfolog)) {
1764 puts(shader->getInfoLog());
1765 puts(shader->getInfoDebugLog());
1766 }
1767
1768 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001769 }
1770
1771 if (m_compile_options & EOptionDumpReflection) {
1772 program.buildReflection();
1773 program.dumpReflection();
1774 }
1775
Cody Northrop5a95b472015-06-03 13:01:54 -06001776 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1777
1778 //
1779 // Test the different modes of SPIR-V modification
1780 //
1781 if (this->m_canonicalize_spv) {
1782 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1783 }
1784
1785 if (this->m_strip_spv) {
1786 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1787 }
1788
1789 if (this->m_do_everything_spv) {
1790 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1791 }
1792
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001793 delete shader;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001794
1795 return true;
1796}
1797
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001798
1799
Tony Barbour6918cd52015-04-09 12:58:51 -06001800VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001801 m_width( 0 ),
1802 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001803 m_data( NULL ),
1804 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001805{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001806}
1807
Tony Barbour6918cd52015-04-09 12:58:51 -06001808VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001809{
1810
1811}
1812
Tony Barbour6918cd52015-04-09 12:58:51 -06001813VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001814{
1815 m_title = copyin.m_title;
1816 m_width = copyin.m_width;
1817 m_height = copyin.m_height;
1818 m_data_size = copyin.m_data_size;
1819 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1820}
1821
Tony Barbour6918cd52015-04-09 12:58:51 -06001822ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001823{
Tony Barbour6918cd52015-04-09 12:58:51 -06001824 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1825 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001826 return output;
1827}
1828
Tony Barbour6918cd52015-04-09 12:58:51 -06001829VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001830{
1831 m_title = rhs.m_title;
1832 m_width = rhs.m_width;
1833 m_height = rhs.m_height;
1834 m_data_size = rhs.m_data_size;
1835 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001836 return *this;
1837}
1838
Tony Barbour6918cd52015-04-09 12:58:51 -06001839int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001840{
1841 if( this->m_data != rhs.m_data) return 0;
1842 return 1;
1843}
1844
1845// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001846int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001847{
1848 if( this->m_data_size < rhs.m_data_size ) return 1;
1849 return 0;
1850}
1851