blob: 77fa84d22a7ec0d9db6c2426ada4f116e77c05f8 [file] [log] [blame]
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001//
Courtney Goeltzenleuchterfcbe16f2015-10-29 13:50:34 -06002// Copyright (C) 2015 Valve Corporation
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06003//
4// Permission is hereby granted, free of charge, to any person obtaining a
5// copy of this software and associated documentation files (the "Software"),
6// to deal in the Software without restriction, including without limitation
7// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8// and/or sell copies of the Software, and to permit persons to whom the
9// Software is furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included
12// in all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060021//
22// Author: Chia-I Wu <olv@lunarg.com>
23// Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
24// Author: Tony Barbour <tony@LunarG.com>
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -060025
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060026#include "vktestframework.h"
27#include "vkrenderframework.h"
Jon Ashburn94207e92015-12-04 17:03:59 -070028//TODO FIXME remove this once glslang doesn't define this
29#undef BadValue
Cody Northrop5a95b472015-06-03 13:01:54 -060030#include "SPIRV/GlslangToSpv.h"
31#include "SPIRV/SPVRemapper.h"
Tony Barbour4ab45422014-12-10 17:00:20 -070032#include <limits.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060033#include <math.h>
Chia-I Wuec664fa2014-12-02 11:54:24 +080034#include <wand/MagickWand.h>
Jon Ashburn94207e92015-12-04 17:03:59 -070035
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060036
Tony Barbour3d69c9e2015-05-20 16:53:31 -060037#if defined(PATH_MAX) && !defined(MAX_PATH)
38#define MAX_PATH PATH_MAX
39#endif
40
Tony Barbour6a3faf02015-07-23 10:36:18 -060041#ifdef _WIN32
42#define ERR_EXIT(err_msg, err_class) \
43 do { \
44 MessageBox(NULL, err_msg, err_class, MB_OK); \
45 exit(1); \
46 } while (0)
47#else // _WIN32
48
49#define ERR_EXIT(err_msg, err_class) \
50 do { \
51 printf(err_msg); \
52 fflush(stdout); \
53 exit(1); \
54 } while (0)
55#endif // _WIN32
56
57#define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \
58{ \
59 m_fp##entrypoint = (PFN_vk##entrypoint) vkGetInstanceProcAddr(inst, "vk"#entrypoint); \
60 if (m_fp##entrypoint == NULL) { \
61 ERR_EXIT("vkGetInstanceProcAddr failed to find vk"#entrypoint, \
62 "vkGetInstanceProcAddr Failure"); \
63 } \
64}
65
66#define GET_DEVICE_PROC_ADDR(dev, entrypoint) \
67{ \
68 m_fp##entrypoint = (PFN_vk##entrypoint) vkGetDeviceProcAddr(dev, "vk"#entrypoint); \
69 if (m_fp##entrypoint == NULL) { \
70 ERR_EXIT("vkGetDeviceProcAddr failed to find vk"#entrypoint, \
71 "vkGetDeviceProcAddr Failure"); \
72 } \
73}
74
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060075// Command-line options
76enum TOptions {
77 EOptionNone = 0x000,
78 EOptionIntermediate = 0x001,
79 EOptionSuppressInfolog = 0x002,
80 EOptionMemoryLeakMode = 0x004,
81 EOptionRelaxedErrors = 0x008,
82 EOptionGiveWarnings = 0x010,
83 EOptionLinkProgram = 0x020,
84 EOptionMultiThreaded = 0x040,
85 EOptionDumpConfig = 0x080,
86 EOptionDumpReflection = 0x100,
87 EOptionSuppressWarnings = 0x200,
88 EOptionDumpVersions = 0x400,
Cody Northrop3bfd27c2015-03-17 15:55:58 -060089 EOptionSpv = 0x800,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060090 EOptionDefaultDesktop = 0x1000,
91};
92
Ian Elliott7e40db92015-08-21 15:09:33 -060093typedef struct _SwapchainBuffers {
Tony Barbour6a3faf02015-07-23 10:36:18 -060094 VkImage image;
Chia-I Wu3432a0c2015-10-27 18:04:07 +080095 VkCommandBuffer cmd;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -060096 VkImageView view;
Ian Elliott7e40db92015-08-21 15:09:33 -060097} SwapchainBuffers;
Tony Barbour6a3faf02015-07-23 10:36:18 -060098
Chia-I Wuf8693382015-04-16 22:02:10 +080099class TestFrameworkVkPresent
100{
101public:
102 TestFrameworkVkPresent(vk_testing::Device &device);
103
104 void Run();
Jon Ashburn07daee72015-05-21 18:13:33 -0600105 void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst);
Chia-I Wuf8693382015-04-16 22:02:10 +0800106 void CreateMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -0600107 void CreateSwapchain();
Tony Barbourbd094ce2015-10-23 11:00:15 -0600108 void SetImageLayout(VkImage image, VkImageAspectFlags aspectMask,
109 VkImageLayout old_image_layout, VkImageLayout new_image_layout);
Chia-I Wuf8693382015-04-16 22:02:10 +0800110 void TearDown();
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600111#ifdef _WIN32
112 static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
113#endif
114
Chia-I Wuf8693382015-04-16 22:02:10 +0800115
116protected:
117 vk_testing::Device &m_device;
118 vk_testing::Queue &m_queue;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800119 vk_testing::CommandPool m_cmdpool;
120 vk_testing::CommandBuffer m_cmdbuf;
Chia-I Wuf8693382015-04-16 22:02:10 +0800121
122private:
Ian Elliottc11750d2015-10-30 13:24:12 -0600123 VkInstance m_instance;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600124#ifdef _WIN32
125 HINSTANCE m_connection; // hInstance - Windows Instance
126 HWND m_window; // hWnd - window handle
127
128#else
Chia-I Wuf8693382015-04-16 22:02:10 +0800129 xcb_connection_t *m_connection;
130 xcb_screen_t *m_screen;
131 xcb_window_t m_window;
132 xcb_intern_atom_reply_t *m_atom_wm_delete_window;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600133#endif
Ian Elliottc11750d2015-10-30 13:24:12 -0600134 VkSurfaceKHR m_surface;
Courtney Goeltzenleuchterd6079ec2015-04-22 10:09:35 -0600135 std::list<VkTestImageRecord> m_images;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600136 uint32_t m_present_queue_node_index;
Chia-I Wuf8693382015-04-16 22:02:10 +0800137
Ian Elliott7e40db92015-08-21 15:09:33 -0600138 PFN_vkGetPhysicalDeviceSurfaceSupportKHR m_fpGetPhysicalDeviceSurfaceSupportKHR;
Ian Elliottc11750d2015-10-30 13:24:12 -0600139 PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR m_fpGetPhysicalDeviceSurfaceCapabilitiesKHR;
140 PFN_vkGetPhysicalDeviceSurfaceFormatsKHR m_fpGetPhysicalDeviceSurfaceFormatsKHR;
141 PFN_vkGetPhysicalDeviceSurfacePresentModesKHR m_fpGetPhysicalDeviceSurfacePresentModesKHR;
Ian Elliott7e40db92015-08-21 15:09:33 -0600142 PFN_vkCreateSwapchainKHR m_fpCreateSwapchainKHR;
143 PFN_vkDestroySwapchainKHR m_fpDestroySwapchainKHR;
144 PFN_vkGetSwapchainImagesKHR m_fpGetSwapchainImagesKHR;
145 PFN_vkAcquireNextImageKHR m_fpAcquireNextImageKHR;
146 PFN_vkQueuePresentKHR m_fpQueuePresentKHR;
Ian Elliott7e40db92015-08-21 15:09:33 -0600147 uint32_t m_swapchainImageCount;
148 VkSwapchainKHR m_swap_chain;
149 SwapchainBuffers *m_buffers;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600150 VkFormat m_format;
Ian Elliott7e40db92015-08-21 15:09:33 -0600151 VkColorSpaceKHR m_color_space;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600152
153 uint32_t m_current_buffer;
Chia-I Wuf8693382015-04-16 22:02:10 +0800154
155 bool m_quit;
156 bool m_pause;
157
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600158 int m_width;
159 int m_height;
Chia-I Wuf8693382015-04-16 22:02:10 +0800160
161 std::list<VkTestImageRecord>::iterator m_display_image;
162
163 void Display();
Tony Barbourfeb61962015-09-21 15:17:33 -0600164#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800165 void HandleEvent(xcb_generic_event_t *event);
Tony Barbourfeb61962015-09-21 15:17:33 -0600166#endif
Chia-I Wuf8693382015-04-16 22:02:10 +0800167};
168
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600169#ifndef _WIN32
170
171#include <errno.h>
172
173int fopen_s(
174 FILE** pFile,
175 const char* filename,
176 const char* mode
177)
178{
179 if (!pFile || !filename || !mode) {
180 return EINVAL;
181 }
182
183 FILE* f = fopen(filename, mode);
184 if (! f) {
185 if (errno != 0) {
186 return errno;
187 } else {
188 return ENOENT;
189 }
190 }
191 *pFile = f;
192
193 return 0;
194}
195
196#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600197
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600198
199
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600200// Set up environment for GLSL compiler
201// Must be done once per process
202void TestEnvironment::SetUp()
203{
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600204 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600205 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800206
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600207 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600208}
209
210void TestEnvironment::TearDown()
211{
212 glslang::FinalizeProcess();
213}
214
Tony Barbour6918cd52015-04-09 12:58:51 -0600215VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600216 m_compile_options( 0 ),
217 m_num_shader_strings( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600218{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600219
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600220}
221
Tony Barbour6918cd52015-04-09 12:58:51 -0600222VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600223{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600224
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600225}
226
227// Define all the static elements
Cody Northropa3673cf2015-06-09 13:00:45 -0600228bool VkTestFramework::m_show_images = false;
229bool VkTestFramework::m_save_images = false;
230bool VkTestFramework::m_compare_images = false;
231bool VkTestFramework::m_use_glsl = false;
232bool VkTestFramework::m_canonicalize_spv = false;
233bool VkTestFramework::m_strip_spv = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600234bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour6918cd52015-04-09 12:58:51 -0600235int VkTestFramework::m_width = 0;
236int VkTestFramework::m_height = 0;
237std::list<VkTestImageRecord> VkTestFramework::m_images;
238std::list<VkTestImageRecord>::iterator VkTestFramework::m_display_image;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600239int m_display_image_idx = 0;
240
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600241bool VkTestFramework::optionMatch(const char* option, char* optionLine)
242{
243 if (strncmp(option, optionLine, strlen(option)) == 0)
244 return true;
245 else
246 return false;
247}
248
Tony Barbour6918cd52015-04-09 12:58:51 -0600249void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600250{
251 int i, n;
252
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600253 for (i=1, n=1; i< *argc; i++) {
254 if (optionMatch("--show-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600255 m_show_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600256 else if (optionMatch("--save-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600257 m_save_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600258 else if (optionMatch("--no-SPV", argv[i]))
259 m_use_glsl = true;
260 else if (optionMatch("--strip-SPV", argv[i]))
261 m_strip_spv = true;
262 else if (optionMatch("--canonicalize-SPV", argv[i]))
263 m_canonicalize_spv = true;
264 else if (optionMatch("--compare-images", argv[i]))
Tony Barbour247bf372014-10-30 14:29:04 -0600265 m_compare_images = true;
Tony Barbour247bf372014-10-30 14:29:04 -0600266
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600267 else if (optionMatch("--help", argv[i]) ||
268 optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700269 printf("\nOther options:\n");
270 printf("\t--show-images\n"
271 "\t\tDisplay test images in viewer after tests complete.\n");
272 printf("\t--save-images\n"
273 "\t\tSave tests images as ppm files in current working directory.\n"
274 "\t\tUsed to generate golden images for compare-images.\n");
275 printf("\t--compare-images\n"
276 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barboura98d3932014-12-11 09:52:49 -0700277 "\t\tAlso saves the generated test image in current working\n"
278 "\t\t\tdirectory but only if the image is different from the golden\n"
279 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
280 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700281 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600282 printf("\t--no-SPV\n"
283 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600284 printf("\t--strip-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600285 "\t\tStrip SPIR-V debug information (line numbers, names, etc).\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600286 printf("\t--canonicalize-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600287 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600288 exit(0);
289 } else {
290 printf("\nUnrecognized option: %s\n", argv[i]);
291 printf("\nUse --help or -h for option list.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700292 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700293 }
294
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600295 /*
296 * Since the above "consume" inputs, update argv
297 * so that it contains the trimmed list of args for glutInit
298 */
299
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600300 argv[n] = argv[i];
301 n++;
302 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600303}
304
Tony Barbour6918cd52015-04-09 12:58:51 -0600305void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600306{
307 string filename;
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600308 uint32_t x, y;
Tony Barbour6918cd52015-04-09 12:58:51 -0600309 VkImageObj displayImage(image->device());
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600310 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbour84d448c2015-04-02 14:02:33 -0600311
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800312 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 -0600313 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600314
315 filename.append(basename);
316 filename.append(".ppm");
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600317
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600318 const VkImageSubresource sr = {
Courtney Goeltzenleuchter908e7672015-10-21 17:00:51 -0600319 VK_IMAGE_ASPECT_COLOR_BIT, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600320 };
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600321 VkSubresourceLayout sr_layout;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600322
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600323 vkGetImageSubresourceLayout(image->device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600324
Tony Barbour84d448c2015-04-02 14:02:33 -0600325 char *ptr;
Chia-I Wu681d7a02015-07-03 13:44:34 +0800326 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600327 ptr += sr_layout.offset;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600328 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600329 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
330
331 file << "P6\n";
Tony Barbourfeb61962015-09-21 15:17:33 -0600332 file << displayImage.width() << " ";
Tony Barbour84d448c2015-04-02 14:02:33 -0600333 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600334 file << 255 << "\n";
335
Tony Barbour84d448c2015-04-02 14:02:33 -0600336 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700337 const int *row = (const int *) ptr;
338 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600339
Tony Barbourd1c35722015-04-16 15:59:00 -0600340 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700341 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600342 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700343 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
344 file.write((char *) &swapped, 3);
345 row++;
346 }
347 }
Tony Barbourd1c35722015-04-16 15:59:00 -0600348 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700349 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600350 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700351 file.write((char *) row, 3);
352 row++;
353 }
354 }
355 else {
356 printf("Unrecognized image format - will not write image files");
357 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600358 }
359
360 ptr += sr_layout.rowPitch;
361 }
362
363 file.close();
Chia-I Wu681d7a02015-07-03 13:44:34 +0800364 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600365}
366
Tony Barbour6918cd52015-04-09 12:58:51 -0600367void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour247bf372014-10-30 14:29:04 -0600368{
369
370 MagickWand *magick_wand_1;
371 MagickWand *magick_wand_2;
372 MagickWand *compare_wand;
373 MagickBooleanType status;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600374 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600375 double differenz;
376
Tony Barbour4ab45422014-12-10 17:00:20 -0700377 if (getenv("RENDERTEST_GOLDEN_DIR"))
378 {
379 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
380 }
381
Tony Barbour247bf372014-10-30 14:29:04 -0600382 MagickWandGenesis();
383 magick_wand_1=NewMagickWand();
384 sprintf(testimage,"%s.ppm",basename);
385 status=MagickReadImage(magick_wand_1,testimage);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600386 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour247bf372014-10-30 14:29:04 -0600387
388
389 MagickWandGenesis();
390 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700391 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600392 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600393 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour247bf372014-10-30 14:29:04 -0600394
Tony Barbour247bf372014-10-30 14:29:04 -0600395 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
396 if (differenz != 0.0)
397 {
398 char difference[256];
399
400 sprintf(difference,"%s-diff.ppm",basename);
401 status = MagickWriteImage(compare_wand, difference);
402 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
403 }
404 DestroyMagickWand(compare_wand);
405
406 DestroyMagickWand(magick_wand_1);
407 DestroyMagickWand(magick_wand_2);
408 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700409
410 if (differenz == 0.0)
411 {
412 /*
413 * If test image and golden image match, we do not need to
414 * keep around the test image.
415 */
416 remove(testimage);
417 }
Tony Barbour247bf372014-10-30 14:29:04 -0600418}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600419
Tony Barbour6918cd52015-04-09 12:58:51 -0600420void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600421{
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 Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600439 ptr += sr_layout.offset;
440
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600441 record.m_title.append(comment);
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600442 record.m_width = displayImage.width();
443 record.m_height = displayImage.height();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600444 // TODO: Need to make this more robust to handle different image formats
Tony-LunarG399dfca2015-05-19 14:08:26 -0600445 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600446 record.m_data = malloc(record.m_data_size);
447 memcpy(record.m_data, ptr, record.m_data_size);
448 m_images.push_back(record);
449 m_display_image = --m_images.end();
450
Chia-I Wu681d7a02015-07-03 13:44:34 +0800451 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600452}
453
Tony Barbour6918cd52015-04-09 12:58:51 -0600454void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600455{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600456 for (int32_t i = 0; i < images.size(); i++) {
457 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600458 }
459}
460
Tony Barbour6918cd52015-04-09 12:58:51 -0600461void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600462{
463 const ::testing::TestInfo* const test_info =
464 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600465 ostringstream filestream;
466 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600467
Tony Barbour247bf372014-10-30 14:29:04 -0600468 m_width = 40;
469
470 if (strcmp(test_info->name(), m_testName.c_str())) {
471 filestream << test_info->name();
472 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700473 m_frameNum = 2;
474 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600475 }
476 else {
477 filestream << test_info->name() << "-" << m_frameNum;
478 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700479 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600480 }
481
Tony Barbour247bf372014-10-30 14:29:04 -0600482 // ToDo - scrub string for bad characters
483
484 if (m_save_images || m_compare_images) {
485 WritePPM(filename.c_str(), image);
486 if (m_compare_images) {
487 Compare(filename.c_str(), image);
488 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600489 }
490
491 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600492 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600493 }
494}
495
Chia-I Wuf8693382015-04-16 22:02:10 +0800496TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
497 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700498 m_queue(*m_device.graphics_queues()[0]),
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800499 m_cmdpool(m_device, vk_testing::CommandPool::create_info(m_device.graphics_queue_node_index_)),
500 m_cmdbuf(m_device, vk_testing::CommandBuffer::create_info(m_cmdpool.handle()))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600501{
Tony Barbour96db8822015-02-25 12:28:39 -0700502 m_quit = false;
503 m_pause = false;
504 m_width = 0;
505 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600506}
507
Tony Barbour6918cd52015-04-09 12:58:51 -0600508void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600509{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600510 VkResult U_ASSERT_ONLY err;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600511 vk_testing::Buffer buf;
512 void *dest_ptr;
513
Tony Barbour6a3faf02015-07-23 10:36:18 -0600514 VkSemaphore presentCompleteSemaphore;
515 VkSemaphoreCreateInfo presentCompleteSemaphoreCreateInfo = {};
516 presentCompleteSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
517 presentCompleteSemaphoreCreateInfo.pNext = NULL;
518 presentCompleteSemaphoreCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
519
520
521 err = vkCreateSemaphore(m_device.handle(),
522 &presentCompleteSemaphoreCreateInfo,
Chia-I Wuf7458c52015-10-26 21:10:41 +0800523 NULL, &presentCompleteSemaphore);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600524 assert(!err);
525
526 // Get the index of the next available swapchain image:
Ian Elliott7e40db92015-08-21 15:09:33 -0600527 err = m_fpAcquireNextImageKHR(m_device.handle(), m_swap_chain,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600528 UINT64_MAX,
529 presentCompleteSemaphore,
Ian Elliottc11750d2015-10-30 13:24:12 -0600530 VK_NULL_HANDLE,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600531 &m_current_buffer);
Ian Elliott7e40db92015-08-21 15:09:33 -0600532 // TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
Tony Barbour6a3faf02015-07-23 10:36:18 -0600533 // return codes
534 assert(!err);
535
Tony-LunarG399dfca2015-05-19 14:08:26 -0600536 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Cody Northrop7fb43862015-06-22 14:56:14 -0600537 buf.init_as_src(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800538 dest_ptr = buf.memory().map();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600539 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800540 buf.memory().unmap();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600541
542 m_cmdbuf.begin();
Tony Barbourbd094ce2015-10-23 11:00:15 -0600543 VkImageMemoryBarrier memoryBarrier = {};
544 memoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
545 memoryBarrier.pNext = NULL;
Tony Barbourd800bbd2015-11-05 10:54:44 -0700546 memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
Chia-I Wua4594202015-10-27 19:54:37 +0800547 memoryBarrier.dstAccessMask = 0;
Ian Elliott1dcd1092015-11-17 17:29:40 -0700548 memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800549 memoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600550 memoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800551 memoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600552 memoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
553 memoryBarrier.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800554 memoryBarrier.subresourceRange.levelCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600555 memoryBarrier.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800556 memoryBarrier.subresourceRange.layerCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600557 memoryBarrier.image = m_buffers[m_current_buffer].image;
558 VkImageMemoryBarrier *pmemory_barrier = &memoryBarrier;
Chia-I Wu89d0f942015-10-31 00:31:16 +0800559 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 +0800560 0, 1, (const void * const*)&pmemory_barrier);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600561
562 VkBufferImageCopy region = {};
Tony Barbourd800bbd2015-11-05 10:54:44 -0700563 region.bufferRowLength = m_display_image->m_width;
564 region.bufferImageHeight = m_display_image->m_height;
565 region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
566 region.imageSubresource.layerCount = 1;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600567 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;
Ian Elliott1dcd1092015-11-17 17:29:40 -0700577 memoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_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;
Ian Elliottc11750d2015-10-30 13:24:12 -0600609 present.pSwapchains = & m_swap_chain;
610 present.pImageIndices = &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
Ian Elliottc11750d2015-10-30 13:24:12 -0600786 // Create the WSI surface:
Ian Elliott1a3845b2015-07-06 14:33:04 -0600787#ifdef _WIN32
Ian Elliottc11750d2015-10-30 13:24:12 -0600788 err = vkCreateWin32SurfaceKHR(m_instance, m_connection,
789 m_window, NULL, &m_surface);
Ian Elliott1a3845b2015-07-06 14:33:04 -0600790#else // _WIN32
Ian Elliottc11750d2015-10-30 13:24:12 -0600791 err = vkCreateXcbSurfaceKHR(m_instance, m_connection,
792 m_window, NULL, &m_surface);
Ian Elliott1a3845b2015-07-06 14:33:04 -0600793#endif // _WIN32
Ian Elliottc11750d2015-10-30 13:24:12 -0600794 assert(!err);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600795
796 // Iterate over each queue to learn whether it supports presenting to WSI:
797 VkBool32 supportsPresent;
798 m_present_queue_node_index = UINT32_MAX;
799 std::vector<vk_testing::Queue *> queues = m_device.graphics_queues();
800 for (int i=0; i < queues.size(); i++)
801 {
802 int family_index = queues[i]->get_family_index();
Ian Elliott7e40db92015-08-21 15:09:33 -0600803 m_fpGetPhysicalDeviceSurfaceSupportKHR(m_device.phy().handle(),
Tony Barbour6a3faf02015-07-23 10:36:18 -0600804 family_index,
Ian Elliottc11750d2015-10-30 13:24:12 -0600805 m_surface,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600806 &supportsPresent);
807 if (supportsPresent) {
808 m_present_queue_node_index = family_index;
809 }
810 }
811
812 assert(m_present_queue_node_index != UINT32_MAX);
813
814
815 // Get the list of VkFormat's that are supported:
Ian Elliott8b139792015-08-07 11:51:12 -0600816 uint32_t formatCount;
Ian Elliottc11750d2015-10-30 13:24:12 -0600817 err = m_fpGetPhysicalDeviceSurfaceFormatsKHR(m_device.phy().handle(),
818 m_surface,
Ian Elliott8b139792015-08-07 11:51:12 -0600819 &formatCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600820 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600821 VkSurfaceFormatKHR *surfFormats =
822 (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
Ian Elliottc11750d2015-10-30 13:24:12 -0600823 err = m_fpGetPhysicalDeviceSurfaceFormatsKHR(m_device.phy().handle(),
824 m_surface,
Ian Elliott8b139792015-08-07 11:51:12 -0600825 &formatCount, surfFormats);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600826 assert(!err);
827 // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
828 // the surface has no preferred format. Otherwise, at least one
829 // supported format will be returned.
Tony Barbour6a3faf02015-07-23 10:36:18 -0600830 if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED)
831 {
832 m_format = VK_FORMAT_B8G8R8A8_UNORM;
833 }
834 else
835 {
836 assert(formatCount >= 1);
837 m_format = surfFormats[0].format;
838 }
Ian Elliott8b139792015-08-07 11:51:12 -0600839 m_color_space = surfFormats[0].colorSpace;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600840
Ian Elliottc11750d2015-10-30 13:24:12 -0600841 // Check the surface capabilities and formats
842 VkSurfaceCapabilitiesKHR surfCapabilities;
843 err = m_fpGetPhysicalDeviceSurfaceCapabilitiesKHR(m_device.phy().handle(),
844 m_surface,
845 &surfCapabilities);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600846 assert(!err);
847
Ian Elliott8b139792015-08-07 11:51:12 -0600848 uint32_t presentModeCount;
Ian Elliottc11750d2015-10-30 13:24:12 -0600849 err = m_fpGetPhysicalDeviceSurfacePresentModesKHR(m_device.phy().handle(),
850 m_surface,
Ian Elliott8b139792015-08-07 11:51:12 -0600851 &presentModeCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600852 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600853 VkPresentModeKHR *presentModes =
854 (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
Ian Elliott8b139792015-08-07 11:51:12 -0600855 assert(presentModes);
Ian Elliottc11750d2015-10-30 13:24:12 -0600856 err = m_fpGetPhysicalDeviceSurfacePresentModesKHR(m_device.phy().handle(),
857 m_surface,
Ian Elliott8b139792015-08-07 11:51:12 -0600858 &presentModeCount, presentModes);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600859 assert(!err);
860
Ian Elliott7e40db92015-08-21 15:09:33 -0600861 VkExtent2D swapchainExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600862 // width and height are either both -1, or both not -1.
Ian Elliottc11750d2015-10-30 13:24:12 -0600863 if (surfCapabilities.currentExtent.width == -1)
Tony Barbour6a3faf02015-07-23 10:36:18 -0600864 {
865 // If the surface size is undefined, the size is set to
866 // the size of the images requested.
Ian Elliott7e40db92015-08-21 15:09:33 -0600867 swapchainExtent.width = m_width;
868 swapchainExtent.height = m_height;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600869 }
870 else
871 {
872 // If the surface size is defined, the swap chain size must match
Ian Elliottc11750d2015-10-30 13:24:12 -0600873 swapchainExtent = surfCapabilities.currentExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600874 }
875
876 // If mailbox mode is available, use it, as is the lowest-latency non-
Ian Elliottae0e8242015-08-10 13:20:49 -0600877 // tearing mode. If not, try IMMEDIATE which will usually be available,
878 // and is fastest (though it tears). If not, fall back to FIFO which is
879 // always available.
Ian Elliott7e40db92015-08-21 15:09:33 -0600880 VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600881 for (size_t i = 0; i < presentModeCount; i++) {
Ian Elliott7e40db92015-08-21 15:09:33 -0600882 if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
883 swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600884 break;
885 }
Ian Elliott7e40db92015-08-21 15:09:33 -0600886 if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) &&
887 (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
888 swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
Ian Elliottae0e8242015-08-10 13:20:49 -0600889 }
Tony Barbour6a3faf02015-07-23 10:36:18 -0600890 }
891
892 // Determine the number of VkImage's to use in the swap chain (we desire to
893 // own only 1 image at a time, besides the images being displayed and
894 // queued for display):
Ian Elliottc11750d2015-10-30 13:24:12 -0600895 uint32_t desiredNumberOfSwapchainImages = surfCapabilities.minImageCount + 1;
896 if ((surfCapabilities.maxImageCount > 0) &&
897 (desiredNumberOfSwapchainImages > surfCapabilities.maxImageCount))
Tony Barbour6a3faf02015-07-23 10:36:18 -0600898 {
899 // Application must settle for fewer images than desired:
Ian Elliottc11750d2015-10-30 13:24:12 -0600900 desiredNumberOfSwapchainImages = surfCapabilities.maxImageCount;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600901 }
902
Ian Elliottc11750d2015-10-30 13:24:12 -0600903 VkSurfaceTransformFlagsKHR preTransform;
904 if (surfCapabilities.supportedTransforms & VK_SURFACE_TRANSFORM_NONE_BIT_KHR) {
905 preTransform = VK_SURFACE_TRANSFORM_NONE_BIT_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600906 } else {
Ian Elliottc11750d2015-10-30 13:24:12 -0600907 preTransform = surfCapabilities.currentTransform;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600908 }
Ian Elliott1a3845b2015-07-06 14:33:04 -0600909
Cody Northropdf5b0922015-08-28 16:22:48 -0600910 // We want to blit to the swap chain, ensure the driver supports it. Color is always supported, per WSI spec.
Ian Elliottc11750d2015-10-30 13:24:12 -0600911 assert((surfCapabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) != 0);
Cody Northropdf5b0922015-08-28 16:22:48 -0600912
Ian Elliott7e40db92015-08-21 15:09:33 -0600913 VkSwapchainCreateInfoKHR swap_chain = {};
Ian Elliotta257eea2015-09-22 10:20:23 -0600914 swap_chain.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600915 swap_chain.pNext = NULL;
Ian Elliottc11750d2015-10-30 13:24:12 -0600916 swap_chain.surface = m_surface;
Ian Elliott7e40db92015-08-21 15:09:33 -0600917 swap_chain.minImageCount = desiredNumberOfSwapchainImages;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600918 swap_chain.imageFormat = m_format;
Ian Elliott8b139792015-08-07 11:51:12 -0600919 swap_chain.imageColorSpace = m_color_space;
Ian Elliott7e40db92015-08-21 15:09:33 -0600920 swap_chain.imageExtent.width = swapchainExtent.width;
921 swap_chain.imageExtent.height = swapchainExtent.height;
Ian Elliottc11750d2015-10-30 13:24:12 -0600922 swap_chain.imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT |
923 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
924 swap_chain.preTransform = (VkSurfaceTransformFlagBitsKHR) preTransform;
925 swap_chain.imageArrayLayers = 1;
926 swap_chain.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
927 swap_chain.queueFamilyIndexCount = 0;
Ian Elliott8b139792015-08-07 11:51:12 -0600928 swap_chain.pQueueFamilyIndices = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600929 swap_chain.presentMode = swapchainPresentMode;
Chia-I Wue2fc5522015-10-26 20:04:44 +0800930 swap_chain.oldSwapchain = VK_NULL_HANDLE;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600931 swap_chain.clipped = true;
932
933 uint32_t i;
Chia-I Wuf8693382015-04-16 22:02:10 +0800934
Ian Elliottc11750d2015-10-30 13:24:12 -0600935 err = m_fpCreateSwapchainKHR(m_device.handle(), &swap_chain, NULL, &m_swap_chain);
Chia-I Wuf8693382015-04-16 22:02:10 +0800936 assert(!err);
937
Ian Elliott7e40db92015-08-21 15:09:33 -0600938 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
939 &m_swapchainImageCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600940 assert(!err);
941
Ian Elliott7e40db92015-08-21 15:09:33 -0600942 VkImage* swapchainImages = (VkImage*)malloc(m_swapchainImageCount * sizeof(VkImage));
943 assert(swapchainImages);
944 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
945 &m_swapchainImageCount, swapchainImages);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600946 assert(!err);
947
Ian Elliott7e40db92015-08-21 15:09:33 -0600948 m_buffers = (SwapchainBuffers*)malloc(sizeof(SwapchainBuffers)*m_swapchainImageCount);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600949 assert(m_buffers);
950
Ian Elliott7e40db92015-08-21 15:09:33 -0600951 for (i = 0; i < m_swapchainImageCount; i++) {
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600952 VkImageViewCreateInfo color_image_view = {};
953 color_image_view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
954 color_image_view.pNext = NULL;
955 color_image_view.format = m_format;
Tony Barbourd800bbd2015-11-05 10:54:44 -0700956 color_image_view.components.r = VK_COMPONENT_SWIZZLE_R;
957 color_image_view.components.g = VK_COMPONENT_SWIZZLE_G;
958 color_image_view.components.b = VK_COMPONENT_SWIZZLE_B;
959 color_image_view.components.a = VK_COMPONENT_SWIZZLE_A;
Courtney Goeltzenleuchterba724512015-09-10 17:58:54 -0600960 color_image_view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600961 color_image_view.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800962 color_image_view.subresourceRange.levelCount = 1;
Courtney Goeltzenleuchter4a261892015-09-10 16:38:41 -0600963 color_image_view.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800964 color_image_view.subresourceRange.layerCount = 1;
Tony Barbourd800bbd2015-11-05 10:54:44 -0700965 color_image_view.viewType = VK_IMAGE_VIEW_TYPE_2D;
966 color_image_view.flags = 0;
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,
Ian Elliott1dcd1092015-11-17 17:29:40 -0700978 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
Tony Barbourbd094ce2015-10-23 11:00:15 -0600979
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 };
Chia-I Wub8d47ae2015-11-11 10:18:12 +0800994 cmd_buf_info.occlusionQueryEnable = VK_FALSE;
995 cmd_buf_info.queryFlags = 0;
996 cmd_buf_info.pipelineStatistics = 0;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600997
998 err = vkBeginCommandBuffer(m_cmdbuf.handle(), &cmd_buf_info);
999 assert(!err);
1000
1001 VkImageMemoryBarrier image_memory_barrier = {};
1002 image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
1003 image_memory_barrier.pNext = NULL;
Chia-I Wua4594202015-10-27 19:54:37 +08001004 image_memory_barrier.srcAccessMask = 0;
1005 image_memory_barrier.dstAccessMask = 0;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001006 image_memory_barrier.oldLayout = old_image_layout;
1007 image_memory_barrier.newLayout = new_image_layout;
1008 image_memory_barrier.image = image;
1009 image_memory_barrier.subresourceRange.aspectMask = aspectMask;
1010 image_memory_barrier.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001011 image_memory_barrier.subresourceRange.levelCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001012 image_memory_barrier.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001013 image_memory_barrier.subresourceRange.layerCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001014
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001015 if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
Tony Barbourbd094ce2015-10-23 11:00:15 -06001016 /* Make sure anything that was copying from this image has completed */
Chia-I Wua4594202015-10-27 19:54:37 +08001017 image_memory_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001018 }
1019
1020 if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
1021 /* Make sure any Copy or CPU writes to image are flushed */
Chia-I Wua4594202015-10-27 19:54:37 +08001022 image_memory_barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001023 }
1024
1025 VkImageMemoryBarrier *pmemory_barrier = &image_memory_barrier;
1026
1027 VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1028 VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1029
Chia-I Wu53534662015-10-26 17:08:33 +08001030 vkCmdPipelineBarrier(m_cmdbuf.handle(), src_stages, dest_stages, 0, 1, (const void * const*)&pmemory_barrier);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001031
1032 err = vkEndCommandBuffer(m_cmdbuf.handle());
1033 assert(!err);
1034
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001035 const VkCommandBuffer cmd_bufs[] = { m_cmdbuf.handle() };
Tony Barbourbd094ce2015-10-23 11:00:15 -06001036 VkFence nullFence = { VK_NULL_HANDLE };
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001037 VkSubmitInfo submit_info;
Chia-I Wuf9be13c2015-10-26 20:37:06 +08001038 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1039 submit_info.pNext = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001040 submit_info.waitSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001041 submit_info.pWaitSemaphores = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001042 submit_info.commandBufferCount = 1;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001043 submit_info.pCommandBuffers = cmd_bufs;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001044 submit_info.signalSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001045 submit_info.pSignalSemaphores = NULL;
1046
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -06001047 err = vkQueueSubmit(m_queue.handle(), 1, &submit_info, nullFence);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001048 assert(!err);
1049
1050 err = vkQueueWaitIdle(m_queue.handle());
1051 assert(!err);
1052
1053}
Tony Barbour96db8822015-02-25 12:28:39 -07001054
Jon Ashburn07daee72015-05-21 18:13:33 -06001055void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -07001056{
Ian Elliottc11750d2015-10-30 13:24:12 -06001057 m_instance = inst;
Ian Elliott7e40db92015-08-21 15:09:33 -06001058 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceSupportKHR);
Ian Elliottc11750d2015-10-30 13:24:12 -06001059 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceCapabilitiesKHR);
1060 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceFormatsKHR);
1061 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfacePresentModesKHR);
Ian Elliott7e40db92015-08-21 15:09:33 -06001062 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1063 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1064 GET_DEVICE_PROC_ADDR(m_device.handle(), DestroySwapchainKHR);
1065 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSwapchainImagesKHR);
1066 GET_DEVICE_PROC_ADDR(m_device.handle(), AcquireNextImageKHR);
1067 GET_DEVICE_PROC_ADDR(m_device.handle(), QueuePresentKHR);
Jon Ashburn07daee72015-05-21 18:13:33 -06001068
Tony Barbour96db8822015-02-25 12:28:39 -07001069 m_images = imagesIn;
1070}
1071
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001072#ifdef _WIN32
1073void TestFrameworkVkPresent::CreateMyWindow()
1074{
1075 WNDCLASSEX win_class;
1076 // const ::testing::TestInfo* const test_info =
1077 // ::testing::UnitTest::GetInstance()->current_test_info();
1078 m_connection = GetModuleHandle(NULL);
1079
1080 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1081 it != m_images.end(); it++) {
1082 if (m_width < it->m_width)
1083 m_width = it->m_width;
1084 if (m_height < it->m_height)
1085 m_height = it->m_height;
1086 }
1087 // Initialize the window class structure:
1088 win_class.cbSize = sizeof(WNDCLASSEX);
1089 win_class.style = CS_HREDRAW | CS_VREDRAW;
1090 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
1091 win_class.cbClsExtra = 0;
1092 win_class.cbWndExtra = 0;
1093 win_class.hInstance = m_connection; // hInstance
1094 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
1095 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
1096 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
1097 win_class.lpszMenuName = NULL;
1098 win_class.lpszClassName = "Test";
1099 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
1100 // Register window class:
1101 if (!RegisterClassEx(&win_class)) {
1102 // It didn't work, so try to give a useful error:
1103 printf("Unexpected error trying to start the application!\n");
1104 fflush(stdout);
1105 exit(1);
1106 }
1107 // Create window with the registered class:
Cody Northrop39582252015-08-05 15:39:31 -06001108 RECT wr = { 0, 0, m_width, m_height };
1109 AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001110 m_window = CreateWindowEx(0,
1111 "Test", // class name
1112 "Test", // app name
1113 WS_OVERLAPPEDWINDOW | // window style
1114 WS_VISIBLE |
1115 WS_SYSMENU,
1116 100,100, // x/y coords
Cody Northrop39582252015-08-05 15:39:31 -06001117 wr.right - wr.left, // width
1118 wr.bottom - wr.top, // height
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001119 NULL, // handle to parent
1120 NULL, // handle to menu
1121 m_connection, // hInstance
1122 NULL); // no extra parameters
1123
1124 if (!m_window) {
1125 // It didn't work, so try to give a useful error:
1126 DWORD error = GetLastError();
1127 char message[120];
1128 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
1129 MessageBox(NULL, message, "Error", MB_OK);
1130 exit(1);
1131 }
Tony-LunarG399dfca2015-05-19 14:08:26 -06001132 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
1133 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001134}
1135#else
Tony Barbour6918cd52015-04-09 12:58:51 -06001136void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -07001137{
Chia-I Wuf8693382015-04-16 22:02:10 +08001138 const xcb_setup_t *setup;
1139 xcb_screen_iterator_t iter;
1140 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -07001141 uint32_t value_mask, value_list[32];
1142
Chia-I Wuf8693382015-04-16 22:02:10 +08001143 m_connection = xcb_connect(NULL, &scr);
1144
1145 setup = xcb_get_setup(m_connection);
1146 iter = xcb_setup_roots_iterator(setup);
1147 while (scr-- > 0)
1148 xcb_screen_next(&iter);
1149
1150 m_screen = iter.data;
1151
1152 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1153 it != m_images.end(); it++) {
1154 if (m_width < it->m_width)
1155 m_width = it->m_width;
1156 if (m_height < it->m_height)
1157 m_height = it->m_height;
1158 }
1159
1160 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -07001161
1162 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +08001163 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -07001164 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
1165 XCB_EVENT_MASK_EXPOSURE |
1166 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
1167
Chia-I Wuf8693382015-04-16 22:02:10 +08001168 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -07001169 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001170 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -07001171 0, 0, m_width, m_height, 0,
1172 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001173 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -07001174 value_mask, value_list);
1175
1176 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +08001177 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -07001178 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +08001179 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001180
Chia-I Wuf8693382015-04-16 22:02:10 +08001181 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
1182 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001183
Chia-I Wuf8693382015-04-16 22:02:10 +08001184 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -07001185 m_window, (*reply).atom, 4, 32, 1,
1186 &(*m_atom_wm_delete_window).atom);
1187 free(reply);
1188
Chia-I Wuf8693382015-04-16 22:02:10 +08001189 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -07001190}
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001191#endif
Tony Barbour96db8822015-02-25 12:28:39 -07001192
Tony Barbour6918cd52015-04-09 12:58:51 -06001193void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -07001194{
Ian Elliottc11750d2015-10-30 13:24:12 -06001195 m_fpDestroySwapchainKHR(m_device.handle(), m_swap_chain, NULL);
Tony Barbour9226a822015-10-23 10:58:56 -06001196
1197 for (uint32_t i = 0; i < m_swapchainImageCount; i++) {
Chia-I Wuf7458c52015-10-26 21:10:41 +08001198 vkDestroyImageView(m_device.handle(), m_buffers[i].view, NULL);
Tony Barbour9226a822015-10-23 10:58:56 -06001199 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001200#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +08001201 xcb_destroy_window(m_connection, m_window);
1202 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001203#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001204}
1205
Tony Barbour6918cd52015-04-09 12:58:51 -06001206void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001207{
1208 if (m_images.size() == 0) return;
1209
Chia-I Wuf8693382015-04-16 22:02:10 +08001210 vk_testing::Environment env;
1211 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -07001212 {
Chia-I Wuf8693382015-04-16 22:02:10 +08001213 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -07001214
Jon Ashburn07daee72015-05-21 18:13:33 -06001215 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001216 vkPresent.CreateMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -06001217 vkPresent.CreateSwapchain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001218 vkPresent.Run();
1219 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -07001220 }
Chia-I Wuf8693382015-04-16 22:02:10 +08001221 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001222}
1223
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001224//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001225// These are the default resources for TBuiltInResources, used for both
1226// - parsing this string for the case where the user didn't supply one
1227// - dumping out a template for user construction of a config file
1228//
1229static const char* DefaultConfig =
1230 "MaxLights 32\n"
1231 "MaxClipPlanes 6\n"
1232 "MaxTextureUnits 32\n"
1233 "MaxTextureCoords 32\n"
1234 "MaxVertexAttribs 64\n"
1235 "MaxVertexUniformComponents 4096\n"
1236 "MaxVaryingFloats 64\n"
1237 "MaxVertexTextureImageUnits 32\n"
1238 "MaxCombinedTextureImageUnits 80\n"
1239 "MaxTextureImageUnits 32\n"
1240 "MaxFragmentUniformComponents 4096\n"
1241 "MaxDrawBuffers 32\n"
1242 "MaxVertexUniformVectors 128\n"
1243 "MaxVaryingVectors 8\n"
1244 "MaxFragmentUniformVectors 16\n"
1245 "MaxVertexOutputVectors 16\n"
1246 "MaxFragmentInputVectors 15\n"
1247 "MinProgramTexelOffset -8\n"
1248 "MaxProgramTexelOffset 7\n"
1249 "MaxClipDistances 8\n"
1250 "MaxComputeWorkGroupCountX 65535\n"
1251 "MaxComputeWorkGroupCountY 65535\n"
1252 "MaxComputeWorkGroupCountZ 65535\n"
1253 "MaxComputeWorkGroupSizeX 1024\n"
1254 "MaxComputeWorkGroupSizeY 1024\n"
1255 "MaxComputeWorkGroupSizeZ 64\n"
1256 "MaxComputeUniformComponents 1024\n"
1257 "MaxComputeTextureImageUnits 16\n"
1258 "MaxComputeImageUniforms 8\n"
1259 "MaxComputeAtomicCounters 8\n"
1260 "MaxComputeAtomicCounterBuffers 1\n"
1261 "MaxVaryingComponents 60\n"
1262 "MaxVertexOutputComponents 64\n"
1263 "MaxGeometryInputComponents 64\n"
1264 "MaxGeometryOutputComponents 128\n"
1265 "MaxFragmentInputComponents 128\n"
1266 "MaxImageUnits 8\n"
1267 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
1268 "MaxCombinedShaderOutputResources 8\n"
1269 "MaxImageSamples 0\n"
1270 "MaxVertexImageUniforms 0\n"
1271 "MaxTessControlImageUniforms 0\n"
1272 "MaxTessEvaluationImageUniforms 0\n"
1273 "MaxGeometryImageUniforms 0\n"
1274 "MaxFragmentImageUniforms 8\n"
1275 "MaxCombinedImageUniforms 8\n"
1276 "MaxGeometryTextureImageUnits 16\n"
1277 "MaxGeometryOutputVertices 256\n"
1278 "MaxGeometryTotalOutputComponents 1024\n"
1279 "MaxGeometryUniformComponents 1024\n"
1280 "MaxGeometryVaryingComponents 64\n"
1281 "MaxTessControlInputComponents 128\n"
1282 "MaxTessControlOutputComponents 128\n"
1283 "MaxTessControlTextureImageUnits 16\n"
1284 "MaxTessControlUniformComponents 1024\n"
1285 "MaxTessControlTotalOutputComponents 4096\n"
1286 "MaxTessEvaluationInputComponents 128\n"
1287 "MaxTessEvaluationOutputComponents 128\n"
1288 "MaxTessEvaluationTextureImageUnits 16\n"
1289 "MaxTessEvaluationUniformComponents 1024\n"
1290 "MaxTessPatchComponents 120\n"
1291 "MaxPatchVertices 32\n"
1292 "MaxTessGenLevel 64\n"
1293 "MaxViewports 16\n"
1294 "MaxVertexAtomicCounters 0\n"
1295 "MaxTessControlAtomicCounters 0\n"
1296 "MaxTessEvaluationAtomicCounters 0\n"
1297 "MaxGeometryAtomicCounters 0\n"
1298 "MaxFragmentAtomicCounters 8\n"
1299 "MaxCombinedAtomicCounters 8\n"
1300 "MaxAtomicCounterBindings 1\n"
1301 "MaxVertexAtomicCounterBuffers 0\n"
1302 "MaxTessControlAtomicCounterBuffers 0\n"
1303 "MaxTessEvaluationAtomicCounterBuffers 0\n"
1304 "MaxGeometryAtomicCounterBuffers 0\n"
1305 "MaxFragmentAtomicCounterBuffers 1\n"
1306 "MaxCombinedAtomicCounterBuffers 1\n"
1307 "MaxAtomicCounterBufferSize 16384\n"
1308 "MaxTransformFeedbackBuffers 4\n"
1309 "MaxTransformFeedbackInterleavedComponents 64\n"
1310 "MaxCullDistances 8\n"
1311 "MaxCombinedClipAndCullDistances 8\n"
1312 "MaxSamples 4\n"
1313
1314 "nonInductiveForLoops 1\n"
1315 "whileLoops 1\n"
1316 "doWhileLoops 1\n"
1317 "generalUniformIndexing 1\n"
1318 "generalAttributeMatrixVectorIndexing 1\n"
1319 "generalVaryingIndexing 1\n"
1320 "generalSamplerIndexing 1\n"
1321 "generalVariableIndexing 1\n"
1322 "generalConstantMatrixVectorIndexing 1\n"
1323 ;
1324
1325//
1326// *.conf => this is a config file that can set limits/resources
1327//
Tony Barbour6918cd52015-04-09 12:58:51 -06001328bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001329{
1330 if (name.size() < 5)
1331 return false;
1332
1333 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
1334 ConfigFile = name;
1335 return true;
1336 }
1337
1338 return false;
1339}
1340
1341//
1342// Parse either a .conf file provided by the user or the default string above.
1343//
Tony Barbour6918cd52015-04-09 12:58:51 -06001344void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001345{
1346 char** configStrings = 0;
1347 char* config = 0;
1348 if (ConfigFile.size() > 0) {
1349 configStrings = ReadFileData(ConfigFile.c_str());
1350 if (configStrings)
1351 config = *configStrings;
1352 else {
1353 printf("Error opening configuration file; will instead use the default configuration\n");
1354 }
1355 }
1356
1357 if (config == 0) {
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001358 config = (char *) alloca(strlen(DefaultConfig) + 1);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001359 strcpy(config, DefaultConfig);
1360 }
1361
1362 const char* delims = " \t\n\r";
1363 const char* token = strtok(config, delims);
1364 while (token) {
1365 const char* valueStr = strtok(0, delims);
1366 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1367 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1368 return;
1369 }
1370 int value = atoi(valueStr);
1371
1372 if (strcmp(token, "MaxLights") == 0)
1373 Resources.maxLights = value;
1374 else if (strcmp(token, "MaxClipPlanes") == 0)
1375 Resources.maxClipPlanes = value;
1376 else if (strcmp(token, "MaxTextureUnits") == 0)
1377 Resources.maxTextureUnits = value;
1378 else if (strcmp(token, "MaxTextureCoords") == 0)
1379 Resources.maxTextureCoords = value;
1380 else if (strcmp(token, "MaxVertexAttribs") == 0)
1381 Resources.maxVertexAttribs = value;
1382 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1383 Resources.maxVertexUniformComponents = value;
1384 else if (strcmp(token, "MaxVaryingFloats") == 0)
1385 Resources.maxVaryingFloats = value;
1386 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1387 Resources.maxVertexTextureImageUnits = value;
1388 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1389 Resources.maxCombinedTextureImageUnits = value;
1390 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1391 Resources.maxTextureImageUnits = value;
1392 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1393 Resources.maxFragmentUniformComponents = value;
1394 else if (strcmp(token, "MaxDrawBuffers") == 0)
1395 Resources.maxDrawBuffers = value;
1396 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1397 Resources.maxVertexUniformVectors = value;
1398 else if (strcmp(token, "MaxVaryingVectors") == 0)
1399 Resources.maxVaryingVectors = value;
1400 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1401 Resources.maxFragmentUniformVectors = value;
1402 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1403 Resources.maxVertexOutputVectors = value;
1404 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1405 Resources.maxFragmentInputVectors = value;
1406 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1407 Resources.minProgramTexelOffset = value;
1408 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1409 Resources.maxProgramTexelOffset = value;
1410 else if (strcmp(token, "MaxClipDistances") == 0)
1411 Resources.maxClipDistances = value;
1412 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1413 Resources.maxComputeWorkGroupCountX = value;
1414 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1415 Resources.maxComputeWorkGroupCountY = value;
1416 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1417 Resources.maxComputeWorkGroupCountZ = value;
1418 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1419 Resources.maxComputeWorkGroupSizeX = value;
1420 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1421 Resources.maxComputeWorkGroupSizeY = value;
1422 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1423 Resources.maxComputeWorkGroupSizeZ = value;
1424 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1425 Resources.maxComputeUniformComponents = value;
1426 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1427 Resources.maxComputeTextureImageUnits = value;
1428 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1429 Resources.maxComputeImageUniforms = value;
1430 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1431 Resources.maxComputeAtomicCounters = value;
1432 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1433 Resources.maxComputeAtomicCounterBuffers = value;
1434 else if (strcmp(token, "MaxVaryingComponents") == 0)
1435 Resources.maxVaryingComponents = value;
1436 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1437 Resources.maxVertexOutputComponents = value;
1438 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1439 Resources.maxGeometryInputComponents = value;
1440 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1441 Resources.maxGeometryOutputComponents = value;
1442 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1443 Resources.maxFragmentInputComponents = value;
1444 else if (strcmp(token, "MaxImageUnits") == 0)
1445 Resources.maxImageUnits = value;
1446 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1447 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1448 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1449 Resources.maxCombinedShaderOutputResources = value;
1450 else if (strcmp(token, "MaxImageSamples") == 0)
1451 Resources.maxImageSamples = value;
1452 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1453 Resources.maxVertexImageUniforms = value;
1454 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1455 Resources.maxTessControlImageUniforms = value;
1456 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1457 Resources.maxTessEvaluationImageUniforms = value;
1458 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1459 Resources.maxGeometryImageUniforms = value;
1460 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1461 Resources.maxFragmentImageUniforms = value;
1462 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1463 Resources.maxCombinedImageUniforms = value;
1464 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1465 Resources.maxGeometryTextureImageUnits = value;
1466 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1467 Resources.maxGeometryOutputVertices = value;
1468 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1469 Resources.maxGeometryTotalOutputComponents = value;
1470 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1471 Resources.maxGeometryUniformComponents = value;
1472 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1473 Resources.maxGeometryVaryingComponents = value;
1474 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1475 Resources.maxTessControlInputComponents = value;
1476 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1477 Resources.maxTessControlOutputComponents = value;
1478 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1479 Resources.maxTessControlTextureImageUnits = value;
1480 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1481 Resources.maxTessControlUniformComponents = value;
1482 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1483 Resources.maxTessControlTotalOutputComponents = value;
1484 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1485 Resources.maxTessEvaluationInputComponents = value;
1486 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1487 Resources.maxTessEvaluationOutputComponents = value;
1488 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1489 Resources.maxTessEvaluationTextureImageUnits = value;
1490 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1491 Resources.maxTessEvaluationUniformComponents = value;
1492 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1493 Resources.maxTessPatchComponents = value;
1494 else if (strcmp(token, "MaxPatchVertices") == 0)
1495 Resources.maxPatchVertices = value;
1496 else if (strcmp(token, "MaxTessGenLevel") == 0)
1497 Resources.maxTessGenLevel = value;
1498 else if (strcmp(token, "MaxViewports") == 0)
1499 Resources.maxViewports = value;
1500 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1501 Resources.maxVertexAtomicCounters = value;
1502 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1503 Resources.maxTessControlAtomicCounters = value;
1504 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1505 Resources.maxTessEvaluationAtomicCounters = value;
1506 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1507 Resources.maxGeometryAtomicCounters = value;
1508 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1509 Resources.maxFragmentAtomicCounters = value;
1510 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1511 Resources.maxCombinedAtomicCounters = value;
1512 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1513 Resources.maxAtomicCounterBindings = value;
1514 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1515 Resources.maxVertexAtomicCounterBuffers = value;
1516 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1517 Resources.maxTessControlAtomicCounterBuffers = value;
1518 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1519 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1520 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1521 Resources.maxGeometryAtomicCounterBuffers = value;
1522 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1523 Resources.maxFragmentAtomicCounterBuffers = value;
1524 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1525 Resources.maxCombinedAtomicCounterBuffers = value;
1526 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1527 Resources.maxAtomicCounterBufferSize = value;
1528 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1529 Resources.maxTransformFeedbackBuffers = value;
1530 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1531 Resources.maxTransformFeedbackInterleavedComponents = value;
1532 else if (strcmp(token, "MaxCullDistances") == 0)
1533 Resources.maxCullDistances = value;
1534 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1535 Resources.maxCombinedClipAndCullDistances = value;
1536 else if (strcmp(token, "MaxSamples") == 0)
1537 Resources.maxSamples = value;
1538
1539 else if (strcmp(token, "nonInductiveForLoops") == 0)
1540 Resources.limits.nonInductiveForLoops = (value != 0);
1541 else if (strcmp(token, "whileLoops") == 0)
1542 Resources.limits.whileLoops = (value != 0);
1543 else if (strcmp(token, "doWhileLoops") == 0)
1544 Resources.limits.doWhileLoops = (value != 0);
1545 else if (strcmp(token, "generalUniformIndexing") == 0)
1546 Resources.limits.generalUniformIndexing = (value != 0);
1547 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1548 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1549 else if (strcmp(token, "generalVaryingIndexing") == 0)
1550 Resources.limits.generalVaryingIndexing = (value != 0);
1551 else if (strcmp(token, "generalSamplerIndexing") == 0)
1552 Resources.limits.generalSamplerIndexing = (value != 0);
1553 else if (strcmp(token, "generalVariableIndexing") == 0)
1554 Resources.limits.generalVariableIndexing = (value != 0);
1555 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1556 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1557 else
1558 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1559
1560 token = strtok(0, delims);
1561 }
1562 if (configStrings)
1563 FreeFileData(configStrings);
1564}
1565
Tony Barbour6918cd52015-04-09 12:58:51 -06001566void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001567{
1568 if (m_compile_options & EOptionRelaxedErrors)
1569 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1570 if (m_compile_options & EOptionIntermediate)
1571 messages = (EShMessages)(messages | EShMsgAST);
1572 if (m_compile_options & EOptionSuppressWarnings)
1573 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1574}
1575
1576//
1577// Malloc a string of sufficient size and read a string into it.
1578//
Tony Barbour6918cd52015-04-09 12:58:51 -06001579char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001580{
1581 FILE *in;
1582 #if defined(_WIN32) && defined(__GNUC__)
1583 in = fopen(fileName, "r");
1584 int errorCode = in ? 0 : 1;
1585 #else
1586 int errorCode = fopen_s(&in, fileName, "r");
1587 #endif
1588
1589 char *fdata;
1590 int count = 0;
1591 const int maxSourceStrings = 5;
1592 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1593
1594 if (errorCode) {
1595 printf("Error: unable to open input file: %s\n", fileName);
1596 return 0;
1597 }
1598
1599 while (fgetc(in) != EOF)
1600 count++;
1601
1602 fseek(in, 0, SEEK_SET);
1603
1604 if (!(fdata = (char*)malloc(count+2))) {
1605 printf("Error allocating memory\n");
1606 return 0;
1607 }
1608 if (fread(fdata,1,count, in)!=count) {
1609 printf("Error reading input file: %s\n", fileName);
1610 return 0;
1611 }
1612 fdata[count] = '\0';
1613 fclose(in);
1614 if (count == 0) {
1615 return_data[0]=(char*)malloc(count+2);
1616 return_data[0][0]='\0';
1617 m_num_shader_strings = 0;
1618 return return_data;
1619 } else
1620 m_num_shader_strings = 1;
1621
1622 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1623 int ptr_len=0,i=0;
1624 while(count>0){
1625 return_data[i]=(char*)malloc(len+2);
1626 memcpy(return_data[i],fdata+ptr_len,len);
1627 return_data[i][len]='\0';
1628 count-=(len);
1629 ptr_len+=(len);
1630 if(count<len){
1631 if(count==0){
1632 m_num_shader_strings=(i+1);
1633 break;
1634 }
1635 len = count;
1636 }
1637 ++i;
1638 }
1639 return return_data;
1640}
1641
Tony Barbour6918cd52015-04-09 12:58:51 -06001642void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001643{
1644 for(int i=0;i<m_num_shader_strings;i++)
1645 free(data[i]);
1646}
1647
1648//
1649// Deduce the language from the filename. Files must end in one of the
1650// following extensions:
1651//
1652// .vert = vertex
1653// .tesc = tessellation control
1654// .tese = tessellation evaluation
1655// .geom = geometry
1656// .frag = fragment
1657// .comp = compute
1658//
Tony Barbour6918cd52015-04-09 12:58:51 -06001659EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001660{
1661 size_t ext = name.rfind('.');
1662 if (ext == std::string::npos) {
1663 return EShLangVertex;
1664 }
1665
1666 std::string suffix = name.substr(ext + 1, std::string::npos);
1667 if (suffix == "vert")
1668 return EShLangVertex;
1669 else if (suffix == "tesc")
1670 return EShLangTessControl;
1671 else if (suffix == "tese")
1672 return EShLangTessEvaluation;
1673 else if (suffix == "geom")
1674 return EShLangGeometry;
1675 else if (suffix == "frag")
1676 return EShLangFragment;
1677 else if (suffix == "comp")
1678 return EShLangCompute;
1679
1680 return EShLangVertex;
1681}
1682
1683//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001684// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001685//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001686EShLanguage VkTestFramework::FindLanguage(const VkShaderStageFlagBits shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001687{
1688 switch (shader_type) {
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001689 case VK_SHADER_STAGE_VERTEX_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001690 return EShLangVertex;
1691
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001692 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001693 return EShLangTessControl;
1694
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001695 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001696 return EShLangTessEvaluation;
1697
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001698 case VK_SHADER_STAGE_GEOMETRY_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001699 return EShLangGeometry;
1700
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001701 case VK_SHADER_STAGE_FRAGMENT_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001702 return EShLangFragment;
1703
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001704 case VK_SHADER_STAGE_COMPUTE_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001705 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001706
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001707 default:
1708 return EShLangVertex;
1709 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001710}
1711
1712
1713//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001714// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001715// Return value of false means an error was encountered.
1716//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001717bool VkTestFramework::GLSLtoSPV(const VkShaderStageFlagBits shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001718 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001719 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001720{
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001721 glslang::TProgram program;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001722 const char *shaderStrings[1];
1723
1724 // TODO: Do we want to load a special config file depending on the
1725 // shader source? Optional name maybe?
1726 // SetConfigFile(fileName);
1727
1728 ProcessConfigFile();
1729
1730 EShMessages messages = EShMsgDefault;
1731 SetMessageOptions(messages);
1732
1733 EShLanguage stage = FindLanguage(shader_type);
1734 glslang::TShader* shader = new glslang::TShader(stage);
1735
1736 shaderStrings[0] = pshader;
1737 shader->setStrings(shaderStrings, 1);
1738
1739 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1740
Cody Northrop195d6622014-11-03 12:54:37 -07001741 if (! (m_compile_options & EOptionSuppressInfolog)) {
1742 puts(shader->getInfoLog());
1743 puts(shader->getInfoDebugLog());
1744 }
1745
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001746 return false; // something didn't work
1747 }
1748
1749 program.addShader(shader);
1750
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001751
1752 //
1753 // Program-level processing...
1754 //
1755
Cody Northrop195d6622014-11-03 12:54:37 -07001756 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001757
Cody Northrop195d6622014-11-03 12:54:37 -07001758 if (! (m_compile_options & EOptionSuppressInfolog)) {
1759 puts(shader->getInfoLog());
1760 puts(shader->getInfoDebugLog());
1761 }
1762
1763 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001764 }
1765
1766 if (m_compile_options & EOptionDumpReflection) {
1767 program.buildReflection();
1768 program.dumpReflection();
1769 }
1770
Cody Northrop5a95b472015-06-03 13:01:54 -06001771 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1772
1773 //
1774 // Test the different modes of SPIR-V modification
1775 //
1776 if (this->m_canonicalize_spv) {
1777 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1778 }
1779
1780 if (this->m_strip_spv) {
1781 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1782 }
1783
1784 if (this->m_do_everything_spv) {
1785 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1786 }
1787
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001788 delete shader;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001789
1790 return true;
1791}
1792
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001793
1794
Tony Barbour6918cd52015-04-09 12:58:51 -06001795VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001796 m_width( 0 ),
1797 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001798 m_data( NULL ),
1799 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001800{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001801}
1802
Tony Barbour6918cd52015-04-09 12:58:51 -06001803VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001804{
1805
1806}
1807
Tony Barbour6918cd52015-04-09 12:58:51 -06001808VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001809{
1810 m_title = copyin.m_title;
1811 m_width = copyin.m_width;
1812 m_height = copyin.m_height;
1813 m_data_size = copyin.m_data_size;
1814 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1815}
1816
Tony Barbour6918cd52015-04-09 12:58:51 -06001817ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001818{
Tony Barbour6918cd52015-04-09 12:58:51 -06001819 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1820 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001821 return output;
1822}
1823
Tony Barbour6918cd52015-04-09 12:58:51 -06001824VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001825{
1826 m_title = rhs.m_title;
1827 m_width = rhs.m_width;
1828 m_height = rhs.m_height;
1829 m_data_size = rhs.m_data_size;
1830 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001831 return *this;
1832}
1833
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 != rhs.m_data) return 0;
1837 return 1;
1838}
1839
1840// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001841int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001842{
1843 if( this->m_data_size < rhs.m_data_size ) return 1;
1844 return 0;
1845}
1846