blob: c6c0b0b450b533d9c5fd1d89d853eac70efe74fe [file] [log] [blame]
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001// VK tests
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06002//
3// Copyright (C) 2014 LunarG, Inc.
4//
5// Permission is hereby granted, free of charge, to any person obtaining a
6// copy of this software and associated documentation files (the "Software"),
7// to deal in the Software without restriction, including without limitation
8// the rights to use, copy, modify, merge, publish, distribute, sublicense,
9// and/or sell copies of the Software, and to permit persons to whom the
10// Software is furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included
13// in all copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21// DEALINGS IN THE SOFTWARE.
22
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060023#include "vktestframework.h"
24#include "vkrenderframework.h"
Cody Northrop5a95b472015-06-03 13:01:54 -060025#include "SPIRV/GlslangToSpv.h"
26#include "SPIRV/SPVRemapper.h"
Tony Barbour4ab45422014-12-10 17:00:20 -070027#include <limits.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060028#include <math.h>
Chia-I Wuec664fa2014-12-02 11:54:24 +080029#include <wand/MagickWand.h>
Tony Barbourfeb61962015-09-21 15:17:33 -060030#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +080031#include <xcb/xcb.h>
Tony Barbourfeb61962015-09-21 15:17:33 -060032#endif
Ian Elliott7e40db92015-08-21 15:09:33 -060033#include "vk_ext_khr_swapchain.h"
34#include "vk_ext_khr_device_swapchain.h"
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060035
Tony Barbour3d69c9e2015-05-20 16:53:31 -060036#if defined(PATH_MAX) && !defined(MAX_PATH)
37#define MAX_PATH PATH_MAX
38#endif
39
Tony Barbour6a3faf02015-07-23 10:36:18 -060040#ifdef _WIN32
41#define ERR_EXIT(err_msg, err_class) \
42 do { \
43 MessageBox(NULL, err_msg, err_class, MB_OK); \
44 exit(1); \
45 } while (0)
46#else // _WIN32
47
48#define ERR_EXIT(err_msg, err_class) \
49 do { \
50 printf(err_msg); \
51 fflush(stdout); \
52 exit(1); \
53 } while (0)
54#endif // _WIN32
55
56#define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \
57{ \
58 m_fp##entrypoint = (PFN_vk##entrypoint) vkGetInstanceProcAddr(inst, "vk"#entrypoint); \
59 if (m_fp##entrypoint == NULL) { \
60 ERR_EXIT("vkGetInstanceProcAddr failed to find vk"#entrypoint, \
61 "vkGetInstanceProcAddr Failure"); \
62 } \
63}
64
65#define GET_DEVICE_PROC_ADDR(dev, entrypoint) \
66{ \
67 m_fp##entrypoint = (PFN_vk##entrypoint) vkGetDeviceProcAddr(dev, "vk"#entrypoint); \
68 if (m_fp##entrypoint == NULL) { \
69 ERR_EXIT("vkGetDeviceProcAddr failed to find vk"#entrypoint, \
70 "vkGetDeviceProcAddr Failure"); \
71 } \
72}
73
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060074// Command-line options
75enum TOptions {
76 EOptionNone = 0x000,
77 EOptionIntermediate = 0x001,
78 EOptionSuppressInfolog = 0x002,
79 EOptionMemoryLeakMode = 0x004,
80 EOptionRelaxedErrors = 0x008,
81 EOptionGiveWarnings = 0x010,
82 EOptionLinkProgram = 0x020,
83 EOptionMultiThreaded = 0x040,
84 EOptionDumpConfig = 0x080,
85 EOptionDumpReflection = 0x100,
86 EOptionSuppressWarnings = 0x200,
87 EOptionDumpVersions = 0x400,
Cody Northrop3bfd27c2015-03-17 15:55:58 -060088 EOptionSpv = 0x800,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060089 EOptionDefaultDesktop = 0x1000,
90};
91
Ian Elliott7e40db92015-08-21 15:09:33 -060092typedef struct _SwapchainBuffers {
Tony Barbour6a3faf02015-07-23 10:36:18 -060093 VkImage image;
Chia-I Wu3432a0c2015-10-27 18:04:07 +080094 VkCommandBuffer cmd;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -060095 VkImageView view;
Ian Elliott7e40db92015-08-21 15:09:33 -060096} SwapchainBuffers;
Tony Barbour6a3faf02015-07-23 10:36:18 -060097
Chia-I Wuf8693382015-04-16 22:02:10 +080098class TestFrameworkVkPresent
99{
100public:
101 TestFrameworkVkPresent(vk_testing::Device &device);
102
103 void Run();
Jon Ashburn07daee72015-05-21 18:13:33 -0600104 void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst);
Chia-I Wuf8693382015-04-16 22:02:10 +0800105 void CreateMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -0600106 void CreateSwapchain();
Tony Barbourbd094ce2015-10-23 11:00:15 -0600107 void SetImageLayout(VkImage image, VkImageAspectFlags aspectMask,
108 VkImageLayout old_image_layout, VkImageLayout new_image_layout);
Chia-I Wuf8693382015-04-16 22:02:10 +0800109 void TearDown();
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600110#ifdef _WIN32
111 static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
112#endif
113
Chia-I Wuf8693382015-04-16 22:02:10 +0800114
115protected:
116 vk_testing::Device &m_device;
117 vk_testing::Queue &m_queue;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800118 vk_testing::CommandPool m_cmdpool;
119 vk_testing::CommandBuffer m_cmdbuf;
Chia-I Wuf8693382015-04-16 22:02:10 +0800120
121private:
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600122#ifdef _WIN32
123 HINSTANCE m_connection; // hInstance - Windows Instance
124 HWND m_window; // hWnd - window handle
125
126#else
Chia-I Wuf8693382015-04-16 22:02:10 +0800127 xcb_connection_t *m_connection;
128 xcb_screen_t *m_screen;
129 xcb_window_t m_window;
130 xcb_intern_atom_reply_t *m_atom_wm_delete_window;
Ian Elliott7e40db92015-08-21 15:09:33 -0600131 VkPlatformHandleXcbKHR m_platform_handle_xcb;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600132#endif
Courtney Goeltzenleuchterd6079ec2015-04-22 10:09:35 -0600133 std::list<VkTestImageRecord> m_images;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600134 uint32_t m_present_queue_node_index;
Chia-I Wuf8693382015-04-16 22:02:10 +0800135
Ian Elliott7e40db92015-08-21 15:09:33 -0600136 PFN_vkGetPhysicalDeviceSurfaceSupportKHR m_fpGetPhysicalDeviceSurfaceSupportKHR;
137 PFN_vkGetSurfacePropertiesKHR m_fpGetSurfacePropertiesKHR;
138 PFN_vkGetSurfaceFormatsKHR m_fpGetSurfaceFormatsKHR;
139 PFN_vkGetSurfacePresentModesKHR m_fpGetSurfacePresentModesKHR;
140 PFN_vkCreateSwapchainKHR m_fpCreateSwapchainKHR;
141 PFN_vkDestroySwapchainKHR m_fpDestroySwapchainKHR;
142 PFN_vkGetSwapchainImagesKHR m_fpGetSwapchainImagesKHR;
143 PFN_vkAcquireNextImageKHR m_fpAcquireNextImageKHR;
144 PFN_vkQueuePresentKHR m_fpQueuePresentKHR;
145 VkSurfaceDescriptionWindowKHR m_surface_description;
146 uint32_t m_swapchainImageCount;
147 VkSwapchainKHR m_swap_chain;
148 SwapchainBuffers *m_buffers;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600149 VkFormat m_format;
Ian Elliott7e40db92015-08-21 15:09:33 -0600150 VkColorSpaceKHR m_color_space;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600151
152 uint32_t m_current_buffer;
Chia-I Wuf8693382015-04-16 22:02:10 +0800153
154 bool m_quit;
155 bool m_pause;
156
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600157 int m_width;
158 int m_height;
Chia-I Wuf8693382015-04-16 22:02:10 +0800159
160 std::list<VkTestImageRecord>::iterator m_display_image;
161
162 void Display();
Tony Barbourfeb61962015-09-21 15:17:33 -0600163#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800164 void HandleEvent(xcb_generic_event_t *event);
Tony Barbourfeb61962015-09-21 15:17:33 -0600165#endif
Chia-I Wuf8693382015-04-16 22:02:10 +0800166};
167
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600168#ifndef _WIN32
169
170#include <errno.h>
171
172int fopen_s(
173 FILE** pFile,
174 const char* filename,
175 const char* mode
176)
177{
178 if (!pFile || !filename || !mode) {
179 return EINVAL;
180 }
181
182 FILE* f = fopen(filename, mode);
183 if (! f) {
184 if (errno != 0) {
185 return errno;
186 } else {
187 return ENOENT;
188 }
189 }
190 *pFile = f;
191
192 return 0;
193}
194
195#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600196
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600197
198
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600199// Set up environment for GLSL compiler
200// Must be done once per process
201void TestEnvironment::SetUp()
202{
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600203 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600204 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800205
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600206 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600207}
208
209void TestEnvironment::TearDown()
210{
211 glslang::FinalizeProcess();
212}
213
Tony Barbour6918cd52015-04-09 12:58:51 -0600214VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600215 m_compile_options( 0 ),
216 m_num_shader_strings( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600217{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600218
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600219}
220
Tony Barbour6918cd52015-04-09 12:58:51 -0600221VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600222{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600223
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600224}
225
226// Define all the static elements
Cody Northropa3673cf2015-06-09 13:00:45 -0600227bool VkTestFramework::m_show_images = false;
228bool VkTestFramework::m_save_images = false;
229bool VkTestFramework::m_compare_images = false;
230bool VkTestFramework::m_use_glsl = false;
231bool VkTestFramework::m_canonicalize_spv = false;
232bool VkTestFramework::m_strip_spv = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600233bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour6918cd52015-04-09 12:58:51 -0600234int VkTestFramework::m_width = 0;
235int VkTestFramework::m_height = 0;
236std::list<VkTestImageRecord> VkTestFramework::m_images;
237std::list<VkTestImageRecord>::iterator VkTestFramework::m_display_image;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600238int m_display_image_idx = 0;
239
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600240bool VkTestFramework::optionMatch(const char* option, char* optionLine)
241{
242 if (strncmp(option, optionLine, strlen(option)) == 0)
243 return true;
244 else
245 return false;
246}
247
Tony Barbour6918cd52015-04-09 12:58:51 -0600248void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600249{
250 int i, n;
251
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600252 for (i=1, n=1; i< *argc; i++) {
253 if (optionMatch("--show-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600254 m_show_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600255 else if (optionMatch("--save-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600256 m_save_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600257 else if (optionMatch("--no-SPV", argv[i]))
258 m_use_glsl = true;
259 else if (optionMatch("--strip-SPV", argv[i]))
260 m_strip_spv = true;
261 else if (optionMatch("--canonicalize-SPV", argv[i]))
262 m_canonicalize_spv = true;
263 else if (optionMatch("--compare-images", argv[i]))
Tony Barbour247bf372014-10-30 14:29:04 -0600264 m_compare_images = true;
Tony Barbour247bf372014-10-30 14:29:04 -0600265
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600266 else if (optionMatch("--help", argv[i]) ||
267 optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700268 printf("\nOther options:\n");
269 printf("\t--show-images\n"
270 "\t\tDisplay test images in viewer after tests complete.\n");
271 printf("\t--save-images\n"
272 "\t\tSave tests images as ppm files in current working directory.\n"
273 "\t\tUsed to generate golden images for compare-images.\n");
274 printf("\t--compare-images\n"
275 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barboura98d3932014-12-11 09:52:49 -0700276 "\t\tAlso saves the generated test image in current working\n"
277 "\t\t\tdirectory but only if the image is different from the golden\n"
278 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
279 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700280 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600281 printf("\t--no-SPV\n"
282 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600283 printf("\t--strip-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600284 "\t\tStrip SPIR-V debug information (line numbers, names, etc).\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600285 printf("\t--canonicalize-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600286 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600287 exit(0);
288 } else {
289 printf("\nUnrecognized option: %s\n", argv[i]);
290 printf("\nUse --help or -h for option list.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700291 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700292 }
293
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600294 /*
295 * Since the above "consume" inputs, update argv
296 * so that it contains the trimmed list of args for glutInit
297 */
298
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600299 argv[n] = argv[i];
300 n++;
301 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600302}
303
Tony Barbour6918cd52015-04-09 12:58:51 -0600304void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600305{
306 string filename;
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600307 uint32_t x, y;
Tony Barbour6918cd52015-04-09 12:58:51 -0600308 VkImageObj displayImage(image->device());
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600309 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbour84d448c2015-04-02 14:02:33 -0600310
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800311 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 -0600312 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600313
314 filename.append(basename);
315 filename.append(".ppm");
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600316
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600317 const VkImageSubresource sr = {
Courtney Goeltzenleuchter908e7672015-10-21 17:00:51 -0600318 VK_IMAGE_ASPECT_COLOR_BIT, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600319 };
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600320 VkSubresourceLayout sr_layout;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600321
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600322 vkGetImageSubresourceLayout(image->device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600323
Tony Barbour84d448c2015-04-02 14:02:33 -0600324 char *ptr;
Chia-I Wu681d7a02015-07-03 13:44:34 +0800325 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600326 ptr += sr_layout.offset;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600327 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600328 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
329
330 file << "P6\n";
Tony Barbourfeb61962015-09-21 15:17:33 -0600331 file << displayImage.width() << " ";
Tony Barbour84d448c2015-04-02 14:02:33 -0600332 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600333 file << 255 << "\n";
334
Tony Barbour84d448c2015-04-02 14:02:33 -0600335 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700336 const int *row = (const int *) ptr;
337 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600338
Tony Barbourd1c35722015-04-16 15:59:00 -0600339 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700340 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600341 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700342 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
343 file.write((char *) &swapped, 3);
344 row++;
345 }
346 }
Tony Barbourd1c35722015-04-16 15:59:00 -0600347 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700348 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600349 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700350 file.write((char *) row, 3);
351 row++;
352 }
353 }
354 else {
355 printf("Unrecognized image format - will not write image files");
356 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600357 }
358
359 ptr += sr_layout.rowPitch;
360 }
361
362 file.close();
Chia-I Wu681d7a02015-07-03 13:44:34 +0800363 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600364}
365
Tony Barbour6918cd52015-04-09 12:58:51 -0600366void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour247bf372014-10-30 14:29:04 -0600367{
368
369 MagickWand *magick_wand_1;
370 MagickWand *magick_wand_2;
371 MagickWand *compare_wand;
372 MagickBooleanType status;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600373 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600374 double differenz;
375
Tony Barbour4ab45422014-12-10 17:00:20 -0700376 if (getenv("RENDERTEST_GOLDEN_DIR"))
377 {
378 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
379 }
380
Tony Barbour247bf372014-10-30 14:29:04 -0600381 MagickWandGenesis();
382 magick_wand_1=NewMagickWand();
383 sprintf(testimage,"%s.ppm",basename);
384 status=MagickReadImage(magick_wand_1,testimage);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600385 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour247bf372014-10-30 14:29:04 -0600386
387
388 MagickWandGenesis();
389 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700390 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600391 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600392 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour247bf372014-10-30 14:29:04 -0600393
Tony Barbour247bf372014-10-30 14:29:04 -0600394 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
395 if (differenz != 0.0)
396 {
397 char difference[256];
398
399 sprintf(difference,"%s-diff.ppm",basename);
400 status = MagickWriteImage(compare_wand, difference);
401 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
402 }
403 DestroyMagickWand(compare_wand);
404
405 DestroyMagickWand(magick_wand_1);
406 DestroyMagickWand(magick_wand_2);
407 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700408
409 if (differenz == 0.0)
410 {
411 /*
412 * If test image and golden image match, we do not need to
413 * keep around the test image.
414 */
415 remove(testimage);
416 }
Tony Barbour247bf372014-10-30 14:29:04 -0600417}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600418
Tony Barbour6918cd52015-04-09 12:58:51 -0600419void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600420{
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600421 VkResult err;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600422 VkSubresourceLayout sr_layout;
423 char *ptr;
424 VkTestImageRecord record;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600425 VkImageObj displayImage(image->device());
426 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
427
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800428 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 -0600429
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600430 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600431
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600432 const VkImageSubresource sr = {
Courtney Goeltzenleuchter908e7672015-10-21 17:00:51 -0600433 VK_IMAGE_ASPECT_COLOR_BIT, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600434 };
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600435
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600436 vkGetImageSubresourceLayout(displayImage.device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600437
Chia-I Wu681d7a02015-07-03 13:44:34 +0800438 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600439 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600440
441 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;
Chia-I Wua4594202015-10-27 19:54:37 +0800547 memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
548 memoryBarrier.dstAccessMask = 0;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600549 memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SOURCE_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;
560 vkCmdPipelineBarrier(m_cmdbuf.handle(), VK_PIPELINE_STAGE_ALL_GPU_COMMANDS, 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 = {};
564 region.imageExtent.height = m_display_image->m_height;
565 region.imageExtent.width = m_display_image->m_width;
566 region.imageExtent.depth = 1;
567
Chia-I Wube2b9172015-07-03 11:49:42 +0800568 vkCmdCopyBufferToImage(m_cmdbuf.handle(),
Chia-I Wu681d7a02015-07-03 13:44:34 +0800569 buf.handle(),
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800570 m_buffers[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600571 1, &region);
Tony Barbourbd094ce2015-10-23 11:00:15 -0600572
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800573 memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600574 memoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SOURCE_KHR;
575 vkCmdPipelineBarrier(m_cmdbuf.handle(), VK_PIPELINE_STAGE_ALL_GPU_COMMANDS, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
Chia-I Wu53534662015-10-26 17:08:33 +0800576 0, 1, (const void * const*)&pmemory_barrier);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600577 m_cmdbuf.end();
578
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800579 VkCommandBuffer cmdBufs[1];
Chia-I Wube2b9172015-07-03 11:49:42 +0800580 cmdBufs[0] = m_cmdbuf.handle();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600581
Chia-I Wua690b412015-10-29 22:01:53 +0800582 // Wait for the present complete semaphore to be signaled to ensure
583 // that the image won't be rendered to until the presentation
584 // engine has fully released ownership to the application, and it is
585 // okay to render to the image.
Tony Barbour67e99152015-07-10 14:10:27 -0600586 VkFence nullFence = { VK_NULL_HANDLE };
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600587 VkSubmitInfo submit_info;
Chia-I Wuf9be13c2015-10-26 20:37:06 +0800588 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
589 submit_info.pNext = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +0800590 submit_info.waitSemaphoreCount = 1;
Chia-I Wua690b412015-10-29 22:01:53 +0800591 submit_info.pWaitSemaphores = &presentCompleteSemaphore,
Chia-I Wud50a7d72015-10-26 20:48:51 +0800592 submit_info.commandBufferCount = 1;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600593 submit_info.pCommandBuffers = cmdBufs;
Chia-I Wud50a7d72015-10-26 20:48:51 +0800594 submit_info.signalSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600595 submit_info.pSignalSemaphores = NULL;
596
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -0600597 vkQueueSubmit(m_queue.handle(), 1, &submit_info, nullFence);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600598 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700599
Chia-I Wuf7458c52015-10-26 21:10:41 +0800600 vkDestroySemaphore(m_device.handle(), presentCompleteSemaphore, NULL);
Chia-I Wua690b412015-10-29 22:01:53 +0800601
Ian Elliott7e40db92015-08-21 15:09:33 -0600602 VkPresentInfoKHR present = {};
603 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600604 present.pNext = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600605 present.swapchainCount = 1;
606 present.swapchains = & m_swap_chain;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600607 present.imageIndices = &m_current_buffer;
Tony Barbour96db8822015-02-25 12:28:39 -0700608
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600609#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800610 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700611 XCB_PROP_MODE_REPLACE,
612 m_window,
613 XCB_ATOM_WM_NAME,
614 XCB_ATOM_STRING,
615 8,
616 m_display_image->m_title.size(),
617 m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600618#endif
Jon Ashburn07daee72015-05-21 18:13:33 -0600619
Ian Elliott7e40db92015-08-21 15:09:33 -0600620 err = m_fpQueuePresentKHR(m_queue.handle(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700621 assert(!err);
622
623 m_queue.wait();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600624 m_current_buffer = (m_current_buffer + 1) % 2;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600625}
626
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600627#ifdef _WIN32
Tony-LunarG399dfca2015-05-19 14:08:26 -0600628# define PREVIOUSLY_DOWN 1<<29
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600629// MS-Windows event handling function:
630LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
631 UINT uMsg,
632 WPARAM wParam,
633 LPARAM lParam)
634{
635
636 switch(uMsg)
637 {
638 case WM_CLOSE:
639 PostQuitMessage(0);
640 break;
641
642 case WM_PAINT:
643 {
644 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
645 if (me) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600646 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600647 me->Display();
648 }
649 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600650 break;
651
652 case WM_KEYDOWN:
653 {
654 if (lParam & (PREVIOUSLY_DOWN)){
655 break;
656 }
657 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
658 // the window, we put the this pointer into the window's user data so we could get it back now
659 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
660 switch (wParam)
661 {
662 case VK_ESCAPE: me->m_quit = true;
663 break;
664
665 case VK_LEFT: // left arrow key
666 if (me->m_display_image == me->m_images.begin()) {
667 me->m_display_image = --me->m_images.end();
668 }
669 else {
670 --me->m_display_image;
671 }
672 break;
673
674 case VK_RIGHT: // right arrow key
675 ++me->m_display_image;
676 if (me->m_display_image == me->m_images.end()) {
677 me->m_display_image = me->m_images.begin();
678 }
679 break;
680
681 default:
682 break;
683 }
684 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
685 me->Display();
686 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600687 }
688 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
689}
690
691void TestFrameworkVkPresent::Run()
692{
693 MSG msg; // message
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600694
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600695 /* main message loop*/
Tony-LunarG399dfca2015-05-19 14:08:26 -0600696 while(! m_quit) {
697 GetMessage(&msg, m_window, 0, 0);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600698 if (msg.message == WM_QUIT) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600699 m_quit = true; //if found, quit app
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600700 } else {
701 /* Translate and dispatch to event queue*/
702 TranslateMessage(&msg);
703 DispatchMessage(&msg);
704 }
705 }
706}
707
708#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600709void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600710{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600711 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700712 switch (event_code) {
713 case XCB_EXPOSE:
714 Display(); // TODO: handle resize
715 break;
716 case XCB_CLIENT_MESSAGE:
717 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
718 (m_atom_wm_delete_window)->atom) {
719 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600720 }
721 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700722 case XCB_KEY_RELEASE:
723 {
724 const xcb_key_release_event_t *key =
725 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600726
Tony Barbour96db8822015-02-25 12:28:39 -0700727 switch (key->detail) {
728 case 0x9: // Escape
729 m_quit = true;
730 break;
731 case 0x71: // left arrow key
732 if (m_display_image == m_images.begin()) {
733 m_display_image = --m_images.end();
734 } else {
735 --m_display_image;
736 }
737 break;
738 case 0x72: // right arrow key
739 ++m_display_image;
740 if (m_display_image == m_images.end()) {
741 m_display_image = m_images.begin();
742 }
743 break;
744 case 0x41:
745 m_pause = !m_pause;
746 break;
747 }
748 Display();
749 }
750 break;
751 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600752 break;
753 }
Tony Barbour96db8822015-02-25 12:28:39 -0700754}
755
Tony Barbour6918cd52015-04-09 12:58:51 -0600756void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700757{
Chia-I Wuf8693382015-04-16 22:02:10 +0800758 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700759
760 while (! m_quit) {
761 xcb_generic_event_t *event;
762
763 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800764 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700765 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800766 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700767 }
768 if (event) {
769 HandleEvent(event);
770 free(event);
771 }
772 }
773}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600774#endif // _WIN32
Tony Barbour96db8822015-02-25 12:28:39 -0700775
Ian Elliott7e40db92015-08-21 15:09:33 -0600776void TestFrameworkVkPresent::CreateSwapchain()
Tony Barbour96db8822015-02-25 12:28:39 -0700777{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600778 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700779
Tony-LunarG399dfca2015-05-19 14:08:26 -0600780 m_display_image = m_images.begin();
781 m_current_buffer = 0;
782
Tony Barbour6a3faf02015-07-23 10:36:18 -0600783 // Construct the WSI surface description:
Ian Elliott7e40db92015-08-21 15:09:33 -0600784 m_surface_description.sType = VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600785 m_surface_description.pNext = NULL;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600786#ifdef _WIN32
Ian Elliott7e40db92015-08-21 15:09:33 -0600787 m_surface_description.platform = VK_PLATFORM_WIN32_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600788 m_surface_description.pPlatformHandle = m_connection;
789 m_surface_description.pPlatformWindow = m_window;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600790#else // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -0600791 m_platform_handle_xcb.connection = m_connection;
792 m_platform_handle_xcb.root = m_screen->root;
Ian Elliott7e40db92015-08-21 15:09:33 -0600793 m_surface_description.platform = VK_PLATFORM_XCB_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600794 m_surface_description.pPlatformHandle = &m_platform_handle_xcb;
795 m_surface_description.pPlatformWindow = &m_window;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600796#endif // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -0600797
798 // Iterate over each queue to learn whether it supports presenting to WSI:
799 VkBool32 supportsPresent;
800 m_present_queue_node_index = UINT32_MAX;
801 std::vector<vk_testing::Queue *> queues = m_device.graphics_queues();
802 for (int i=0; i < queues.size(); i++)
803 {
804 int family_index = queues[i]->get_family_index();
Ian Elliott7e40db92015-08-21 15:09:33 -0600805 m_fpGetPhysicalDeviceSurfaceSupportKHR(m_device.phy().handle(),
Tony Barbour6a3faf02015-07-23 10:36:18 -0600806 family_index,
Ian Elliott7e40db92015-08-21 15:09:33 -0600807 (VkSurfaceDescriptionKHR *) &m_surface_description,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600808 &supportsPresent);
809 if (supportsPresent) {
810 m_present_queue_node_index = family_index;
811 }
812 }
813
814 assert(m_present_queue_node_index != UINT32_MAX);
815
816
817 // Get the list of VkFormat's that are supported:
Ian Elliott8b139792015-08-07 11:51:12 -0600818 uint32_t formatCount;
Ian Elliott7e40db92015-08-21 15:09:33 -0600819 err = m_fpGetSurfaceFormatsKHR(m_device.handle(),
820 (VkSurfaceDescriptionKHR *) &m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600821 &formatCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600822 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600823 VkSurfaceFormatKHR *surfFormats =
824 (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
825 err = m_fpGetSurfaceFormatsKHR(m_device.handle(),
826 (VkSurfaceDescriptionKHR *) &m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600827 &formatCount, surfFormats);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600828 assert(!err);
829 // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
830 // the surface has no preferred format. Otherwise, at least one
831 // supported format will be returned.
Tony Barbour6a3faf02015-07-23 10:36:18 -0600832 if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED)
833 {
834 m_format = VK_FORMAT_B8G8R8A8_UNORM;
835 }
836 else
837 {
838 assert(formatCount >= 1);
839 m_format = surfFormats[0].format;
840 }
Ian Elliott8b139792015-08-07 11:51:12 -0600841 m_color_space = surfFormats[0].colorSpace;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600842
843 // Check the surface proprties and formats
Ian Elliott7e40db92015-08-21 15:09:33 -0600844 VkSurfacePropertiesKHR surfProperties;
845 err = m_fpGetSurfacePropertiesKHR(m_device.handle(),
846 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600847 &surfProperties);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600848 assert(!err);
849
Ian Elliott8b139792015-08-07 11:51:12 -0600850 uint32_t presentModeCount;
Ian Elliott7e40db92015-08-21 15:09:33 -0600851 err = m_fpGetSurfacePresentModesKHR(m_device.handle(),
852 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600853 &presentModeCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600854 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600855 VkPresentModeKHR *presentModes =
856 (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
Ian Elliott8b139792015-08-07 11:51:12 -0600857 assert(presentModes);
Ian Elliott7e40db92015-08-21 15:09:33 -0600858 err = m_fpGetSurfacePresentModesKHR(m_device.handle(),
859 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600860 &presentModeCount, presentModes);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600861 assert(!err);
862
Ian Elliott7e40db92015-08-21 15:09:33 -0600863 VkExtent2D swapchainExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600864 // width and height are either both -1, or both not -1.
Ian Elliott8b139792015-08-07 11:51:12 -0600865 if (surfProperties.currentExtent.width == -1)
Tony Barbour6a3faf02015-07-23 10:36:18 -0600866 {
867 // If the surface size is undefined, the size is set to
868 // the size of the images requested.
Ian Elliott7e40db92015-08-21 15:09:33 -0600869 swapchainExtent.width = m_width;
870 swapchainExtent.height = m_height;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600871 }
872 else
873 {
874 // If the surface size is defined, the swap chain size must match
Ian Elliott7e40db92015-08-21 15:09:33 -0600875 swapchainExtent = surfProperties.currentExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600876 }
877
878 // If mailbox mode is available, use it, as is the lowest-latency non-
Ian Elliottae0e8242015-08-10 13:20:49 -0600879 // tearing mode. If not, try IMMEDIATE which will usually be available,
880 // and is fastest (though it tears). If not, fall back to FIFO which is
881 // always available.
Ian Elliott7e40db92015-08-21 15:09:33 -0600882 VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600883 for (size_t i = 0; i < presentModeCount; i++) {
Ian Elliott7e40db92015-08-21 15:09:33 -0600884 if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
885 swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600886 break;
887 }
Ian Elliott7e40db92015-08-21 15:09:33 -0600888 if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) &&
889 (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
890 swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
Ian Elliottae0e8242015-08-10 13:20:49 -0600891 }
Tony Barbour6a3faf02015-07-23 10:36:18 -0600892 }
893
894 // Determine the number of VkImage's to use in the swap chain (we desire to
895 // own only 1 image at a time, besides the images being displayed and
896 // queued for display):
Ian Elliott7e40db92015-08-21 15:09:33 -0600897 uint32_t desiredNumberOfSwapchainImages = surfProperties.minImageCount + 1;
Ian Elliott8b139792015-08-07 11:51:12 -0600898 if ((surfProperties.maxImageCount > 0) &&
Ian Elliott7e40db92015-08-21 15:09:33 -0600899 (desiredNumberOfSwapchainImages > surfProperties.maxImageCount))
Tony Barbour6a3faf02015-07-23 10:36:18 -0600900 {
901 // Application must settle for fewer images than desired:
Ian Elliott7e40db92015-08-21 15:09:33 -0600902 desiredNumberOfSwapchainImages = surfProperties.maxImageCount;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600903 }
904
Ian Elliott7e40db92015-08-21 15:09:33 -0600905 VkSurfaceTransformKHR preTransform;
906 if (surfProperties.supportedTransforms & VK_SURFACE_TRANSFORM_NONE_BIT_KHR) {
907 preTransform = VK_SURFACE_TRANSFORM_NONE_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600908 } else {
Ian Elliott8b139792015-08-07 11:51:12 -0600909 preTransform = surfProperties.currentTransform;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600910 }
Ian Elliott1a3845b2015-07-06 14:33:04 -0600911
Cody Northropdf5b0922015-08-28 16:22:48 -0600912 // 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 +0800913 assert((surfProperties.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) != 0);
Cody Northropdf5b0922015-08-28 16:22:48 -0600914
Ian Elliott7e40db92015-08-21 15:09:33 -0600915 VkSwapchainCreateInfoKHR swap_chain = {};
Ian Elliotta257eea2015-09-22 10:20:23 -0600916 swap_chain.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600917 swap_chain.pNext = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600918 swap_chain.pSurfaceDescription = (const VkSurfaceDescriptionKHR *)&m_surface_description;
919 swap_chain.minImageCount = desiredNumberOfSwapchainImages;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600920 swap_chain.imageFormat = m_format;
Ian Elliott8b139792015-08-07 11:51:12 -0600921 swap_chain.imageColorSpace = m_color_space;
Ian Elliott7e40db92015-08-21 15:09:33 -0600922 swap_chain.imageExtent.width = swapchainExtent.width;
923 swap_chain.imageExtent.height = swapchainExtent.height;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800924 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DST_BIT |
Cody Northropdf8f42a2015-08-05 15:38:39 -0600925 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600926 swap_chain.preTransform = preTransform;
Chia-I Wuf8693382015-04-16 22:02:10 +0800927 swap_chain.imageArraySize = 1;
Ian Elliott8b139792015-08-07 11:51:12 -0600928 swap_chain.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
929 swap_chain.queueFamilyCount = 0;
930 swap_chain.pQueueFamilyIndices = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600931 swap_chain.presentMode = swapchainPresentMode;
Chia-I Wue2fc5522015-10-26 20:04:44 +0800932 swap_chain.oldSwapchain = VK_NULL_HANDLE;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600933 swap_chain.clipped = true;
934
935 uint32_t i;
Chia-I Wuf8693382015-04-16 22:02:10 +0800936
Ian Elliott7e40db92015-08-21 15:09:33 -0600937 err = m_fpCreateSwapchainKHR(m_device.handle(), &swap_chain, &m_swap_chain);
Chia-I Wuf8693382015-04-16 22:02:10 +0800938 assert(!err);
939
Ian Elliott7e40db92015-08-21 15:09:33 -0600940 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
941 &m_swapchainImageCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600942 assert(!err);
943
Ian Elliott7e40db92015-08-21 15:09:33 -0600944 VkImage* swapchainImages = (VkImage*)malloc(m_swapchainImageCount * sizeof(VkImage));
945 assert(swapchainImages);
946 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
947 &m_swapchainImageCount, swapchainImages);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600948 assert(!err);
949
Ian Elliott7e40db92015-08-21 15:09:33 -0600950 m_buffers = (SwapchainBuffers*)malloc(sizeof(SwapchainBuffers)*m_swapchainImageCount);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600951 assert(m_buffers);
952
Ian Elliott7e40db92015-08-21 15:09:33 -0600953 for (i = 0; i < m_swapchainImageCount; i++) {
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600954 VkImageViewCreateInfo color_image_view = {};
955 color_image_view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
956 color_image_view.pNext = NULL;
Courtney Goeltzenleuchter00265c82015-09-11 15:22:06 -0600957 color_image_view.viewType = VK_IMAGE_VIEW_TYPE_2D;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600958 color_image_view.format = m_format;
Courtney Goeltzenleuchterba724512015-09-10 17:58:54 -0600959 color_image_view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600960 color_image_view.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800961 color_image_view.subresourceRange.levelCount = 1;
Courtney Goeltzenleuchter4a261892015-09-10 16:38:41 -0600962 color_image_view.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800963 color_image_view.subresourceRange.layerCount = 1;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600964
Ian Elliott7e40db92015-08-21 15:09:33 -0600965 m_buffers[i].image = swapchainImages[i];
Tony Barbour6a3faf02015-07-23 10:36:18 -0600966
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600967 color_image_view.image = m_buffers[i].image;
968 err = vkCreateImageView(m_device.handle(),
Chia-I Wuf7458c52015-10-26 21:10:41 +0800969 &color_image_view, NULL, &m_buffers[i].view);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600970 assert(!err);
Tony Barbourbd094ce2015-10-23 11:00:15 -0600971
972 /* Set image layout to PRESENT_SOURCE_KHR so that before the copy, it can be set to */
973 /* TRANSFER_DESTINATION_OPTIMAL */
974 SetImageLayout(m_buffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT,
975 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SOURCE_KHR);
976
Tony Barbour6a3faf02015-07-23 10:36:18 -0600977 }
Tony Barbour96db8822015-02-25 12:28:39 -0700978}
Tony Barbourbd094ce2015-10-23 11:00:15 -0600979void TestFrameworkVkPresent::SetImageLayout(VkImage image, VkImageAspectFlags aspectMask,
980 VkImageLayout old_image_layout, VkImageLayout new_image_layout)
981{
982 VkResult U_ASSERT_ONLY err;
983
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800984 VkCommandBufferBeginInfo cmd_buf_info = {};
985 cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600986 cmd_buf_info.pNext = NULL;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800987 cmd_buf_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600988 cmd_buf_info.renderPass = { VK_NULL_HANDLE };
989 cmd_buf_info.subpass = 0;
990 cmd_buf_info.framebuffer = { VK_NULL_HANDLE };
991
992 err = vkBeginCommandBuffer(m_cmdbuf.handle(), &cmd_buf_info);
993 assert(!err);
994
995 VkImageMemoryBarrier image_memory_barrier = {};
996 image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
997 image_memory_barrier.pNext = NULL;
Chia-I Wua4594202015-10-27 19:54:37 +0800998 image_memory_barrier.srcAccessMask = 0;
999 image_memory_barrier.dstAccessMask = 0;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001000 image_memory_barrier.oldLayout = old_image_layout;
1001 image_memory_barrier.newLayout = new_image_layout;
1002 image_memory_barrier.image = image;
1003 image_memory_barrier.subresourceRange.aspectMask = aspectMask;
1004 image_memory_barrier.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001005 image_memory_barrier.subresourceRange.levelCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001006 image_memory_barrier.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001007 image_memory_barrier.subresourceRange.layerCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001008
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001009 if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
Tony Barbourbd094ce2015-10-23 11:00:15 -06001010 /* Make sure anything that was copying from this image has completed */
Chia-I Wua4594202015-10-27 19:54:37 +08001011 image_memory_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001012 }
1013
1014 if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
1015 /* Make sure any Copy or CPU writes to image are flushed */
Chia-I Wua4594202015-10-27 19:54:37 +08001016 image_memory_barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001017 }
1018
1019 VkImageMemoryBarrier *pmemory_barrier = &image_memory_barrier;
1020
1021 VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1022 VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1023
Chia-I Wu53534662015-10-26 17:08:33 +08001024 vkCmdPipelineBarrier(m_cmdbuf.handle(), src_stages, dest_stages, 0, 1, (const void * const*)&pmemory_barrier);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001025
1026 err = vkEndCommandBuffer(m_cmdbuf.handle());
1027 assert(!err);
1028
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001029 const VkCommandBuffer cmd_bufs[] = { m_cmdbuf.handle() };
Tony Barbourbd094ce2015-10-23 11:00:15 -06001030 VkFence nullFence = { VK_NULL_HANDLE };
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001031 VkSubmitInfo submit_info;
Chia-I Wuf9be13c2015-10-26 20:37:06 +08001032 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1033 submit_info.pNext = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001034 submit_info.waitSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001035 submit_info.pWaitSemaphores = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001036 submit_info.commandBufferCount = 1;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001037 submit_info.pCommandBuffers = cmd_bufs;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001038 submit_info.signalSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001039 submit_info.pSignalSemaphores = NULL;
1040
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -06001041 err = vkQueueSubmit(m_queue.handle(), 1, &submit_info, nullFence);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001042 assert(!err);
1043
1044 err = vkQueueWaitIdle(m_queue.handle());
1045 assert(!err);
1046
1047}
Tony Barbour96db8822015-02-25 12:28:39 -07001048
Jon Ashburn07daee72015-05-21 18:13:33 -06001049void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -07001050{
Ian Elliott7e40db92015-08-21 15:09:33 -06001051 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceSupportKHR);
1052 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfacePropertiesKHR);
1053 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfaceFormatsKHR);
1054 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfacePresentModesKHR);
1055 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1056 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1057 GET_DEVICE_PROC_ADDR(m_device.handle(), DestroySwapchainKHR);
1058 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSwapchainImagesKHR);
1059 GET_DEVICE_PROC_ADDR(m_device.handle(), AcquireNextImageKHR);
1060 GET_DEVICE_PROC_ADDR(m_device.handle(), QueuePresentKHR);
Jon Ashburn07daee72015-05-21 18:13:33 -06001061
Tony Barbour96db8822015-02-25 12:28:39 -07001062 m_images = imagesIn;
1063}
1064
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001065#ifdef _WIN32
1066void TestFrameworkVkPresent::CreateMyWindow()
1067{
1068 WNDCLASSEX win_class;
1069 // const ::testing::TestInfo* const test_info =
1070 // ::testing::UnitTest::GetInstance()->current_test_info();
1071 m_connection = GetModuleHandle(NULL);
1072
1073 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1074 it != m_images.end(); it++) {
1075 if (m_width < it->m_width)
1076 m_width = it->m_width;
1077 if (m_height < it->m_height)
1078 m_height = it->m_height;
1079 }
1080 // Initialize the window class structure:
1081 win_class.cbSize = sizeof(WNDCLASSEX);
1082 win_class.style = CS_HREDRAW | CS_VREDRAW;
1083 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
1084 win_class.cbClsExtra = 0;
1085 win_class.cbWndExtra = 0;
1086 win_class.hInstance = m_connection; // hInstance
1087 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
1088 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
1089 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
1090 win_class.lpszMenuName = NULL;
1091 win_class.lpszClassName = "Test";
1092 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
1093 // Register window class:
1094 if (!RegisterClassEx(&win_class)) {
1095 // It didn't work, so try to give a useful error:
1096 printf("Unexpected error trying to start the application!\n");
1097 fflush(stdout);
1098 exit(1);
1099 }
1100 // Create window with the registered class:
Cody Northrop39582252015-08-05 15:39:31 -06001101 RECT wr = { 0, 0, m_width, m_height };
1102 AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001103 m_window = CreateWindowEx(0,
1104 "Test", // class name
1105 "Test", // app name
1106 WS_OVERLAPPEDWINDOW | // window style
1107 WS_VISIBLE |
1108 WS_SYSMENU,
1109 100,100, // x/y coords
Cody Northrop39582252015-08-05 15:39:31 -06001110 wr.right - wr.left, // width
1111 wr.bottom - wr.top, // height
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001112 NULL, // handle to parent
1113 NULL, // handle to menu
1114 m_connection, // hInstance
1115 NULL); // no extra parameters
1116
1117 if (!m_window) {
1118 // It didn't work, so try to give a useful error:
1119 DWORD error = GetLastError();
1120 char message[120];
1121 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
1122 MessageBox(NULL, message, "Error", MB_OK);
1123 exit(1);
1124 }
Tony-LunarG399dfca2015-05-19 14:08:26 -06001125 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
1126 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001127}
1128#else
Tony Barbour6918cd52015-04-09 12:58:51 -06001129void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -07001130{
Chia-I Wuf8693382015-04-16 22:02:10 +08001131 const xcb_setup_t *setup;
1132 xcb_screen_iterator_t iter;
1133 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -07001134 uint32_t value_mask, value_list[32];
1135
Chia-I Wuf8693382015-04-16 22:02:10 +08001136 m_connection = xcb_connect(NULL, &scr);
1137
1138 setup = xcb_get_setup(m_connection);
1139 iter = xcb_setup_roots_iterator(setup);
1140 while (scr-- > 0)
1141 xcb_screen_next(&iter);
1142
1143 m_screen = iter.data;
1144
1145 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1146 it != m_images.end(); it++) {
1147 if (m_width < it->m_width)
1148 m_width = it->m_width;
1149 if (m_height < it->m_height)
1150 m_height = it->m_height;
1151 }
1152
1153 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -07001154
1155 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +08001156 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -07001157 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
1158 XCB_EVENT_MASK_EXPOSURE |
1159 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
1160
Chia-I Wuf8693382015-04-16 22:02:10 +08001161 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -07001162 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001163 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -07001164 0, 0, m_width, m_height, 0,
1165 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001166 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -07001167 value_mask, value_list);
1168
1169 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +08001170 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -07001171 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +08001172 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001173
Chia-I Wuf8693382015-04-16 22:02:10 +08001174 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
1175 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001176
Chia-I Wuf8693382015-04-16 22:02:10 +08001177 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -07001178 m_window, (*reply).atom, 4, 32, 1,
1179 &(*m_atom_wm_delete_window).atom);
1180 free(reply);
1181
Chia-I Wuf8693382015-04-16 22:02:10 +08001182 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -07001183}
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001184#endif
Tony Barbour96db8822015-02-25 12:28:39 -07001185
Tony Barbour6918cd52015-04-09 12:58:51 -06001186void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -07001187{
Ian Elliott7e40db92015-08-21 15:09:33 -06001188 m_fpDestroySwapchainKHR(m_device.handle(), m_swap_chain);
Tony Barbour9226a822015-10-23 10:58:56 -06001189
1190 for (uint32_t i = 0; i < m_swapchainImageCount; i++) {
Chia-I Wuf7458c52015-10-26 21:10:41 +08001191 vkDestroyImageView(m_device.handle(), m_buffers[i].view, NULL);
Tony Barbour9226a822015-10-23 10:58:56 -06001192 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001193#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +08001194 xcb_destroy_window(m_connection, m_window);
1195 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001196#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001197}
1198
Tony Barbour6918cd52015-04-09 12:58:51 -06001199void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001200{
1201 if (m_images.size() == 0) return;
1202
Chia-I Wuf8693382015-04-16 22:02:10 +08001203 vk_testing::Environment env;
1204 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -07001205 {
Chia-I Wuf8693382015-04-16 22:02:10 +08001206 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -07001207
Jon Ashburn07daee72015-05-21 18:13:33 -06001208 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001209 vkPresent.CreateMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -06001210 vkPresent.CreateSwapchain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001211 vkPresent.Run();
1212 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -07001213 }
Chia-I Wuf8693382015-04-16 22:02:10 +08001214 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001215}
1216
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001217//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001218// These are the default resources for TBuiltInResources, used for both
1219// - parsing this string for the case where the user didn't supply one
1220// - dumping out a template for user construction of a config file
1221//
1222static const char* DefaultConfig =
1223 "MaxLights 32\n"
1224 "MaxClipPlanes 6\n"
1225 "MaxTextureUnits 32\n"
1226 "MaxTextureCoords 32\n"
1227 "MaxVertexAttribs 64\n"
1228 "MaxVertexUniformComponents 4096\n"
1229 "MaxVaryingFloats 64\n"
1230 "MaxVertexTextureImageUnits 32\n"
1231 "MaxCombinedTextureImageUnits 80\n"
1232 "MaxTextureImageUnits 32\n"
1233 "MaxFragmentUniformComponents 4096\n"
1234 "MaxDrawBuffers 32\n"
1235 "MaxVertexUniformVectors 128\n"
1236 "MaxVaryingVectors 8\n"
1237 "MaxFragmentUniformVectors 16\n"
1238 "MaxVertexOutputVectors 16\n"
1239 "MaxFragmentInputVectors 15\n"
1240 "MinProgramTexelOffset -8\n"
1241 "MaxProgramTexelOffset 7\n"
1242 "MaxClipDistances 8\n"
1243 "MaxComputeWorkGroupCountX 65535\n"
1244 "MaxComputeWorkGroupCountY 65535\n"
1245 "MaxComputeWorkGroupCountZ 65535\n"
1246 "MaxComputeWorkGroupSizeX 1024\n"
1247 "MaxComputeWorkGroupSizeY 1024\n"
1248 "MaxComputeWorkGroupSizeZ 64\n"
1249 "MaxComputeUniformComponents 1024\n"
1250 "MaxComputeTextureImageUnits 16\n"
1251 "MaxComputeImageUniforms 8\n"
1252 "MaxComputeAtomicCounters 8\n"
1253 "MaxComputeAtomicCounterBuffers 1\n"
1254 "MaxVaryingComponents 60\n"
1255 "MaxVertexOutputComponents 64\n"
1256 "MaxGeometryInputComponents 64\n"
1257 "MaxGeometryOutputComponents 128\n"
1258 "MaxFragmentInputComponents 128\n"
1259 "MaxImageUnits 8\n"
1260 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
1261 "MaxCombinedShaderOutputResources 8\n"
1262 "MaxImageSamples 0\n"
1263 "MaxVertexImageUniforms 0\n"
1264 "MaxTessControlImageUniforms 0\n"
1265 "MaxTessEvaluationImageUniforms 0\n"
1266 "MaxGeometryImageUniforms 0\n"
1267 "MaxFragmentImageUniforms 8\n"
1268 "MaxCombinedImageUniforms 8\n"
1269 "MaxGeometryTextureImageUnits 16\n"
1270 "MaxGeometryOutputVertices 256\n"
1271 "MaxGeometryTotalOutputComponents 1024\n"
1272 "MaxGeometryUniformComponents 1024\n"
1273 "MaxGeometryVaryingComponents 64\n"
1274 "MaxTessControlInputComponents 128\n"
1275 "MaxTessControlOutputComponents 128\n"
1276 "MaxTessControlTextureImageUnits 16\n"
1277 "MaxTessControlUniformComponents 1024\n"
1278 "MaxTessControlTotalOutputComponents 4096\n"
1279 "MaxTessEvaluationInputComponents 128\n"
1280 "MaxTessEvaluationOutputComponents 128\n"
1281 "MaxTessEvaluationTextureImageUnits 16\n"
1282 "MaxTessEvaluationUniformComponents 1024\n"
1283 "MaxTessPatchComponents 120\n"
1284 "MaxPatchVertices 32\n"
1285 "MaxTessGenLevel 64\n"
1286 "MaxViewports 16\n"
1287 "MaxVertexAtomicCounters 0\n"
1288 "MaxTessControlAtomicCounters 0\n"
1289 "MaxTessEvaluationAtomicCounters 0\n"
1290 "MaxGeometryAtomicCounters 0\n"
1291 "MaxFragmentAtomicCounters 8\n"
1292 "MaxCombinedAtomicCounters 8\n"
1293 "MaxAtomicCounterBindings 1\n"
1294 "MaxVertexAtomicCounterBuffers 0\n"
1295 "MaxTessControlAtomicCounterBuffers 0\n"
1296 "MaxTessEvaluationAtomicCounterBuffers 0\n"
1297 "MaxGeometryAtomicCounterBuffers 0\n"
1298 "MaxFragmentAtomicCounterBuffers 1\n"
1299 "MaxCombinedAtomicCounterBuffers 1\n"
1300 "MaxAtomicCounterBufferSize 16384\n"
1301 "MaxTransformFeedbackBuffers 4\n"
1302 "MaxTransformFeedbackInterleavedComponents 64\n"
1303 "MaxCullDistances 8\n"
1304 "MaxCombinedClipAndCullDistances 8\n"
1305 "MaxSamples 4\n"
1306
1307 "nonInductiveForLoops 1\n"
1308 "whileLoops 1\n"
1309 "doWhileLoops 1\n"
1310 "generalUniformIndexing 1\n"
1311 "generalAttributeMatrixVectorIndexing 1\n"
1312 "generalVaryingIndexing 1\n"
1313 "generalSamplerIndexing 1\n"
1314 "generalVariableIndexing 1\n"
1315 "generalConstantMatrixVectorIndexing 1\n"
1316 ;
1317
1318//
1319// *.conf => this is a config file that can set limits/resources
1320//
Tony Barbour6918cd52015-04-09 12:58:51 -06001321bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001322{
1323 if (name.size() < 5)
1324 return false;
1325
1326 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
1327 ConfigFile = name;
1328 return true;
1329 }
1330
1331 return false;
1332}
1333
1334//
1335// Parse either a .conf file provided by the user or the default string above.
1336//
Tony Barbour6918cd52015-04-09 12:58:51 -06001337void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001338{
1339 char** configStrings = 0;
1340 char* config = 0;
1341 if (ConfigFile.size() > 0) {
1342 configStrings = ReadFileData(ConfigFile.c_str());
1343 if (configStrings)
1344 config = *configStrings;
1345 else {
1346 printf("Error opening configuration file; will instead use the default configuration\n");
1347 }
1348 }
1349
1350 if (config == 0) {
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001351 config = (char *) alloca(strlen(DefaultConfig) + 1);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001352 strcpy(config, DefaultConfig);
1353 }
1354
1355 const char* delims = " \t\n\r";
1356 const char* token = strtok(config, delims);
1357 while (token) {
1358 const char* valueStr = strtok(0, delims);
1359 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1360 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1361 return;
1362 }
1363 int value = atoi(valueStr);
1364
1365 if (strcmp(token, "MaxLights") == 0)
1366 Resources.maxLights = value;
1367 else if (strcmp(token, "MaxClipPlanes") == 0)
1368 Resources.maxClipPlanes = value;
1369 else if (strcmp(token, "MaxTextureUnits") == 0)
1370 Resources.maxTextureUnits = value;
1371 else if (strcmp(token, "MaxTextureCoords") == 0)
1372 Resources.maxTextureCoords = value;
1373 else if (strcmp(token, "MaxVertexAttribs") == 0)
1374 Resources.maxVertexAttribs = value;
1375 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1376 Resources.maxVertexUniformComponents = value;
1377 else if (strcmp(token, "MaxVaryingFloats") == 0)
1378 Resources.maxVaryingFloats = value;
1379 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1380 Resources.maxVertexTextureImageUnits = value;
1381 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1382 Resources.maxCombinedTextureImageUnits = value;
1383 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1384 Resources.maxTextureImageUnits = value;
1385 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1386 Resources.maxFragmentUniformComponents = value;
1387 else if (strcmp(token, "MaxDrawBuffers") == 0)
1388 Resources.maxDrawBuffers = value;
1389 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1390 Resources.maxVertexUniformVectors = value;
1391 else if (strcmp(token, "MaxVaryingVectors") == 0)
1392 Resources.maxVaryingVectors = value;
1393 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1394 Resources.maxFragmentUniformVectors = value;
1395 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1396 Resources.maxVertexOutputVectors = value;
1397 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1398 Resources.maxFragmentInputVectors = value;
1399 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1400 Resources.minProgramTexelOffset = value;
1401 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1402 Resources.maxProgramTexelOffset = value;
1403 else if (strcmp(token, "MaxClipDistances") == 0)
1404 Resources.maxClipDistances = value;
1405 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1406 Resources.maxComputeWorkGroupCountX = value;
1407 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1408 Resources.maxComputeWorkGroupCountY = value;
1409 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1410 Resources.maxComputeWorkGroupCountZ = value;
1411 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1412 Resources.maxComputeWorkGroupSizeX = value;
1413 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1414 Resources.maxComputeWorkGroupSizeY = value;
1415 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1416 Resources.maxComputeWorkGroupSizeZ = value;
1417 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1418 Resources.maxComputeUniformComponents = value;
1419 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1420 Resources.maxComputeTextureImageUnits = value;
1421 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1422 Resources.maxComputeImageUniforms = value;
1423 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1424 Resources.maxComputeAtomicCounters = value;
1425 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1426 Resources.maxComputeAtomicCounterBuffers = value;
1427 else if (strcmp(token, "MaxVaryingComponents") == 0)
1428 Resources.maxVaryingComponents = value;
1429 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1430 Resources.maxVertexOutputComponents = value;
1431 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1432 Resources.maxGeometryInputComponents = value;
1433 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1434 Resources.maxGeometryOutputComponents = value;
1435 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1436 Resources.maxFragmentInputComponents = value;
1437 else if (strcmp(token, "MaxImageUnits") == 0)
1438 Resources.maxImageUnits = value;
1439 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1440 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1441 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1442 Resources.maxCombinedShaderOutputResources = value;
1443 else if (strcmp(token, "MaxImageSamples") == 0)
1444 Resources.maxImageSamples = value;
1445 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1446 Resources.maxVertexImageUniforms = value;
1447 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1448 Resources.maxTessControlImageUniforms = value;
1449 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1450 Resources.maxTessEvaluationImageUniforms = value;
1451 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1452 Resources.maxGeometryImageUniforms = value;
1453 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1454 Resources.maxFragmentImageUniforms = value;
1455 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1456 Resources.maxCombinedImageUniforms = value;
1457 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1458 Resources.maxGeometryTextureImageUnits = value;
1459 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1460 Resources.maxGeometryOutputVertices = value;
1461 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1462 Resources.maxGeometryTotalOutputComponents = value;
1463 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1464 Resources.maxGeometryUniformComponents = value;
1465 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1466 Resources.maxGeometryVaryingComponents = value;
1467 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1468 Resources.maxTessControlInputComponents = value;
1469 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1470 Resources.maxTessControlOutputComponents = value;
1471 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1472 Resources.maxTessControlTextureImageUnits = value;
1473 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1474 Resources.maxTessControlUniformComponents = value;
1475 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1476 Resources.maxTessControlTotalOutputComponents = value;
1477 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1478 Resources.maxTessEvaluationInputComponents = value;
1479 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1480 Resources.maxTessEvaluationOutputComponents = value;
1481 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1482 Resources.maxTessEvaluationTextureImageUnits = value;
1483 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1484 Resources.maxTessEvaluationUniformComponents = value;
1485 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1486 Resources.maxTessPatchComponents = value;
1487 else if (strcmp(token, "MaxPatchVertices") == 0)
1488 Resources.maxPatchVertices = value;
1489 else if (strcmp(token, "MaxTessGenLevel") == 0)
1490 Resources.maxTessGenLevel = value;
1491 else if (strcmp(token, "MaxViewports") == 0)
1492 Resources.maxViewports = value;
1493 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1494 Resources.maxVertexAtomicCounters = value;
1495 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1496 Resources.maxTessControlAtomicCounters = value;
1497 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1498 Resources.maxTessEvaluationAtomicCounters = value;
1499 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1500 Resources.maxGeometryAtomicCounters = value;
1501 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1502 Resources.maxFragmentAtomicCounters = value;
1503 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1504 Resources.maxCombinedAtomicCounters = value;
1505 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1506 Resources.maxAtomicCounterBindings = value;
1507 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1508 Resources.maxVertexAtomicCounterBuffers = value;
1509 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1510 Resources.maxTessControlAtomicCounterBuffers = value;
1511 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1512 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1513 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1514 Resources.maxGeometryAtomicCounterBuffers = value;
1515 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1516 Resources.maxFragmentAtomicCounterBuffers = value;
1517 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1518 Resources.maxCombinedAtomicCounterBuffers = value;
1519 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1520 Resources.maxAtomicCounterBufferSize = value;
1521 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1522 Resources.maxTransformFeedbackBuffers = value;
1523 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1524 Resources.maxTransformFeedbackInterleavedComponents = value;
1525 else if (strcmp(token, "MaxCullDistances") == 0)
1526 Resources.maxCullDistances = value;
1527 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1528 Resources.maxCombinedClipAndCullDistances = value;
1529 else if (strcmp(token, "MaxSamples") == 0)
1530 Resources.maxSamples = value;
1531
1532 else if (strcmp(token, "nonInductiveForLoops") == 0)
1533 Resources.limits.nonInductiveForLoops = (value != 0);
1534 else if (strcmp(token, "whileLoops") == 0)
1535 Resources.limits.whileLoops = (value != 0);
1536 else if (strcmp(token, "doWhileLoops") == 0)
1537 Resources.limits.doWhileLoops = (value != 0);
1538 else if (strcmp(token, "generalUniformIndexing") == 0)
1539 Resources.limits.generalUniformIndexing = (value != 0);
1540 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1541 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1542 else if (strcmp(token, "generalVaryingIndexing") == 0)
1543 Resources.limits.generalVaryingIndexing = (value != 0);
1544 else if (strcmp(token, "generalSamplerIndexing") == 0)
1545 Resources.limits.generalSamplerIndexing = (value != 0);
1546 else if (strcmp(token, "generalVariableIndexing") == 0)
1547 Resources.limits.generalVariableIndexing = (value != 0);
1548 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1549 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1550 else
1551 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1552
1553 token = strtok(0, delims);
1554 }
1555 if (configStrings)
1556 FreeFileData(configStrings);
1557}
1558
Tony Barbour6918cd52015-04-09 12:58:51 -06001559void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001560{
1561 if (m_compile_options & EOptionRelaxedErrors)
1562 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1563 if (m_compile_options & EOptionIntermediate)
1564 messages = (EShMessages)(messages | EShMsgAST);
1565 if (m_compile_options & EOptionSuppressWarnings)
1566 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1567}
1568
1569//
1570// Malloc a string of sufficient size and read a string into it.
1571//
Tony Barbour6918cd52015-04-09 12:58:51 -06001572char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001573{
1574 FILE *in;
1575 #if defined(_WIN32) && defined(__GNUC__)
1576 in = fopen(fileName, "r");
1577 int errorCode = in ? 0 : 1;
1578 #else
1579 int errorCode = fopen_s(&in, fileName, "r");
1580 #endif
1581
1582 char *fdata;
1583 int count = 0;
1584 const int maxSourceStrings = 5;
1585 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1586
1587 if (errorCode) {
1588 printf("Error: unable to open input file: %s\n", fileName);
1589 return 0;
1590 }
1591
1592 while (fgetc(in) != EOF)
1593 count++;
1594
1595 fseek(in, 0, SEEK_SET);
1596
1597 if (!(fdata = (char*)malloc(count+2))) {
1598 printf("Error allocating memory\n");
1599 return 0;
1600 }
1601 if (fread(fdata,1,count, in)!=count) {
1602 printf("Error reading input file: %s\n", fileName);
1603 return 0;
1604 }
1605 fdata[count] = '\0';
1606 fclose(in);
1607 if (count == 0) {
1608 return_data[0]=(char*)malloc(count+2);
1609 return_data[0][0]='\0';
1610 m_num_shader_strings = 0;
1611 return return_data;
1612 } else
1613 m_num_shader_strings = 1;
1614
1615 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1616 int ptr_len=0,i=0;
1617 while(count>0){
1618 return_data[i]=(char*)malloc(len+2);
1619 memcpy(return_data[i],fdata+ptr_len,len);
1620 return_data[i][len]='\0';
1621 count-=(len);
1622 ptr_len+=(len);
1623 if(count<len){
1624 if(count==0){
1625 m_num_shader_strings=(i+1);
1626 break;
1627 }
1628 len = count;
1629 }
1630 ++i;
1631 }
1632 return return_data;
1633}
1634
Tony Barbour6918cd52015-04-09 12:58:51 -06001635void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001636{
1637 for(int i=0;i<m_num_shader_strings;i++)
1638 free(data[i]);
1639}
1640
1641//
1642// Deduce the language from the filename. Files must end in one of the
1643// following extensions:
1644//
1645// .vert = vertex
1646// .tesc = tessellation control
1647// .tese = tessellation evaluation
1648// .geom = geometry
1649// .frag = fragment
1650// .comp = compute
1651//
Tony Barbour6918cd52015-04-09 12:58:51 -06001652EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001653{
1654 size_t ext = name.rfind('.');
1655 if (ext == std::string::npos) {
1656 return EShLangVertex;
1657 }
1658
1659 std::string suffix = name.substr(ext + 1, std::string::npos);
1660 if (suffix == "vert")
1661 return EShLangVertex;
1662 else if (suffix == "tesc")
1663 return EShLangTessControl;
1664 else if (suffix == "tese")
1665 return EShLangTessEvaluation;
1666 else if (suffix == "geom")
1667 return EShLangGeometry;
1668 else if (suffix == "frag")
1669 return EShLangFragment;
1670 else if (suffix == "comp")
1671 return EShLangCompute;
1672
1673 return EShLangVertex;
1674}
1675
1676//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001677// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001678//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001679EShLanguage VkTestFramework::FindLanguage(const VkShaderStageFlagBits shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001680{
1681 switch (shader_type) {
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001682 case VK_SHADER_STAGE_VERTEX_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001683 return EShLangVertex;
1684
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001685 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001686 return EShLangTessControl;
1687
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001688 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001689 return EShLangTessEvaluation;
1690
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001691 case VK_SHADER_STAGE_GEOMETRY_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001692 return EShLangGeometry;
1693
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001694 case VK_SHADER_STAGE_FRAGMENT_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001695 return EShLangFragment;
1696
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001697 case VK_SHADER_STAGE_COMPUTE_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001698 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001699
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001700 default:
1701 return EShLangVertex;
1702 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001703}
1704
1705
1706//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001707// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001708// Return value of false means an error was encountered.
1709//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001710bool VkTestFramework::GLSLtoSPV(const VkShaderStageFlagBits shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001711 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001712 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001713{
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001714 glslang::TProgram program;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001715 const char *shaderStrings[1];
1716
1717 // TODO: Do we want to load a special config file depending on the
1718 // shader source? Optional name maybe?
1719 // SetConfigFile(fileName);
1720
1721 ProcessConfigFile();
1722
1723 EShMessages messages = EShMsgDefault;
1724 SetMessageOptions(messages);
1725
1726 EShLanguage stage = FindLanguage(shader_type);
1727 glslang::TShader* shader = new glslang::TShader(stage);
1728
1729 shaderStrings[0] = pshader;
1730 shader->setStrings(shaderStrings, 1);
1731
1732 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1733
Cody Northrop195d6622014-11-03 12:54:37 -07001734 if (! (m_compile_options & EOptionSuppressInfolog)) {
1735 puts(shader->getInfoLog());
1736 puts(shader->getInfoDebugLog());
1737 }
1738
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001739 return false; // something didn't work
1740 }
1741
1742 program.addShader(shader);
1743
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001744
1745 //
1746 // Program-level processing...
1747 //
1748
Cody Northrop195d6622014-11-03 12:54:37 -07001749 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001750
Cody Northrop195d6622014-11-03 12:54:37 -07001751 if (! (m_compile_options & EOptionSuppressInfolog)) {
1752 puts(shader->getInfoLog());
1753 puts(shader->getInfoDebugLog());
1754 }
1755
1756 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001757 }
1758
1759 if (m_compile_options & EOptionDumpReflection) {
1760 program.buildReflection();
1761 program.dumpReflection();
1762 }
1763
Cody Northrop5a95b472015-06-03 13:01:54 -06001764 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1765
1766 //
1767 // Test the different modes of SPIR-V modification
1768 //
1769 if (this->m_canonicalize_spv) {
1770 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1771 }
1772
1773 if (this->m_strip_spv) {
1774 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1775 }
1776
1777 if (this->m_do_everything_spv) {
1778 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1779 }
1780
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001781 delete shader;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001782
1783 return true;
1784}
1785
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001786
1787
Tony Barbour6918cd52015-04-09 12:58:51 -06001788VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001789 m_width( 0 ),
1790 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001791 m_data( NULL ),
1792 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001793{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001794}
1795
Tony Barbour6918cd52015-04-09 12:58:51 -06001796VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001797{
1798
1799}
1800
Tony Barbour6918cd52015-04-09 12:58:51 -06001801VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001802{
1803 m_title = copyin.m_title;
1804 m_width = copyin.m_width;
1805 m_height = copyin.m_height;
1806 m_data_size = copyin.m_data_size;
1807 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1808}
1809
Tony Barbour6918cd52015-04-09 12:58:51 -06001810ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001811{
Tony Barbour6918cd52015-04-09 12:58:51 -06001812 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1813 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001814 return output;
1815}
1816
Tony Barbour6918cd52015-04-09 12:58:51 -06001817VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001818{
1819 m_title = rhs.m_title;
1820 m_width = rhs.m_width;
1821 m_height = rhs.m_height;
1822 m_data_size = rhs.m_data_size;
1823 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001824 return *this;
1825}
1826
Tony Barbour6918cd52015-04-09 12:58:51 -06001827int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001828{
1829 if( this->m_data != rhs.m_data) return 0;
1830 return 1;
1831}
1832
1833// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001834int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001835{
1836 if( this->m_data_size < rhs.m_data_size ) return 1;
1837 return 0;
1838}
1839