blob: c0ed75a7777b81e38646680b3bec9da11b2e7aa6 [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 Elliott7e40db92015-08-21 15:09:33 -060036#include "vk_ext_khr_swapchain.h"
37#include "vk_ext_khr_device_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;
140 PFN_vkGetSurfacePropertiesKHR m_fpGetSurfacePropertiesKHR;
141 PFN_vkGetSurfaceFormatsKHR m_fpGetSurfaceFormatsKHR;
142 PFN_vkGetSurfacePresentModesKHR m_fpGetSurfacePresentModesKHR;
143 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 Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600424 VkResult err;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600425 VkSubresourceLayout sr_layout;
426 char *ptr;
427 VkTestImageRecord record;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600428 VkImageObj displayImage(image->device());
429 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
430
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800431 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 -0600432
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600433 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600434
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600435 const VkImageSubresource sr = {
Courtney Goeltzenleuchter908e7672015-10-21 17:00:51 -0600436 VK_IMAGE_ASPECT_COLOR_BIT, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600437 };
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600438
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600439 vkGetImageSubresourceLayout(displayImage.device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600440
Chia-I Wu681d7a02015-07-03 13:44:34 +0800441 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600442 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600443
444 ptr += sr_layout.offset;
445
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600446 record.m_title.append(comment);
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600447 record.m_width = displayImage.width();
448 record.m_height = displayImage.height();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600449 // TODO: Need to make this more robust to handle different image formats
Tony-LunarG399dfca2015-05-19 14:08:26 -0600450 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600451 record.m_data = malloc(record.m_data_size);
452 memcpy(record.m_data, ptr, record.m_data_size);
453 m_images.push_back(record);
454 m_display_image = --m_images.end();
455
Chia-I Wu681d7a02015-07-03 13:44:34 +0800456 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600457}
458
Tony Barbour6918cd52015-04-09 12:58:51 -0600459void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600460{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600461 for (int32_t i = 0; i < images.size(); i++) {
462 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600463 }
464}
465
Tony Barbour6918cd52015-04-09 12:58:51 -0600466void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600467{
468 const ::testing::TestInfo* const test_info =
469 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600470 ostringstream filestream;
471 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600472
Tony Barbour247bf372014-10-30 14:29:04 -0600473 m_width = 40;
474
475 if (strcmp(test_info->name(), m_testName.c_str())) {
476 filestream << test_info->name();
477 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700478 m_frameNum = 2;
479 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600480 }
481 else {
482 filestream << test_info->name() << "-" << m_frameNum;
483 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700484 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600485 }
486
Tony Barbour247bf372014-10-30 14:29:04 -0600487 // ToDo - scrub string for bad characters
488
489 if (m_save_images || m_compare_images) {
490 WritePPM(filename.c_str(), image);
491 if (m_compare_images) {
492 Compare(filename.c_str(), image);
493 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600494 }
495
496 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600497 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600498 }
499}
500
Chia-I Wuf8693382015-04-16 22:02:10 +0800501TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
502 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700503 m_queue(*m_device.graphics_queues()[0]),
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800504 m_cmdpool(m_device, vk_testing::CommandPool::create_info(m_device.graphics_queue_node_index_)),
505 m_cmdbuf(m_device, vk_testing::CommandBuffer::create_info(m_cmdpool.handle()))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600506{
Tony Barbour96db8822015-02-25 12:28:39 -0700507 m_quit = false;
508 m_pause = false;
509 m_width = 0;
510 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600511}
512
Tony Barbour6918cd52015-04-09 12:58:51 -0600513void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600514{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600515 VkResult U_ASSERT_ONLY err;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600516 vk_testing::Buffer buf;
517 void *dest_ptr;
518
Tony Barbour6a3faf02015-07-23 10:36:18 -0600519 VkSemaphore presentCompleteSemaphore;
520 VkSemaphoreCreateInfo presentCompleteSemaphoreCreateInfo = {};
521 presentCompleteSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
522 presentCompleteSemaphoreCreateInfo.pNext = NULL;
523 presentCompleteSemaphoreCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
524
525
526 err = vkCreateSemaphore(m_device.handle(),
527 &presentCompleteSemaphoreCreateInfo,
Chia-I Wuf7458c52015-10-26 21:10:41 +0800528 NULL, &presentCompleteSemaphore);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600529 assert(!err);
530
531 // Get the index of the next available swapchain image:
Ian Elliott7e40db92015-08-21 15:09:33 -0600532 err = m_fpAcquireNextImageKHR(m_device.handle(), m_swap_chain,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600533 UINT64_MAX,
534 presentCompleteSemaphore,
535 &m_current_buffer);
Ian Elliott7e40db92015-08-21 15:09:33 -0600536 // TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
Tony Barbour6a3faf02015-07-23 10:36:18 -0600537 // return codes
538 assert(!err);
539
Tony-LunarG399dfca2015-05-19 14:08:26 -0600540 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Cody Northrop7fb43862015-06-22 14:56:14 -0600541 buf.init_as_src(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800542 dest_ptr = buf.memory().map();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600543 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800544 buf.memory().unmap();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600545
546 m_cmdbuf.begin();
Tony Barbourbd094ce2015-10-23 11:00:15 -0600547 VkImageMemoryBarrier memoryBarrier = {};
548 memoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
549 memoryBarrier.pNext = NULL;
Chia-I Wua4594202015-10-27 19:54:37 +0800550 memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
551 memoryBarrier.dstAccessMask = 0;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600552 memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SOURCE_KHR;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800553 memoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600554 memoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800555 memoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600556 memoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
557 memoryBarrier.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800558 memoryBarrier.subresourceRange.levelCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600559 memoryBarrier.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800560 memoryBarrier.subresourceRange.layerCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600561 memoryBarrier.image = m_buffers[m_current_buffer].image;
562 VkImageMemoryBarrier *pmemory_barrier = &memoryBarrier;
Chia-I Wu89d0f942015-10-31 00:31:16 +0800563 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 +0800564 0, 1, (const void * const*)&pmemory_barrier);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600565
566 VkBufferImageCopy region = {};
567 region.imageExtent.height = m_display_image->m_height;
568 region.imageExtent.width = m_display_image->m_width;
569 region.imageExtent.depth = 1;
570
Chia-I Wube2b9172015-07-03 11:49:42 +0800571 vkCmdCopyBufferToImage(m_cmdbuf.handle(),
Chia-I Wu681d7a02015-07-03 13:44:34 +0800572 buf.handle(),
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800573 m_buffers[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600574 1, &region);
Tony Barbourbd094ce2015-10-23 11:00:15 -0600575
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800576 memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600577 memoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SOURCE_KHR;
Chia-I Wu89d0f942015-10-31 00:31:16 +0800578 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 +0800579 0, 1, (const void * const*)&pmemory_barrier);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600580 m_cmdbuf.end();
581
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800582 VkCommandBuffer cmdBufs[1];
Chia-I Wube2b9172015-07-03 11:49:42 +0800583 cmdBufs[0] = m_cmdbuf.handle();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600584
Chia-I Wua690b412015-10-29 22:01:53 +0800585 // Wait for the present complete semaphore to be signaled to ensure
586 // that the image won't be rendered to until the presentation
587 // engine has fully released ownership to the application, and it is
588 // okay to render to the image.
Tony Barbour67e99152015-07-10 14:10:27 -0600589 VkFence nullFence = { VK_NULL_HANDLE };
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600590 VkSubmitInfo submit_info;
Chia-I Wuf9be13c2015-10-26 20:37:06 +0800591 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
592 submit_info.pNext = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +0800593 submit_info.waitSemaphoreCount = 1;
Chia-I Wua690b412015-10-29 22:01:53 +0800594 submit_info.pWaitSemaphores = &presentCompleteSemaphore,
Chia-I Wud50a7d72015-10-26 20:48:51 +0800595 submit_info.commandBufferCount = 1;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600596 submit_info.pCommandBuffers = cmdBufs;
Chia-I Wud50a7d72015-10-26 20:48:51 +0800597 submit_info.signalSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600598 submit_info.pSignalSemaphores = NULL;
599
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -0600600 vkQueueSubmit(m_queue.handle(), 1, &submit_info, nullFence);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600601 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700602
Chia-I Wuf7458c52015-10-26 21:10:41 +0800603 vkDestroySemaphore(m_device.handle(), presentCompleteSemaphore, NULL);
Chia-I Wua690b412015-10-29 22:01:53 +0800604
Ian Elliott7e40db92015-08-21 15:09:33 -0600605 VkPresentInfoKHR present = {};
606 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600607 present.pNext = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600608 present.swapchainCount = 1;
609 present.swapchains = & m_swap_chain;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600610 present.imageIndices = &m_current_buffer;
Tony Barbour96db8822015-02-25 12:28:39 -0700611
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600612#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800613 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700614 XCB_PROP_MODE_REPLACE,
615 m_window,
616 XCB_ATOM_WM_NAME,
617 XCB_ATOM_STRING,
618 8,
619 m_display_image->m_title.size(),
620 m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600621#endif
Jon Ashburn07daee72015-05-21 18:13:33 -0600622
Ian Elliott7e40db92015-08-21 15:09:33 -0600623 err = m_fpQueuePresentKHR(m_queue.handle(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700624 assert(!err);
625
626 m_queue.wait();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600627 m_current_buffer = (m_current_buffer + 1) % 2;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600628}
629
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600630#ifdef _WIN32
Tony-LunarG399dfca2015-05-19 14:08:26 -0600631# define PREVIOUSLY_DOWN 1<<29
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600632// MS-Windows event handling function:
633LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
634 UINT uMsg,
635 WPARAM wParam,
636 LPARAM lParam)
637{
638
639 switch(uMsg)
640 {
641 case WM_CLOSE:
642 PostQuitMessage(0);
643 break;
644
645 case WM_PAINT:
646 {
647 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
648 if (me) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600649 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600650 me->Display();
651 }
652 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600653 break;
654
655 case WM_KEYDOWN:
656 {
657 if (lParam & (PREVIOUSLY_DOWN)){
658 break;
659 }
660 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
661 // the window, we put the this pointer into the window's user data so we could get it back now
662 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
663 switch (wParam)
664 {
665 case VK_ESCAPE: me->m_quit = true;
666 break;
667
668 case VK_LEFT: // left arrow key
669 if (me->m_display_image == me->m_images.begin()) {
670 me->m_display_image = --me->m_images.end();
671 }
672 else {
673 --me->m_display_image;
674 }
675 break;
676
677 case VK_RIGHT: // right arrow key
678 ++me->m_display_image;
679 if (me->m_display_image == me->m_images.end()) {
680 me->m_display_image = me->m_images.begin();
681 }
682 break;
683
684 default:
685 break;
686 }
687 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
688 me->Display();
689 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600690 }
691 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
692}
693
694void TestFrameworkVkPresent::Run()
695{
696 MSG msg; // message
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600697
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600698 /* main message loop*/
Tony-LunarG399dfca2015-05-19 14:08:26 -0600699 while(! m_quit) {
700 GetMessage(&msg, m_window, 0, 0);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600701 if (msg.message == WM_QUIT) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600702 m_quit = true; //if found, quit app
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600703 } else {
704 /* Translate and dispatch to event queue*/
705 TranslateMessage(&msg);
706 DispatchMessage(&msg);
707 }
708 }
709}
710
711#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600712void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600713{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600714 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700715 switch (event_code) {
716 case XCB_EXPOSE:
717 Display(); // TODO: handle resize
718 break;
719 case XCB_CLIENT_MESSAGE:
720 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
721 (m_atom_wm_delete_window)->atom) {
722 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600723 }
724 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700725 case XCB_KEY_RELEASE:
726 {
727 const xcb_key_release_event_t *key =
728 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600729
Tony Barbour96db8822015-02-25 12:28:39 -0700730 switch (key->detail) {
731 case 0x9: // Escape
732 m_quit = true;
733 break;
734 case 0x71: // left arrow key
735 if (m_display_image == m_images.begin()) {
736 m_display_image = --m_images.end();
737 } else {
738 --m_display_image;
739 }
740 break;
741 case 0x72: // right arrow key
742 ++m_display_image;
743 if (m_display_image == m_images.end()) {
744 m_display_image = m_images.begin();
745 }
746 break;
747 case 0x41:
748 m_pause = !m_pause;
749 break;
750 }
751 Display();
752 }
753 break;
754 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600755 break;
756 }
Tony Barbour96db8822015-02-25 12:28:39 -0700757}
758
Tony Barbour6918cd52015-04-09 12:58:51 -0600759void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700760{
Chia-I Wuf8693382015-04-16 22:02:10 +0800761 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700762
763 while (! m_quit) {
764 xcb_generic_event_t *event;
765
766 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800767 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700768 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800769 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700770 }
771 if (event) {
772 HandleEvent(event);
773 free(event);
774 }
775 }
776}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600777#endif // _WIN32
Tony Barbour96db8822015-02-25 12:28:39 -0700778
Ian Elliott7e40db92015-08-21 15:09:33 -0600779void TestFrameworkVkPresent::CreateSwapchain()
Tony Barbour96db8822015-02-25 12:28:39 -0700780{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600781 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700782
Tony-LunarG399dfca2015-05-19 14:08:26 -0600783 m_display_image = m_images.begin();
784 m_current_buffer = 0;
785
Tony Barbour6a3faf02015-07-23 10:36:18 -0600786 // Construct the WSI surface description:
Ian Elliott7e40db92015-08-21 15:09:33 -0600787 m_surface_description.sType = VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600788 m_surface_description.pNext = NULL;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600789#ifdef _WIN32
Ian Elliott7e40db92015-08-21 15:09:33 -0600790 m_surface_description.platform = VK_PLATFORM_WIN32_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600791 m_surface_description.pPlatformHandle = m_connection;
792 m_surface_description.pPlatformWindow = m_window;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600793#else // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -0600794 m_platform_handle_xcb.connection = m_connection;
795 m_platform_handle_xcb.root = m_screen->root;
Ian Elliott7e40db92015-08-21 15:09:33 -0600796 m_surface_description.platform = VK_PLATFORM_XCB_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600797 m_surface_description.pPlatformHandle = &m_platform_handle_xcb;
798 m_surface_description.pPlatformWindow = &m_window;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600799#endif // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -0600800
801 // Iterate over each queue to learn whether it supports presenting to WSI:
802 VkBool32 supportsPresent;
803 m_present_queue_node_index = UINT32_MAX;
804 std::vector<vk_testing::Queue *> queues = m_device.graphics_queues();
805 for (int i=0; i < queues.size(); i++)
806 {
807 int family_index = queues[i]->get_family_index();
Ian Elliott7e40db92015-08-21 15:09:33 -0600808 m_fpGetPhysicalDeviceSurfaceSupportKHR(m_device.phy().handle(),
Tony Barbour6a3faf02015-07-23 10:36:18 -0600809 family_index,
Ian Elliott7e40db92015-08-21 15:09:33 -0600810 (VkSurfaceDescriptionKHR *) &m_surface_description,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600811 &supportsPresent);
812 if (supportsPresent) {
813 m_present_queue_node_index = family_index;
814 }
815 }
816
817 assert(m_present_queue_node_index != UINT32_MAX);
818
819
820 // Get the list of VkFormat's that are supported:
Ian Elliott8b139792015-08-07 11:51:12 -0600821 uint32_t formatCount;
Ian Elliott7e40db92015-08-21 15:09:33 -0600822 err = m_fpGetSurfaceFormatsKHR(m_device.handle(),
823 (VkSurfaceDescriptionKHR *) &m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600824 &formatCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600825 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600826 VkSurfaceFormatKHR *surfFormats =
827 (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
828 err = m_fpGetSurfaceFormatsKHR(m_device.handle(),
829 (VkSurfaceDescriptionKHR *) &m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600830 &formatCount, surfFormats);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600831 assert(!err);
832 // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
833 // the surface has no preferred format. Otherwise, at least one
834 // supported format will be returned.
Tony Barbour6a3faf02015-07-23 10:36:18 -0600835 if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED)
836 {
837 m_format = VK_FORMAT_B8G8R8A8_UNORM;
838 }
839 else
840 {
841 assert(formatCount >= 1);
842 m_format = surfFormats[0].format;
843 }
Ian Elliott8b139792015-08-07 11:51:12 -0600844 m_color_space = surfFormats[0].colorSpace;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600845
846 // Check the surface proprties and formats
Ian Elliott7e40db92015-08-21 15:09:33 -0600847 VkSurfacePropertiesKHR surfProperties;
848 err = m_fpGetSurfacePropertiesKHR(m_device.handle(),
849 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600850 &surfProperties);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600851 assert(!err);
852
Ian Elliott8b139792015-08-07 11:51:12 -0600853 uint32_t presentModeCount;
Ian Elliott7e40db92015-08-21 15:09:33 -0600854 err = m_fpGetSurfacePresentModesKHR(m_device.handle(),
855 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600856 &presentModeCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600857 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600858 VkPresentModeKHR *presentModes =
859 (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
Ian Elliott8b139792015-08-07 11:51:12 -0600860 assert(presentModes);
Ian Elliott7e40db92015-08-21 15:09:33 -0600861 err = m_fpGetSurfacePresentModesKHR(m_device.handle(),
862 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600863 &presentModeCount, presentModes);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600864 assert(!err);
865
Ian Elliott7e40db92015-08-21 15:09:33 -0600866 VkExtent2D swapchainExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600867 // width and height are either both -1, or both not -1.
Ian Elliott8b139792015-08-07 11:51:12 -0600868 if (surfProperties.currentExtent.width == -1)
Tony Barbour6a3faf02015-07-23 10:36:18 -0600869 {
870 // If the surface size is undefined, the size is set to
871 // the size of the images requested.
Ian Elliott7e40db92015-08-21 15:09:33 -0600872 swapchainExtent.width = m_width;
873 swapchainExtent.height = m_height;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600874 }
875 else
876 {
877 // If the surface size is defined, the swap chain size must match
Ian Elliott7e40db92015-08-21 15:09:33 -0600878 swapchainExtent = surfProperties.currentExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600879 }
880
881 // If mailbox mode is available, use it, as is the lowest-latency non-
Ian Elliottae0e8242015-08-10 13:20:49 -0600882 // tearing mode. If not, try IMMEDIATE which will usually be available,
883 // and is fastest (though it tears). If not, fall back to FIFO which is
884 // always available.
Ian Elliott7e40db92015-08-21 15:09:33 -0600885 VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600886 for (size_t i = 0; i < presentModeCount; i++) {
Ian Elliott7e40db92015-08-21 15:09:33 -0600887 if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
888 swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600889 break;
890 }
Ian Elliott7e40db92015-08-21 15:09:33 -0600891 if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) &&
892 (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
893 swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
Ian Elliottae0e8242015-08-10 13:20:49 -0600894 }
Tony Barbour6a3faf02015-07-23 10:36:18 -0600895 }
896
897 // Determine the number of VkImage's to use in the swap chain (we desire to
898 // own only 1 image at a time, besides the images being displayed and
899 // queued for display):
Ian Elliott7e40db92015-08-21 15:09:33 -0600900 uint32_t desiredNumberOfSwapchainImages = surfProperties.minImageCount + 1;
Ian Elliott8b139792015-08-07 11:51:12 -0600901 if ((surfProperties.maxImageCount > 0) &&
Ian Elliott7e40db92015-08-21 15:09:33 -0600902 (desiredNumberOfSwapchainImages > surfProperties.maxImageCount))
Tony Barbour6a3faf02015-07-23 10:36:18 -0600903 {
904 // Application must settle for fewer images than desired:
Ian Elliott7e40db92015-08-21 15:09:33 -0600905 desiredNumberOfSwapchainImages = surfProperties.maxImageCount;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600906 }
907
Ian Elliott7e40db92015-08-21 15:09:33 -0600908 VkSurfaceTransformKHR preTransform;
909 if (surfProperties.supportedTransforms & VK_SURFACE_TRANSFORM_NONE_BIT_KHR) {
910 preTransform = VK_SURFACE_TRANSFORM_NONE_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600911 } else {
Ian Elliott8b139792015-08-07 11:51:12 -0600912 preTransform = surfProperties.currentTransform;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600913 }
Ian Elliott1a3845b2015-07-06 14:33:04 -0600914
Cody Northropdf5b0922015-08-28 16:22:48 -0600915 // 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 +0800916 assert((surfProperties.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) != 0);
Cody Northropdf5b0922015-08-28 16:22:48 -0600917
Ian Elliott7e40db92015-08-21 15:09:33 -0600918 VkSwapchainCreateInfoKHR swap_chain = {};
Ian Elliotta257eea2015-09-22 10:20:23 -0600919 swap_chain.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600920 swap_chain.pNext = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600921 swap_chain.pSurfaceDescription = (const VkSurfaceDescriptionKHR *)&m_surface_description;
922 swap_chain.minImageCount = desiredNumberOfSwapchainImages;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600923 swap_chain.imageFormat = m_format;
Ian Elliott8b139792015-08-07 11:51:12 -0600924 swap_chain.imageColorSpace = m_color_space;
Ian Elliott7e40db92015-08-21 15:09:33 -0600925 swap_chain.imageExtent.width = swapchainExtent.width;
926 swap_chain.imageExtent.height = swapchainExtent.height;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800927 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DST_BIT |
Cody Northropdf8f42a2015-08-05 15:38:39 -0600928 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600929 swap_chain.preTransform = preTransform;
Chia-I Wuf8693382015-04-16 22:02:10 +0800930 swap_chain.imageArraySize = 1;
Ian Elliott8b139792015-08-07 11:51:12 -0600931 swap_chain.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
932 swap_chain.queueFamilyCount = 0;
933 swap_chain.pQueueFamilyIndices = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600934 swap_chain.presentMode = swapchainPresentMode;
Chia-I Wue2fc5522015-10-26 20:04:44 +0800935 swap_chain.oldSwapchain = VK_NULL_HANDLE;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600936 swap_chain.clipped = true;
937
938 uint32_t i;
Chia-I Wuf8693382015-04-16 22:02:10 +0800939
Ian Elliott7e40db92015-08-21 15:09:33 -0600940 err = m_fpCreateSwapchainKHR(m_device.handle(), &swap_chain, &m_swap_chain);
Chia-I Wuf8693382015-04-16 22:02:10 +0800941 assert(!err);
942
Ian Elliott7e40db92015-08-21 15:09:33 -0600943 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
944 &m_swapchainImageCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600945 assert(!err);
946
Ian Elliott7e40db92015-08-21 15:09:33 -0600947 VkImage* swapchainImages = (VkImage*)malloc(m_swapchainImageCount * sizeof(VkImage));
948 assert(swapchainImages);
949 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
950 &m_swapchainImageCount, swapchainImages);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600951 assert(!err);
952
Ian Elliott7e40db92015-08-21 15:09:33 -0600953 m_buffers = (SwapchainBuffers*)malloc(sizeof(SwapchainBuffers)*m_swapchainImageCount);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600954 assert(m_buffers);
955
Ian Elliott7e40db92015-08-21 15:09:33 -0600956 for (i = 0; i < m_swapchainImageCount; i++) {
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600957 VkImageViewCreateInfo color_image_view = {};
958 color_image_view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
959 color_image_view.pNext = NULL;
Courtney Goeltzenleuchter00265c82015-09-11 15:22:06 -0600960 color_image_view.viewType = VK_IMAGE_VIEW_TYPE_2D;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600961 color_image_view.format = m_format;
Courtney Goeltzenleuchterba724512015-09-10 17:58:54 -0600962 color_image_view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600963 color_image_view.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800964 color_image_view.subresourceRange.levelCount = 1;
Courtney Goeltzenleuchter4a261892015-09-10 16:38:41 -0600965 color_image_view.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800966 color_image_view.subresourceRange.layerCount = 1;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600967
Ian Elliott7e40db92015-08-21 15:09:33 -0600968 m_buffers[i].image = swapchainImages[i];
Tony Barbour6a3faf02015-07-23 10:36:18 -0600969
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600970 color_image_view.image = m_buffers[i].image;
971 err = vkCreateImageView(m_device.handle(),
Chia-I Wuf7458c52015-10-26 21:10:41 +0800972 &color_image_view, NULL, &m_buffers[i].view);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600973 assert(!err);
Tony Barbourbd094ce2015-10-23 11:00:15 -0600974
975 /* Set image layout to PRESENT_SOURCE_KHR so that before the copy, it can be set to */
976 /* TRANSFER_DESTINATION_OPTIMAL */
977 SetImageLayout(m_buffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT,
978 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SOURCE_KHR);
979
Tony Barbour6a3faf02015-07-23 10:36:18 -0600980 }
Tony Barbour96db8822015-02-25 12:28:39 -0700981}
Tony Barbourbd094ce2015-10-23 11:00:15 -0600982void TestFrameworkVkPresent::SetImageLayout(VkImage image, VkImageAspectFlags aspectMask,
983 VkImageLayout old_image_layout, VkImageLayout new_image_layout)
984{
985 VkResult U_ASSERT_ONLY err;
986
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800987 VkCommandBufferBeginInfo cmd_buf_info = {};
988 cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600989 cmd_buf_info.pNext = NULL;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800990 cmd_buf_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600991 cmd_buf_info.renderPass = { VK_NULL_HANDLE };
992 cmd_buf_info.subpass = 0;
993 cmd_buf_info.framebuffer = { VK_NULL_HANDLE };
994
995 err = vkBeginCommandBuffer(m_cmdbuf.handle(), &cmd_buf_info);
996 assert(!err);
997
998 VkImageMemoryBarrier image_memory_barrier = {};
999 image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
1000 image_memory_barrier.pNext = NULL;
Chia-I Wua4594202015-10-27 19:54:37 +08001001 image_memory_barrier.srcAccessMask = 0;
1002 image_memory_barrier.dstAccessMask = 0;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001003 image_memory_barrier.oldLayout = old_image_layout;
1004 image_memory_barrier.newLayout = new_image_layout;
1005 image_memory_barrier.image = image;
1006 image_memory_barrier.subresourceRange.aspectMask = aspectMask;
1007 image_memory_barrier.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001008 image_memory_barrier.subresourceRange.levelCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001009 image_memory_barrier.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001010 image_memory_barrier.subresourceRange.layerCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001011
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001012 if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
Tony Barbourbd094ce2015-10-23 11:00:15 -06001013 /* Make sure anything that was copying from this image has completed */
Chia-I Wua4594202015-10-27 19:54:37 +08001014 image_memory_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001015 }
1016
1017 if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
1018 /* Make sure any Copy or CPU writes to image are flushed */
Chia-I Wua4594202015-10-27 19:54:37 +08001019 image_memory_barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001020 }
1021
1022 VkImageMemoryBarrier *pmemory_barrier = &image_memory_barrier;
1023
1024 VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1025 VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1026
Chia-I Wu53534662015-10-26 17:08:33 +08001027 vkCmdPipelineBarrier(m_cmdbuf.handle(), src_stages, dest_stages, 0, 1, (const void * const*)&pmemory_barrier);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001028
1029 err = vkEndCommandBuffer(m_cmdbuf.handle());
1030 assert(!err);
1031
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001032 const VkCommandBuffer cmd_bufs[] = { m_cmdbuf.handle() };
Tony Barbourbd094ce2015-10-23 11:00:15 -06001033 VkFence nullFence = { VK_NULL_HANDLE };
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001034 VkSubmitInfo submit_info;
Chia-I Wuf9be13c2015-10-26 20:37:06 +08001035 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1036 submit_info.pNext = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001037 submit_info.waitSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001038 submit_info.pWaitSemaphores = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001039 submit_info.commandBufferCount = 1;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001040 submit_info.pCommandBuffers = cmd_bufs;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001041 submit_info.signalSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001042 submit_info.pSignalSemaphores = NULL;
1043
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -06001044 err = vkQueueSubmit(m_queue.handle(), 1, &submit_info, nullFence);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001045 assert(!err);
1046
1047 err = vkQueueWaitIdle(m_queue.handle());
1048 assert(!err);
1049
1050}
Tony Barbour96db8822015-02-25 12:28:39 -07001051
Jon Ashburn07daee72015-05-21 18:13:33 -06001052void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -07001053{
Ian Elliott7e40db92015-08-21 15:09:33 -06001054 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceSupportKHR);
1055 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfacePropertiesKHR);
1056 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfaceFormatsKHR);
1057 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfacePresentModesKHR);
1058 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1059 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1060 GET_DEVICE_PROC_ADDR(m_device.handle(), DestroySwapchainKHR);
1061 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSwapchainImagesKHR);
1062 GET_DEVICE_PROC_ADDR(m_device.handle(), AcquireNextImageKHR);
1063 GET_DEVICE_PROC_ADDR(m_device.handle(), QueuePresentKHR);
Jon Ashburn07daee72015-05-21 18:13:33 -06001064
Tony Barbour96db8822015-02-25 12:28:39 -07001065 m_images = imagesIn;
1066}
1067
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001068#ifdef _WIN32
1069void TestFrameworkVkPresent::CreateMyWindow()
1070{
1071 WNDCLASSEX win_class;
1072 // const ::testing::TestInfo* const test_info =
1073 // ::testing::UnitTest::GetInstance()->current_test_info();
1074 m_connection = GetModuleHandle(NULL);
1075
1076 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1077 it != m_images.end(); it++) {
1078 if (m_width < it->m_width)
1079 m_width = it->m_width;
1080 if (m_height < it->m_height)
1081 m_height = it->m_height;
1082 }
1083 // Initialize the window class structure:
1084 win_class.cbSize = sizeof(WNDCLASSEX);
1085 win_class.style = CS_HREDRAW | CS_VREDRAW;
1086 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
1087 win_class.cbClsExtra = 0;
1088 win_class.cbWndExtra = 0;
1089 win_class.hInstance = m_connection; // hInstance
1090 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
1091 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
1092 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
1093 win_class.lpszMenuName = NULL;
1094 win_class.lpszClassName = "Test";
1095 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
1096 // Register window class:
1097 if (!RegisterClassEx(&win_class)) {
1098 // It didn't work, so try to give a useful error:
1099 printf("Unexpected error trying to start the application!\n");
1100 fflush(stdout);
1101 exit(1);
1102 }
1103 // Create window with the registered class:
Cody Northrop39582252015-08-05 15:39:31 -06001104 RECT wr = { 0, 0, m_width, m_height };
1105 AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001106 m_window = CreateWindowEx(0,
1107 "Test", // class name
1108 "Test", // app name
1109 WS_OVERLAPPEDWINDOW | // window style
1110 WS_VISIBLE |
1111 WS_SYSMENU,
1112 100,100, // x/y coords
Cody Northrop39582252015-08-05 15:39:31 -06001113 wr.right - wr.left, // width
1114 wr.bottom - wr.top, // height
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001115 NULL, // handle to parent
1116 NULL, // handle to menu
1117 m_connection, // hInstance
1118 NULL); // no extra parameters
1119
1120 if (!m_window) {
1121 // It didn't work, so try to give a useful error:
1122 DWORD error = GetLastError();
1123 char message[120];
1124 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
1125 MessageBox(NULL, message, "Error", MB_OK);
1126 exit(1);
1127 }
Tony-LunarG399dfca2015-05-19 14:08:26 -06001128 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
1129 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001130}
1131#else
Tony Barbour6918cd52015-04-09 12:58:51 -06001132void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -07001133{
Chia-I Wuf8693382015-04-16 22:02:10 +08001134 const xcb_setup_t *setup;
1135 xcb_screen_iterator_t iter;
1136 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -07001137 uint32_t value_mask, value_list[32];
1138
Chia-I Wuf8693382015-04-16 22:02:10 +08001139 m_connection = xcb_connect(NULL, &scr);
1140
1141 setup = xcb_get_setup(m_connection);
1142 iter = xcb_setup_roots_iterator(setup);
1143 while (scr-- > 0)
1144 xcb_screen_next(&iter);
1145
1146 m_screen = iter.data;
1147
1148 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1149 it != m_images.end(); it++) {
1150 if (m_width < it->m_width)
1151 m_width = it->m_width;
1152 if (m_height < it->m_height)
1153 m_height = it->m_height;
1154 }
1155
1156 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -07001157
1158 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +08001159 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -07001160 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
1161 XCB_EVENT_MASK_EXPOSURE |
1162 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
1163
Chia-I Wuf8693382015-04-16 22:02:10 +08001164 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -07001165 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001166 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -07001167 0, 0, m_width, m_height, 0,
1168 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001169 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -07001170 value_mask, value_list);
1171
1172 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +08001173 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -07001174 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +08001175 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001176
Chia-I Wuf8693382015-04-16 22:02:10 +08001177 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
1178 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001179
Chia-I Wuf8693382015-04-16 22:02:10 +08001180 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -07001181 m_window, (*reply).atom, 4, 32, 1,
1182 &(*m_atom_wm_delete_window).atom);
1183 free(reply);
1184
Chia-I Wuf8693382015-04-16 22:02:10 +08001185 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -07001186}
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001187#endif
Tony Barbour96db8822015-02-25 12:28:39 -07001188
Tony Barbour6918cd52015-04-09 12:58:51 -06001189void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -07001190{
Ian Elliott7e40db92015-08-21 15:09:33 -06001191 m_fpDestroySwapchainKHR(m_device.handle(), m_swap_chain);
Tony Barbour9226a822015-10-23 10:58:56 -06001192
1193 for (uint32_t i = 0; i < m_swapchainImageCount; i++) {
Chia-I Wuf7458c52015-10-26 21:10:41 +08001194 vkDestroyImageView(m_device.handle(), m_buffers[i].view, NULL);
Tony Barbour9226a822015-10-23 10:58:56 -06001195 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001196#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +08001197 xcb_destroy_window(m_connection, m_window);
1198 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001199#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001200}
1201
Tony Barbour6918cd52015-04-09 12:58:51 -06001202void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001203{
1204 if (m_images.size() == 0) return;
1205
Chia-I Wuf8693382015-04-16 22:02:10 +08001206 vk_testing::Environment env;
1207 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -07001208 {
Chia-I Wuf8693382015-04-16 22:02:10 +08001209 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -07001210
Jon Ashburn07daee72015-05-21 18:13:33 -06001211 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001212 vkPresent.CreateMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -06001213 vkPresent.CreateSwapchain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001214 vkPresent.Run();
1215 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -07001216 }
Chia-I Wuf8693382015-04-16 22:02:10 +08001217 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001218}
1219
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001220//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001221// These are the default resources for TBuiltInResources, used for both
1222// - parsing this string for the case where the user didn't supply one
1223// - dumping out a template for user construction of a config file
1224//
1225static const char* DefaultConfig =
1226 "MaxLights 32\n"
1227 "MaxClipPlanes 6\n"
1228 "MaxTextureUnits 32\n"
1229 "MaxTextureCoords 32\n"
1230 "MaxVertexAttribs 64\n"
1231 "MaxVertexUniformComponents 4096\n"
1232 "MaxVaryingFloats 64\n"
1233 "MaxVertexTextureImageUnits 32\n"
1234 "MaxCombinedTextureImageUnits 80\n"
1235 "MaxTextureImageUnits 32\n"
1236 "MaxFragmentUniformComponents 4096\n"
1237 "MaxDrawBuffers 32\n"
1238 "MaxVertexUniformVectors 128\n"
1239 "MaxVaryingVectors 8\n"
1240 "MaxFragmentUniformVectors 16\n"
1241 "MaxVertexOutputVectors 16\n"
1242 "MaxFragmentInputVectors 15\n"
1243 "MinProgramTexelOffset -8\n"
1244 "MaxProgramTexelOffset 7\n"
1245 "MaxClipDistances 8\n"
1246 "MaxComputeWorkGroupCountX 65535\n"
1247 "MaxComputeWorkGroupCountY 65535\n"
1248 "MaxComputeWorkGroupCountZ 65535\n"
1249 "MaxComputeWorkGroupSizeX 1024\n"
1250 "MaxComputeWorkGroupSizeY 1024\n"
1251 "MaxComputeWorkGroupSizeZ 64\n"
1252 "MaxComputeUniformComponents 1024\n"
1253 "MaxComputeTextureImageUnits 16\n"
1254 "MaxComputeImageUniforms 8\n"
1255 "MaxComputeAtomicCounters 8\n"
1256 "MaxComputeAtomicCounterBuffers 1\n"
1257 "MaxVaryingComponents 60\n"
1258 "MaxVertexOutputComponents 64\n"
1259 "MaxGeometryInputComponents 64\n"
1260 "MaxGeometryOutputComponents 128\n"
1261 "MaxFragmentInputComponents 128\n"
1262 "MaxImageUnits 8\n"
1263 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
1264 "MaxCombinedShaderOutputResources 8\n"
1265 "MaxImageSamples 0\n"
1266 "MaxVertexImageUniforms 0\n"
1267 "MaxTessControlImageUniforms 0\n"
1268 "MaxTessEvaluationImageUniforms 0\n"
1269 "MaxGeometryImageUniforms 0\n"
1270 "MaxFragmentImageUniforms 8\n"
1271 "MaxCombinedImageUniforms 8\n"
1272 "MaxGeometryTextureImageUnits 16\n"
1273 "MaxGeometryOutputVertices 256\n"
1274 "MaxGeometryTotalOutputComponents 1024\n"
1275 "MaxGeometryUniformComponents 1024\n"
1276 "MaxGeometryVaryingComponents 64\n"
1277 "MaxTessControlInputComponents 128\n"
1278 "MaxTessControlOutputComponents 128\n"
1279 "MaxTessControlTextureImageUnits 16\n"
1280 "MaxTessControlUniformComponents 1024\n"
1281 "MaxTessControlTotalOutputComponents 4096\n"
1282 "MaxTessEvaluationInputComponents 128\n"
1283 "MaxTessEvaluationOutputComponents 128\n"
1284 "MaxTessEvaluationTextureImageUnits 16\n"
1285 "MaxTessEvaluationUniformComponents 1024\n"
1286 "MaxTessPatchComponents 120\n"
1287 "MaxPatchVertices 32\n"
1288 "MaxTessGenLevel 64\n"
1289 "MaxViewports 16\n"
1290 "MaxVertexAtomicCounters 0\n"
1291 "MaxTessControlAtomicCounters 0\n"
1292 "MaxTessEvaluationAtomicCounters 0\n"
1293 "MaxGeometryAtomicCounters 0\n"
1294 "MaxFragmentAtomicCounters 8\n"
1295 "MaxCombinedAtomicCounters 8\n"
1296 "MaxAtomicCounterBindings 1\n"
1297 "MaxVertexAtomicCounterBuffers 0\n"
1298 "MaxTessControlAtomicCounterBuffers 0\n"
1299 "MaxTessEvaluationAtomicCounterBuffers 0\n"
1300 "MaxGeometryAtomicCounterBuffers 0\n"
1301 "MaxFragmentAtomicCounterBuffers 1\n"
1302 "MaxCombinedAtomicCounterBuffers 1\n"
1303 "MaxAtomicCounterBufferSize 16384\n"
1304 "MaxTransformFeedbackBuffers 4\n"
1305 "MaxTransformFeedbackInterleavedComponents 64\n"
1306 "MaxCullDistances 8\n"
1307 "MaxCombinedClipAndCullDistances 8\n"
1308 "MaxSamples 4\n"
1309
1310 "nonInductiveForLoops 1\n"
1311 "whileLoops 1\n"
1312 "doWhileLoops 1\n"
1313 "generalUniformIndexing 1\n"
1314 "generalAttributeMatrixVectorIndexing 1\n"
1315 "generalVaryingIndexing 1\n"
1316 "generalSamplerIndexing 1\n"
1317 "generalVariableIndexing 1\n"
1318 "generalConstantMatrixVectorIndexing 1\n"
1319 ;
1320
1321//
1322// *.conf => this is a config file that can set limits/resources
1323//
Tony Barbour6918cd52015-04-09 12:58:51 -06001324bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001325{
1326 if (name.size() < 5)
1327 return false;
1328
1329 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
1330 ConfigFile = name;
1331 return true;
1332 }
1333
1334 return false;
1335}
1336
1337//
1338// Parse either a .conf file provided by the user or the default string above.
1339//
Tony Barbour6918cd52015-04-09 12:58:51 -06001340void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001341{
1342 char** configStrings = 0;
1343 char* config = 0;
1344 if (ConfigFile.size() > 0) {
1345 configStrings = ReadFileData(ConfigFile.c_str());
1346 if (configStrings)
1347 config = *configStrings;
1348 else {
1349 printf("Error opening configuration file; will instead use the default configuration\n");
1350 }
1351 }
1352
1353 if (config == 0) {
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001354 config = (char *) alloca(strlen(DefaultConfig) + 1);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001355 strcpy(config, DefaultConfig);
1356 }
1357
1358 const char* delims = " \t\n\r";
1359 const char* token = strtok(config, delims);
1360 while (token) {
1361 const char* valueStr = strtok(0, delims);
1362 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1363 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1364 return;
1365 }
1366 int value = atoi(valueStr);
1367
1368 if (strcmp(token, "MaxLights") == 0)
1369 Resources.maxLights = value;
1370 else if (strcmp(token, "MaxClipPlanes") == 0)
1371 Resources.maxClipPlanes = value;
1372 else if (strcmp(token, "MaxTextureUnits") == 0)
1373 Resources.maxTextureUnits = value;
1374 else if (strcmp(token, "MaxTextureCoords") == 0)
1375 Resources.maxTextureCoords = value;
1376 else if (strcmp(token, "MaxVertexAttribs") == 0)
1377 Resources.maxVertexAttribs = value;
1378 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1379 Resources.maxVertexUniformComponents = value;
1380 else if (strcmp(token, "MaxVaryingFloats") == 0)
1381 Resources.maxVaryingFloats = value;
1382 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1383 Resources.maxVertexTextureImageUnits = value;
1384 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1385 Resources.maxCombinedTextureImageUnits = value;
1386 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1387 Resources.maxTextureImageUnits = value;
1388 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1389 Resources.maxFragmentUniformComponents = value;
1390 else if (strcmp(token, "MaxDrawBuffers") == 0)
1391 Resources.maxDrawBuffers = value;
1392 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1393 Resources.maxVertexUniformVectors = value;
1394 else if (strcmp(token, "MaxVaryingVectors") == 0)
1395 Resources.maxVaryingVectors = value;
1396 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1397 Resources.maxFragmentUniformVectors = value;
1398 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1399 Resources.maxVertexOutputVectors = value;
1400 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1401 Resources.maxFragmentInputVectors = value;
1402 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1403 Resources.minProgramTexelOffset = value;
1404 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1405 Resources.maxProgramTexelOffset = value;
1406 else if (strcmp(token, "MaxClipDistances") == 0)
1407 Resources.maxClipDistances = value;
1408 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1409 Resources.maxComputeWorkGroupCountX = value;
1410 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1411 Resources.maxComputeWorkGroupCountY = value;
1412 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1413 Resources.maxComputeWorkGroupCountZ = value;
1414 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1415 Resources.maxComputeWorkGroupSizeX = value;
1416 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1417 Resources.maxComputeWorkGroupSizeY = value;
1418 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1419 Resources.maxComputeWorkGroupSizeZ = value;
1420 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1421 Resources.maxComputeUniformComponents = value;
1422 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1423 Resources.maxComputeTextureImageUnits = value;
1424 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1425 Resources.maxComputeImageUniforms = value;
1426 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1427 Resources.maxComputeAtomicCounters = value;
1428 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1429 Resources.maxComputeAtomicCounterBuffers = value;
1430 else if (strcmp(token, "MaxVaryingComponents") == 0)
1431 Resources.maxVaryingComponents = value;
1432 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1433 Resources.maxVertexOutputComponents = value;
1434 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1435 Resources.maxGeometryInputComponents = value;
1436 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1437 Resources.maxGeometryOutputComponents = value;
1438 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1439 Resources.maxFragmentInputComponents = value;
1440 else if (strcmp(token, "MaxImageUnits") == 0)
1441 Resources.maxImageUnits = value;
1442 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1443 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1444 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1445 Resources.maxCombinedShaderOutputResources = value;
1446 else if (strcmp(token, "MaxImageSamples") == 0)
1447 Resources.maxImageSamples = value;
1448 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1449 Resources.maxVertexImageUniforms = value;
1450 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1451 Resources.maxTessControlImageUniforms = value;
1452 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1453 Resources.maxTessEvaluationImageUniforms = value;
1454 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1455 Resources.maxGeometryImageUniforms = value;
1456 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1457 Resources.maxFragmentImageUniforms = value;
1458 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1459 Resources.maxCombinedImageUniforms = value;
1460 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1461 Resources.maxGeometryTextureImageUnits = value;
1462 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1463 Resources.maxGeometryOutputVertices = value;
1464 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1465 Resources.maxGeometryTotalOutputComponents = value;
1466 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1467 Resources.maxGeometryUniformComponents = value;
1468 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1469 Resources.maxGeometryVaryingComponents = value;
1470 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1471 Resources.maxTessControlInputComponents = value;
1472 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1473 Resources.maxTessControlOutputComponents = value;
1474 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1475 Resources.maxTessControlTextureImageUnits = value;
1476 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1477 Resources.maxTessControlUniformComponents = value;
1478 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1479 Resources.maxTessControlTotalOutputComponents = value;
1480 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1481 Resources.maxTessEvaluationInputComponents = value;
1482 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1483 Resources.maxTessEvaluationOutputComponents = value;
1484 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1485 Resources.maxTessEvaluationTextureImageUnits = value;
1486 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1487 Resources.maxTessEvaluationUniformComponents = value;
1488 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1489 Resources.maxTessPatchComponents = value;
1490 else if (strcmp(token, "MaxPatchVertices") == 0)
1491 Resources.maxPatchVertices = value;
1492 else if (strcmp(token, "MaxTessGenLevel") == 0)
1493 Resources.maxTessGenLevel = value;
1494 else if (strcmp(token, "MaxViewports") == 0)
1495 Resources.maxViewports = value;
1496 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1497 Resources.maxVertexAtomicCounters = value;
1498 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1499 Resources.maxTessControlAtomicCounters = value;
1500 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1501 Resources.maxTessEvaluationAtomicCounters = value;
1502 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1503 Resources.maxGeometryAtomicCounters = value;
1504 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1505 Resources.maxFragmentAtomicCounters = value;
1506 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1507 Resources.maxCombinedAtomicCounters = value;
1508 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1509 Resources.maxAtomicCounterBindings = value;
1510 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1511 Resources.maxVertexAtomicCounterBuffers = value;
1512 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1513 Resources.maxTessControlAtomicCounterBuffers = value;
1514 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1515 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1516 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1517 Resources.maxGeometryAtomicCounterBuffers = value;
1518 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1519 Resources.maxFragmentAtomicCounterBuffers = value;
1520 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1521 Resources.maxCombinedAtomicCounterBuffers = value;
1522 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1523 Resources.maxAtomicCounterBufferSize = value;
1524 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1525 Resources.maxTransformFeedbackBuffers = value;
1526 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1527 Resources.maxTransformFeedbackInterleavedComponents = value;
1528 else if (strcmp(token, "MaxCullDistances") == 0)
1529 Resources.maxCullDistances = value;
1530 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1531 Resources.maxCombinedClipAndCullDistances = value;
1532 else if (strcmp(token, "MaxSamples") == 0)
1533 Resources.maxSamples = value;
1534
1535 else if (strcmp(token, "nonInductiveForLoops") == 0)
1536 Resources.limits.nonInductiveForLoops = (value != 0);
1537 else if (strcmp(token, "whileLoops") == 0)
1538 Resources.limits.whileLoops = (value != 0);
1539 else if (strcmp(token, "doWhileLoops") == 0)
1540 Resources.limits.doWhileLoops = (value != 0);
1541 else if (strcmp(token, "generalUniformIndexing") == 0)
1542 Resources.limits.generalUniformIndexing = (value != 0);
1543 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1544 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1545 else if (strcmp(token, "generalVaryingIndexing") == 0)
1546 Resources.limits.generalVaryingIndexing = (value != 0);
1547 else if (strcmp(token, "generalSamplerIndexing") == 0)
1548 Resources.limits.generalSamplerIndexing = (value != 0);
1549 else if (strcmp(token, "generalVariableIndexing") == 0)
1550 Resources.limits.generalVariableIndexing = (value != 0);
1551 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1552 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1553 else
1554 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1555
1556 token = strtok(0, delims);
1557 }
1558 if (configStrings)
1559 FreeFileData(configStrings);
1560}
1561
Tony Barbour6918cd52015-04-09 12:58:51 -06001562void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001563{
1564 if (m_compile_options & EOptionRelaxedErrors)
1565 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1566 if (m_compile_options & EOptionIntermediate)
1567 messages = (EShMessages)(messages | EShMsgAST);
1568 if (m_compile_options & EOptionSuppressWarnings)
1569 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1570}
1571
1572//
1573// Malloc a string of sufficient size and read a string into it.
1574//
Tony Barbour6918cd52015-04-09 12:58:51 -06001575char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001576{
1577 FILE *in;
1578 #if defined(_WIN32) && defined(__GNUC__)
1579 in = fopen(fileName, "r");
1580 int errorCode = in ? 0 : 1;
1581 #else
1582 int errorCode = fopen_s(&in, fileName, "r");
1583 #endif
1584
1585 char *fdata;
1586 int count = 0;
1587 const int maxSourceStrings = 5;
1588 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1589
1590 if (errorCode) {
1591 printf("Error: unable to open input file: %s\n", fileName);
1592 return 0;
1593 }
1594
1595 while (fgetc(in) != EOF)
1596 count++;
1597
1598 fseek(in, 0, SEEK_SET);
1599
1600 if (!(fdata = (char*)malloc(count+2))) {
1601 printf("Error allocating memory\n");
1602 return 0;
1603 }
1604 if (fread(fdata,1,count, in)!=count) {
1605 printf("Error reading input file: %s\n", fileName);
1606 return 0;
1607 }
1608 fdata[count] = '\0';
1609 fclose(in);
1610 if (count == 0) {
1611 return_data[0]=(char*)malloc(count+2);
1612 return_data[0][0]='\0';
1613 m_num_shader_strings = 0;
1614 return return_data;
1615 } else
1616 m_num_shader_strings = 1;
1617
1618 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1619 int ptr_len=0,i=0;
1620 while(count>0){
1621 return_data[i]=(char*)malloc(len+2);
1622 memcpy(return_data[i],fdata+ptr_len,len);
1623 return_data[i][len]='\0';
1624 count-=(len);
1625 ptr_len+=(len);
1626 if(count<len){
1627 if(count==0){
1628 m_num_shader_strings=(i+1);
1629 break;
1630 }
1631 len = count;
1632 }
1633 ++i;
1634 }
1635 return return_data;
1636}
1637
Tony Barbour6918cd52015-04-09 12:58:51 -06001638void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001639{
1640 for(int i=0;i<m_num_shader_strings;i++)
1641 free(data[i]);
1642}
1643
1644//
1645// Deduce the language from the filename. Files must end in one of the
1646// following extensions:
1647//
1648// .vert = vertex
1649// .tesc = tessellation control
1650// .tese = tessellation evaluation
1651// .geom = geometry
1652// .frag = fragment
1653// .comp = compute
1654//
Tony Barbour6918cd52015-04-09 12:58:51 -06001655EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001656{
1657 size_t ext = name.rfind('.');
1658 if (ext == std::string::npos) {
1659 return EShLangVertex;
1660 }
1661
1662 std::string suffix = name.substr(ext + 1, std::string::npos);
1663 if (suffix == "vert")
1664 return EShLangVertex;
1665 else if (suffix == "tesc")
1666 return EShLangTessControl;
1667 else if (suffix == "tese")
1668 return EShLangTessEvaluation;
1669 else if (suffix == "geom")
1670 return EShLangGeometry;
1671 else if (suffix == "frag")
1672 return EShLangFragment;
1673 else if (suffix == "comp")
1674 return EShLangCompute;
1675
1676 return EShLangVertex;
1677}
1678
1679//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001680// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001681//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001682EShLanguage VkTestFramework::FindLanguage(const VkShaderStageFlagBits shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001683{
1684 switch (shader_type) {
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001685 case VK_SHADER_STAGE_VERTEX_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001686 return EShLangVertex;
1687
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001688 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001689 return EShLangTessControl;
1690
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001691 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001692 return EShLangTessEvaluation;
1693
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001694 case VK_SHADER_STAGE_GEOMETRY_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001695 return EShLangGeometry;
1696
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001697 case VK_SHADER_STAGE_FRAGMENT_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001698 return EShLangFragment;
1699
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001700 case VK_SHADER_STAGE_COMPUTE_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001701 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001702
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001703 default:
1704 return EShLangVertex;
1705 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001706}
1707
1708
1709//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001710// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001711// Return value of false means an error was encountered.
1712//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001713bool VkTestFramework::GLSLtoSPV(const VkShaderStageFlagBits shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001714 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001715 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001716{
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001717 glslang::TProgram program;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001718 const char *shaderStrings[1];
1719
1720 // TODO: Do we want to load a special config file depending on the
1721 // shader source? Optional name maybe?
1722 // SetConfigFile(fileName);
1723
1724 ProcessConfigFile();
1725
1726 EShMessages messages = EShMsgDefault;
1727 SetMessageOptions(messages);
1728
1729 EShLanguage stage = FindLanguage(shader_type);
1730 glslang::TShader* shader = new glslang::TShader(stage);
1731
1732 shaderStrings[0] = pshader;
1733 shader->setStrings(shaderStrings, 1);
1734
1735 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1736
Cody Northrop195d6622014-11-03 12:54:37 -07001737 if (! (m_compile_options & EOptionSuppressInfolog)) {
1738 puts(shader->getInfoLog());
1739 puts(shader->getInfoDebugLog());
1740 }
1741
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001742 return false; // something didn't work
1743 }
1744
1745 program.addShader(shader);
1746
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001747
1748 //
1749 // Program-level processing...
1750 //
1751
Cody Northrop195d6622014-11-03 12:54:37 -07001752 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001753
Cody Northrop195d6622014-11-03 12:54:37 -07001754 if (! (m_compile_options & EOptionSuppressInfolog)) {
1755 puts(shader->getInfoLog());
1756 puts(shader->getInfoDebugLog());
1757 }
1758
1759 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001760 }
1761
1762 if (m_compile_options & EOptionDumpReflection) {
1763 program.buildReflection();
1764 program.dumpReflection();
1765 }
1766
Cody Northrop5a95b472015-06-03 13:01:54 -06001767 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1768
1769 //
1770 // Test the different modes of SPIR-V modification
1771 //
1772 if (this->m_canonicalize_spv) {
1773 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1774 }
1775
1776 if (this->m_strip_spv) {
1777 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1778 }
1779
1780 if (this->m_do_everything_spv) {
1781 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1782 }
1783
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001784 delete shader;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001785
1786 return true;
1787}
1788
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001789
1790
Tony Barbour6918cd52015-04-09 12:58:51 -06001791VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001792 m_width( 0 ),
1793 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001794 m_data( NULL ),
1795 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001796{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001797}
1798
Tony Barbour6918cd52015-04-09 12:58:51 -06001799VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001800{
1801
1802}
1803
Tony Barbour6918cd52015-04-09 12:58:51 -06001804VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001805{
1806 m_title = copyin.m_title;
1807 m_width = copyin.m_width;
1808 m_height = copyin.m_height;
1809 m_data_size = copyin.m_data_size;
1810 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1811}
1812
Tony Barbour6918cd52015-04-09 12:58:51 -06001813ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001814{
Tony Barbour6918cd52015-04-09 12:58:51 -06001815 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1816 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001817 return output;
1818}
1819
Tony Barbour6918cd52015-04-09 12:58:51 -06001820VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001821{
1822 m_title = rhs.m_title;
1823 m_width = rhs.m_width;
1824 m_height = rhs.m_height;
1825 m_data_size = rhs.m_data_size;
1826 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001827 return *this;
1828}
1829
Tony Barbour6918cd52015-04-09 12:58:51 -06001830int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001831{
1832 if( this->m_data != rhs.m_data) return 0;
1833 return 1;
1834}
1835
1836// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001837int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001838{
1839 if( this->m_data_size < rhs.m_data_size ) return 1;
1840 return 0;
1841}
1842