blob: c4ef1efbac31a7f8eb71ce65e22d6dc92d014029 [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.
21
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060022#include "vktestframework.h"
23#include "vkrenderframework.h"
Cody Northrop5a95b472015-06-03 13:01:54 -060024#include "SPIRV/GlslangToSpv.h"
25#include "SPIRV/SPVRemapper.h"
Tony Barbour4ab45422014-12-10 17:00:20 -070026#include <limits.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060027#include <math.h>
Chia-I Wuec664fa2014-12-02 11:54:24 +080028#include <wand/MagickWand.h>
Tony Barbourfeb61962015-09-21 15:17:33 -060029#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +080030#include <xcb/xcb.h>
Tony Barbourfeb61962015-09-21 15:17:33 -060031#endif
Ian Elliott7e40db92015-08-21 15:09:33 -060032#include "vk_ext_khr_swapchain.h"
33#include "vk_ext_khr_device_swapchain.h"
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060034
Tony Barbour3d69c9e2015-05-20 16:53:31 -060035#if defined(PATH_MAX) && !defined(MAX_PATH)
36#define MAX_PATH PATH_MAX
37#endif
38
Tony Barbour6a3faf02015-07-23 10:36:18 -060039#ifdef _WIN32
40#define ERR_EXIT(err_msg, err_class) \
41 do { \
42 MessageBox(NULL, err_msg, err_class, MB_OK); \
43 exit(1); \
44 } while (0)
45#else // _WIN32
46
47#define ERR_EXIT(err_msg, err_class) \
48 do { \
49 printf(err_msg); \
50 fflush(stdout); \
51 exit(1); \
52 } while (0)
53#endif // _WIN32
54
55#define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \
56{ \
57 m_fp##entrypoint = (PFN_vk##entrypoint) vkGetInstanceProcAddr(inst, "vk"#entrypoint); \
58 if (m_fp##entrypoint == NULL) { \
59 ERR_EXIT("vkGetInstanceProcAddr failed to find vk"#entrypoint, \
60 "vkGetInstanceProcAddr Failure"); \
61 } \
62}
63
64#define GET_DEVICE_PROC_ADDR(dev, entrypoint) \
65{ \
66 m_fp##entrypoint = (PFN_vk##entrypoint) vkGetDeviceProcAddr(dev, "vk"#entrypoint); \
67 if (m_fp##entrypoint == NULL) { \
68 ERR_EXIT("vkGetDeviceProcAddr failed to find vk"#entrypoint, \
69 "vkGetDeviceProcAddr Failure"); \
70 } \
71}
72
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060073// Command-line options
74enum TOptions {
75 EOptionNone = 0x000,
76 EOptionIntermediate = 0x001,
77 EOptionSuppressInfolog = 0x002,
78 EOptionMemoryLeakMode = 0x004,
79 EOptionRelaxedErrors = 0x008,
80 EOptionGiveWarnings = 0x010,
81 EOptionLinkProgram = 0x020,
82 EOptionMultiThreaded = 0x040,
83 EOptionDumpConfig = 0x080,
84 EOptionDumpReflection = 0x100,
85 EOptionSuppressWarnings = 0x200,
86 EOptionDumpVersions = 0x400,
Cody Northrop3bfd27c2015-03-17 15:55:58 -060087 EOptionSpv = 0x800,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060088 EOptionDefaultDesktop = 0x1000,
89};
90
Ian Elliott7e40db92015-08-21 15:09:33 -060091typedef struct _SwapchainBuffers {
Tony Barbour6a3faf02015-07-23 10:36:18 -060092 VkImage image;
Chia-I Wu3432a0c2015-10-27 18:04:07 +080093 VkCommandBuffer cmd;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -060094 VkImageView view;
Ian Elliott7e40db92015-08-21 15:09:33 -060095} SwapchainBuffers;
Tony Barbour6a3faf02015-07-23 10:36:18 -060096
Chia-I Wuf8693382015-04-16 22:02:10 +080097class TestFrameworkVkPresent
98{
99public:
100 TestFrameworkVkPresent(vk_testing::Device &device);
101
102 void Run();
Jon Ashburn07daee72015-05-21 18:13:33 -0600103 void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst);
Chia-I Wuf8693382015-04-16 22:02:10 +0800104 void CreateMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -0600105 void CreateSwapchain();
Tony Barbourbd094ce2015-10-23 11:00:15 -0600106 void SetImageLayout(VkImage image, VkImageAspectFlags aspectMask,
107 VkImageLayout old_image_layout, VkImageLayout new_image_layout);
Chia-I Wuf8693382015-04-16 22:02:10 +0800108 void TearDown();
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600109#ifdef _WIN32
110 static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
111#endif
112
Chia-I Wuf8693382015-04-16 22:02:10 +0800113
114protected:
115 vk_testing::Device &m_device;
116 vk_testing::Queue &m_queue;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800117 vk_testing::CommandPool m_cmdpool;
118 vk_testing::CommandBuffer m_cmdbuf;
Chia-I Wuf8693382015-04-16 22:02:10 +0800119
120private:
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600121#ifdef _WIN32
122 HINSTANCE m_connection; // hInstance - Windows Instance
123 HWND m_window; // hWnd - window handle
124
125#else
Chia-I Wuf8693382015-04-16 22:02:10 +0800126 xcb_connection_t *m_connection;
127 xcb_screen_t *m_screen;
128 xcb_window_t m_window;
129 xcb_intern_atom_reply_t *m_atom_wm_delete_window;
Ian Elliott7e40db92015-08-21 15:09:33 -0600130 VkPlatformHandleXcbKHR m_platform_handle_xcb;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600131#endif
Courtney Goeltzenleuchterd6079ec2015-04-22 10:09:35 -0600132 std::list<VkTestImageRecord> m_images;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600133 uint32_t m_present_queue_node_index;
Chia-I Wuf8693382015-04-16 22:02:10 +0800134
Ian Elliott7e40db92015-08-21 15:09:33 -0600135 PFN_vkGetPhysicalDeviceSurfaceSupportKHR m_fpGetPhysicalDeviceSurfaceSupportKHR;
136 PFN_vkGetSurfacePropertiesKHR m_fpGetSurfacePropertiesKHR;
137 PFN_vkGetSurfaceFormatsKHR m_fpGetSurfaceFormatsKHR;
138 PFN_vkGetSurfacePresentModesKHR m_fpGetSurfacePresentModesKHR;
139 PFN_vkCreateSwapchainKHR m_fpCreateSwapchainKHR;
140 PFN_vkDestroySwapchainKHR m_fpDestroySwapchainKHR;
141 PFN_vkGetSwapchainImagesKHR m_fpGetSwapchainImagesKHR;
142 PFN_vkAcquireNextImageKHR m_fpAcquireNextImageKHR;
143 PFN_vkQueuePresentKHR m_fpQueuePresentKHR;
144 VkSurfaceDescriptionWindowKHR m_surface_description;
145 uint32_t m_swapchainImageCount;
146 VkSwapchainKHR m_swap_chain;
147 SwapchainBuffers *m_buffers;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600148 VkFormat m_format;
Ian Elliott7e40db92015-08-21 15:09:33 -0600149 VkColorSpaceKHR m_color_space;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600150
151 uint32_t m_current_buffer;
Chia-I Wuf8693382015-04-16 22:02:10 +0800152
153 bool m_quit;
154 bool m_pause;
155
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600156 int m_width;
157 int m_height;
Chia-I Wuf8693382015-04-16 22:02:10 +0800158
159 std::list<VkTestImageRecord>::iterator m_display_image;
160
161 void Display();
Tony Barbourfeb61962015-09-21 15:17:33 -0600162#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800163 void HandleEvent(xcb_generic_event_t *event);
Tony Barbourfeb61962015-09-21 15:17:33 -0600164#endif
Chia-I Wuf8693382015-04-16 22:02:10 +0800165};
166
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600167#ifndef _WIN32
168
169#include <errno.h>
170
171int fopen_s(
172 FILE** pFile,
173 const char* filename,
174 const char* mode
175)
176{
177 if (!pFile || !filename || !mode) {
178 return EINVAL;
179 }
180
181 FILE* f = fopen(filename, mode);
182 if (! f) {
183 if (errno != 0) {
184 return errno;
185 } else {
186 return ENOENT;
187 }
188 }
189 *pFile = f;
190
191 return 0;
192}
193
194#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600195
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600196
197
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600198// Set up environment for GLSL compiler
199// Must be done once per process
200void TestEnvironment::SetUp()
201{
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600202 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600203 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800204
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600205 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600206}
207
208void TestEnvironment::TearDown()
209{
210 glslang::FinalizeProcess();
211}
212
Tony Barbour6918cd52015-04-09 12:58:51 -0600213VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600214 m_compile_options( 0 ),
215 m_num_shader_strings( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600216{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600217
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600218}
219
Tony Barbour6918cd52015-04-09 12:58:51 -0600220VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600221{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600222
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600223}
224
225// Define all the static elements
Cody Northropa3673cf2015-06-09 13:00:45 -0600226bool VkTestFramework::m_show_images = false;
227bool VkTestFramework::m_save_images = false;
228bool VkTestFramework::m_compare_images = false;
229bool VkTestFramework::m_use_glsl = false;
230bool VkTestFramework::m_canonicalize_spv = false;
231bool VkTestFramework::m_strip_spv = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600232bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour6918cd52015-04-09 12:58:51 -0600233int VkTestFramework::m_width = 0;
234int VkTestFramework::m_height = 0;
235std::list<VkTestImageRecord> VkTestFramework::m_images;
236std::list<VkTestImageRecord>::iterator VkTestFramework::m_display_image;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600237int m_display_image_idx = 0;
238
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600239bool VkTestFramework::optionMatch(const char* option, char* optionLine)
240{
241 if (strncmp(option, optionLine, strlen(option)) == 0)
242 return true;
243 else
244 return false;
245}
246
Tony Barbour6918cd52015-04-09 12:58:51 -0600247void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600248{
249 int i, n;
250
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600251 for (i=1, n=1; i< *argc; i++) {
252 if (optionMatch("--show-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600253 m_show_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600254 else if (optionMatch("--save-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600255 m_save_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600256 else if (optionMatch("--no-SPV", argv[i]))
257 m_use_glsl = true;
258 else if (optionMatch("--strip-SPV", argv[i]))
259 m_strip_spv = true;
260 else if (optionMatch("--canonicalize-SPV", argv[i]))
261 m_canonicalize_spv = true;
262 else if (optionMatch("--compare-images", argv[i]))
Tony Barbour247bf372014-10-30 14:29:04 -0600263 m_compare_images = true;
Tony Barbour247bf372014-10-30 14:29:04 -0600264
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600265 else if (optionMatch("--help", argv[i]) ||
266 optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700267 printf("\nOther options:\n");
268 printf("\t--show-images\n"
269 "\t\tDisplay test images in viewer after tests complete.\n");
270 printf("\t--save-images\n"
271 "\t\tSave tests images as ppm files in current working directory.\n"
272 "\t\tUsed to generate golden images for compare-images.\n");
273 printf("\t--compare-images\n"
274 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barboura98d3932014-12-11 09:52:49 -0700275 "\t\tAlso saves the generated test image in current working\n"
276 "\t\t\tdirectory but only if the image is different from the golden\n"
277 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
278 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700279 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600280 printf("\t--no-SPV\n"
281 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600282 printf("\t--strip-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600283 "\t\tStrip SPIR-V debug information (line numbers, names, etc).\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600284 printf("\t--canonicalize-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600285 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600286 exit(0);
287 } else {
288 printf("\nUnrecognized option: %s\n", argv[i]);
289 printf("\nUse --help or -h for option list.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700290 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700291 }
292
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600293 /*
294 * Since the above "consume" inputs, update argv
295 * so that it contains the trimmed list of args for glutInit
296 */
297
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600298 argv[n] = argv[i];
299 n++;
300 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600301}
302
Tony Barbour6918cd52015-04-09 12:58:51 -0600303void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600304{
305 string filename;
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600306 uint32_t x, y;
Tony Barbour6918cd52015-04-09 12:58:51 -0600307 VkImageObj displayImage(image->device());
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600308 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbour84d448c2015-04-02 14:02:33 -0600309
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800310 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 -0600311 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600312
313 filename.append(basename);
314 filename.append(".ppm");
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600315
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600316 const VkImageSubresource sr = {
Courtney Goeltzenleuchter908e7672015-10-21 17:00:51 -0600317 VK_IMAGE_ASPECT_COLOR_BIT, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600318 };
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600319 VkSubresourceLayout sr_layout;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600320
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600321 vkGetImageSubresourceLayout(image->device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600322
Tony Barbour84d448c2015-04-02 14:02:33 -0600323 char *ptr;
Chia-I Wu681d7a02015-07-03 13:44:34 +0800324 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600325 ptr += sr_layout.offset;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600326 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600327 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
328
329 file << "P6\n";
Tony Barbourfeb61962015-09-21 15:17:33 -0600330 file << displayImage.width() << " ";
Tony Barbour84d448c2015-04-02 14:02:33 -0600331 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600332 file << 255 << "\n";
333
Tony Barbour84d448c2015-04-02 14:02:33 -0600334 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700335 const int *row = (const int *) ptr;
336 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600337
Tony Barbourd1c35722015-04-16 15:59:00 -0600338 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700339 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600340 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700341 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
342 file.write((char *) &swapped, 3);
343 row++;
344 }
345 }
Tony Barbourd1c35722015-04-16 15:59:00 -0600346 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700347 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600348 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700349 file.write((char *) row, 3);
350 row++;
351 }
352 }
353 else {
354 printf("Unrecognized image format - will not write image files");
355 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600356 }
357
358 ptr += sr_layout.rowPitch;
359 }
360
361 file.close();
Chia-I Wu681d7a02015-07-03 13:44:34 +0800362 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600363}
364
Tony Barbour6918cd52015-04-09 12:58:51 -0600365void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour247bf372014-10-30 14:29:04 -0600366{
367
368 MagickWand *magick_wand_1;
369 MagickWand *magick_wand_2;
370 MagickWand *compare_wand;
371 MagickBooleanType status;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600372 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600373 double differenz;
374
Tony Barbour4ab45422014-12-10 17:00:20 -0700375 if (getenv("RENDERTEST_GOLDEN_DIR"))
376 {
377 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
378 }
379
Tony Barbour247bf372014-10-30 14:29:04 -0600380 MagickWandGenesis();
381 magick_wand_1=NewMagickWand();
382 sprintf(testimage,"%s.ppm",basename);
383 status=MagickReadImage(magick_wand_1,testimage);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600384 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour247bf372014-10-30 14:29:04 -0600385
386
387 MagickWandGenesis();
388 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700389 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600390 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600391 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour247bf372014-10-30 14:29:04 -0600392
Tony Barbour247bf372014-10-30 14:29:04 -0600393 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
394 if (differenz != 0.0)
395 {
396 char difference[256];
397
398 sprintf(difference,"%s-diff.ppm",basename);
399 status = MagickWriteImage(compare_wand, difference);
400 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
401 }
402 DestroyMagickWand(compare_wand);
403
404 DestroyMagickWand(magick_wand_1);
405 DestroyMagickWand(magick_wand_2);
406 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700407
408 if (differenz == 0.0)
409 {
410 /*
411 * If test image and golden image match, we do not need to
412 * keep around the test image.
413 */
414 remove(testimage);
415 }
Tony Barbour247bf372014-10-30 14:29:04 -0600416}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600417
Tony Barbour6918cd52015-04-09 12:58:51 -0600418void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600419{
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600420 VkResult err;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600421 VkSubresourceLayout sr_layout;
422 char *ptr;
423 VkTestImageRecord record;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600424 VkImageObj displayImage(image->device());
425 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
426
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800427 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 -0600428
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600429 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600430
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600431 const VkImageSubresource sr = {
Courtney Goeltzenleuchter908e7672015-10-21 17:00:51 -0600432 VK_IMAGE_ASPECT_COLOR_BIT, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600433 };
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600434
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600435 vkGetImageSubresourceLayout(displayImage.device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600436
Chia-I Wu681d7a02015-07-03 13:44:34 +0800437 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600438 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600439
440 ptr += sr_layout.offset;
441
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600442 record.m_title.append(comment);
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600443 record.m_width = displayImage.width();
444 record.m_height = displayImage.height();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600445 // TODO: Need to make this more robust to handle different image formats
Tony-LunarG399dfca2015-05-19 14:08:26 -0600446 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600447 record.m_data = malloc(record.m_data_size);
448 memcpy(record.m_data, ptr, record.m_data_size);
449 m_images.push_back(record);
450 m_display_image = --m_images.end();
451
Chia-I Wu681d7a02015-07-03 13:44:34 +0800452 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600453}
454
Tony Barbour6918cd52015-04-09 12:58:51 -0600455void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600456{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600457 for (int32_t i = 0; i < images.size(); i++) {
458 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600459 }
460}
461
Tony Barbour6918cd52015-04-09 12:58:51 -0600462void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600463{
464 const ::testing::TestInfo* const test_info =
465 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600466 ostringstream filestream;
467 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600468
Tony Barbour247bf372014-10-30 14:29:04 -0600469 m_width = 40;
470
471 if (strcmp(test_info->name(), m_testName.c_str())) {
472 filestream << test_info->name();
473 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700474 m_frameNum = 2;
475 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600476 }
477 else {
478 filestream << test_info->name() << "-" << m_frameNum;
479 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700480 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600481 }
482
Tony Barbour247bf372014-10-30 14:29:04 -0600483 // ToDo - scrub string for bad characters
484
485 if (m_save_images || m_compare_images) {
486 WritePPM(filename.c_str(), image);
487 if (m_compare_images) {
488 Compare(filename.c_str(), image);
489 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600490 }
491
492 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600493 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600494 }
495}
496
Chia-I Wuf8693382015-04-16 22:02:10 +0800497TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
498 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700499 m_queue(*m_device.graphics_queues()[0]),
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800500 m_cmdpool(m_device, vk_testing::CommandPool::create_info(m_device.graphics_queue_node_index_)),
501 m_cmdbuf(m_device, vk_testing::CommandBuffer::create_info(m_cmdpool.handle()))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600502{
Tony Barbour96db8822015-02-25 12:28:39 -0700503 m_quit = false;
504 m_pause = false;
505 m_width = 0;
506 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600507}
508
Tony Barbour6918cd52015-04-09 12:58:51 -0600509void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600510{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600511 VkResult U_ASSERT_ONLY err;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600512 vk_testing::Buffer buf;
513 void *dest_ptr;
514
Tony Barbour6a3faf02015-07-23 10:36:18 -0600515 VkSemaphore presentCompleteSemaphore;
516 VkSemaphoreCreateInfo presentCompleteSemaphoreCreateInfo = {};
517 presentCompleteSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
518 presentCompleteSemaphoreCreateInfo.pNext = NULL;
519 presentCompleteSemaphoreCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
520
521
522 err = vkCreateSemaphore(m_device.handle(),
523 &presentCompleteSemaphoreCreateInfo,
Chia-I Wuf7458c52015-10-26 21:10:41 +0800524 NULL, &presentCompleteSemaphore);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600525 assert(!err);
526
527 // Get the index of the next available swapchain image:
Ian Elliott7e40db92015-08-21 15:09:33 -0600528 err = m_fpAcquireNextImageKHR(m_device.handle(), m_swap_chain,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600529 UINT64_MAX,
530 presentCompleteSemaphore,
531 &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;
Chia-I Wua4594202015-10-27 19:54:37 +0800546 memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
547 memoryBarrier.dstAccessMask = 0;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600548 memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SOURCE_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 = {};
563 region.imageExtent.height = m_display_image->m_height;
564 region.imageExtent.width = m_display_image->m_width;
565 region.imageExtent.depth = 1;
566
Chia-I Wube2b9172015-07-03 11:49:42 +0800567 vkCmdCopyBufferToImage(m_cmdbuf.handle(),
Chia-I Wu681d7a02015-07-03 13:44:34 +0800568 buf.handle(),
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800569 m_buffers[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600570 1, &region);
Tony Barbourbd094ce2015-10-23 11:00:15 -0600571
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800572 memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600573 memoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SOURCE_KHR;
Chia-I Wu89d0f942015-10-31 00:31:16 +0800574 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 +0800575 0, 1, (const void * const*)&pmemory_barrier);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600576 m_cmdbuf.end();
577
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800578 VkCommandBuffer cmdBufs[1];
Chia-I Wube2b9172015-07-03 11:49:42 +0800579 cmdBufs[0] = m_cmdbuf.handle();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600580
Chia-I Wua690b412015-10-29 22:01:53 +0800581 // Wait for the present complete semaphore to be signaled to ensure
582 // that the image won't be rendered to until the presentation
583 // engine has fully released ownership to the application, and it is
584 // okay to render to the image.
Tony Barbour67e99152015-07-10 14:10:27 -0600585 VkFence nullFence = { VK_NULL_HANDLE };
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600586 VkSubmitInfo submit_info;
Chia-I Wuf9be13c2015-10-26 20:37:06 +0800587 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
588 submit_info.pNext = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +0800589 submit_info.waitSemaphoreCount = 1;
Chia-I Wua690b412015-10-29 22:01:53 +0800590 submit_info.pWaitSemaphores = &presentCompleteSemaphore,
Chia-I Wud50a7d72015-10-26 20:48:51 +0800591 submit_info.commandBufferCount = 1;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600592 submit_info.pCommandBuffers = cmdBufs;
Chia-I Wud50a7d72015-10-26 20:48:51 +0800593 submit_info.signalSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600594 submit_info.pSignalSemaphores = NULL;
595
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -0600596 vkQueueSubmit(m_queue.handle(), 1, &submit_info, nullFence);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600597 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700598
Chia-I Wuf7458c52015-10-26 21:10:41 +0800599 vkDestroySemaphore(m_device.handle(), presentCompleteSemaphore, NULL);
Chia-I Wua690b412015-10-29 22:01:53 +0800600
Ian Elliott7e40db92015-08-21 15:09:33 -0600601 VkPresentInfoKHR present = {};
602 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600603 present.pNext = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600604 present.swapchainCount = 1;
605 present.swapchains = & m_swap_chain;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600606 present.imageIndices = &m_current_buffer;
Tony Barbour96db8822015-02-25 12:28:39 -0700607
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600608#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800609 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700610 XCB_PROP_MODE_REPLACE,
611 m_window,
612 XCB_ATOM_WM_NAME,
613 XCB_ATOM_STRING,
614 8,
615 m_display_image->m_title.size(),
616 m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600617#endif
Jon Ashburn07daee72015-05-21 18:13:33 -0600618
Ian Elliott7e40db92015-08-21 15:09:33 -0600619 err = m_fpQueuePresentKHR(m_queue.handle(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700620 assert(!err);
621
622 m_queue.wait();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600623 m_current_buffer = (m_current_buffer + 1) % 2;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600624}
625
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600626#ifdef _WIN32
Tony-LunarG399dfca2015-05-19 14:08:26 -0600627# define PREVIOUSLY_DOWN 1<<29
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600628// MS-Windows event handling function:
629LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
630 UINT uMsg,
631 WPARAM wParam,
632 LPARAM lParam)
633{
634
635 switch(uMsg)
636 {
637 case WM_CLOSE:
638 PostQuitMessage(0);
639 break;
640
641 case WM_PAINT:
642 {
643 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
644 if (me) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600645 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600646 me->Display();
647 }
648 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600649 break;
650
651 case WM_KEYDOWN:
652 {
653 if (lParam & (PREVIOUSLY_DOWN)){
654 break;
655 }
656 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
657 // the window, we put the this pointer into the window's user data so we could get it back now
658 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
659 switch (wParam)
660 {
661 case VK_ESCAPE: me->m_quit = true;
662 break;
663
664 case VK_LEFT: // left arrow key
665 if (me->m_display_image == me->m_images.begin()) {
666 me->m_display_image = --me->m_images.end();
667 }
668 else {
669 --me->m_display_image;
670 }
671 break;
672
673 case VK_RIGHT: // right arrow key
674 ++me->m_display_image;
675 if (me->m_display_image == me->m_images.end()) {
676 me->m_display_image = me->m_images.begin();
677 }
678 break;
679
680 default:
681 break;
682 }
683 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
684 me->Display();
685 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600686 }
687 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
688}
689
690void TestFrameworkVkPresent::Run()
691{
692 MSG msg; // message
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600693
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600694 /* main message loop*/
Tony-LunarG399dfca2015-05-19 14:08:26 -0600695 while(! m_quit) {
696 GetMessage(&msg, m_window, 0, 0);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600697 if (msg.message == WM_QUIT) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600698 m_quit = true; //if found, quit app
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600699 } else {
700 /* Translate and dispatch to event queue*/
701 TranslateMessage(&msg);
702 DispatchMessage(&msg);
703 }
704 }
705}
706
707#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600708void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600709{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600710 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700711 switch (event_code) {
712 case XCB_EXPOSE:
713 Display(); // TODO: handle resize
714 break;
715 case XCB_CLIENT_MESSAGE:
716 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
717 (m_atom_wm_delete_window)->atom) {
718 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600719 }
720 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700721 case XCB_KEY_RELEASE:
722 {
723 const xcb_key_release_event_t *key =
724 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600725
Tony Barbour96db8822015-02-25 12:28:39 -0700726 switch (key->detail) {
727 case 0x9: // Escape
728 m_quit = true;
729 break;
730 case 0x71: // left arrow key
731 if (m_display_image == m_images.begin()) {
732 m_display_image = --m_images.end();
733 } else {
734 --m_display_image;
735 }
736 break;
737 case 0x72: // right arrow key
738 ++m_display_image;
739 if (m_display_image == m_images.end()) {
740 m_display_image = m_images.begin();
741 }
742 break;
743 case 0x41:
744 m_pause = !m_pause;
745 break;
746 }
747 Display();
748 }
749 break;
750 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600751 break;
752 }
Tony Barbour96db8822015-02-25 12:28:39 -0700753}
754
Tony Barbour6918cd52015-04-09 12:58:51 -0600755void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700756{
Chia-I Wuf8693382015-04-16 22:02:10 +0800757 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700758
759 while (! m_quit) {
760 xcb_generic_event_t *event;
761
762 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800763 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700764 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800765 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700766 }
767 if (event) {
768 HandleEvent(event);
769 free(event);
770 }
771 }
772}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600773#endif // _WIN32
Tony Barbour96db8822015-02-25 12:28:39 -0700774
Ian Elliott7e40db92015-08-21 15:09:33 -0600775void TestFrameworkVkPresent::CreateSwapchain()
Tony Barbour96db8822015-02-25 12:28:39 -0700776{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600777 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700778
Tony-LunarG399dfca2015-05-19 14:08:26 -0600779 m_display_image = m_images.begin();
780 m_current_buffer = 0;
781
Tony Barbour6a3faf02015-07-23 10:36:18 -0600782 // Construct the WSI surface description:
Ian Elliott7e40db92015-08-21 15:09:33 -0600783 m_surface_description.sType = VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600784 m_surface_description.pNext = NULL;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600785#ifdef _WIN32
Ian Elliott7e40db92015-08-21 15:09:33 -0600786 m_surface_description.platform = VK_PLATFORM_WIN32_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600787 m_surface_description.pPlatformHandle = m_connection;
788 m_surface_description.pPlatformWindow = m_window;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600789#else // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -0600790 m_platform_handle_xcb.connection = m_connection;
791 m_platform_handle_xcb.root = m_screen->root;
Ian Elliott7e40db92015-08-21 15:09:33 -0600792 m_surface_description.platform = VK_PLATFORM_XCB_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600793 m_surface_description.pPlatformHandle = &m_platform_handle_xcb;
794 m_surface_description.pPlatformWindow = &m_window;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600795#endif // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -0600796
797 // Iterate over each queue to learn whether it supports presenting to WSI:
798 VkBool32 supportsPresent;
799 m_present_queue_node_index = UINT32_MAX;
800 std::vector<vk_testing::Queue *> queues = m_device.graphics_queues();
801 for (int i=0; i < queues.size(); i++)
802 {
803 int family_index = queues[i]->get_family_index();
Ian Elliott7e40db92015-08-21 15:09:33 -0600804 m_fpGetPhysicalDeviceSurfaceSupportKHR(m_device.phy().handle(),
Tony Barbour6a3faf02015-07-23 10:36:18 -0600805 family_index,
Ian Elliott7e40db92015-08-21 15:09:33 -0600806 (VkSurfaceDescriptionKHR *) &m_surface_description,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600807 &supportsPresent);
808 if (supportsPresent) {
809 m_present_queue_node_index = family_index;
810 }
811 }
812
813 assert(m_present_queue_node_index != UINT32_MAX);
814
815
816 // Get the list of VkFormat's that are supported:
Ian Elliott8b139792015-08-07 11:51:12 -0600817 uint32_t formatCount;
Ian Elliott7e40db92015-08-21 15:09:33 -0600818 err = m_fpGetSurfaceFormatsKHR(m_device.handle(),
819 (VkSurfaceDescriptionKHR *) &m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600820 &formatCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600821 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600822 VkSurfaceFormatKHR *surfFormats =
823 (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
824 err = m_fpGetSurfaceFormatsKHR(m_device.handle(),
825 (VkSurfaceDescriptionKHR *) &m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600826 &formatCount, surfFormats);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600827 assert(!err);
828 // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
829 // the surface has no preferred format. Otherwise, at least one
830 // supported format will be returned.
Tony Barbour6a3faf02015-07-23 10:36:18 -0600831 if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED)
832 {
833 m_format = VK_FORMAT_B8G8R8A8_UNORM;
834 }
835 else
836 {
837 assert(formatCount >= 1);
838 m_format = surfFormats[0].format;
839 }
Ian Elliott8b139792015-08-07 11:51:12 -0600840 m_color_space = surfFormats[0].colorSpace;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600841
842 // Check the surface proprties and formats
Ian Elliott7e40db92015-08-21 15:09:33 -0600843 VkSurfacePropertiesKHR surfProperties;
844 err = m_fpGetSurfacePropertiesKHR(m_device.handle(),
845 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600846 &surfProperties);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600847 assert(!err);
848
Ian Elliott8b139792015-08-07 11:51:12 -0600849 uint32_t presentModeCount;
Ian Elliott7e40db92015-08-21 15:09:33 -0600850 err = m_fpGetSurfacePresentModesKHR(m_device.handle(),
851 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600852 &presentModeCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600853 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600854 VkPresentModeKHR *presentModes =
855 (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
Ian Elliott8b139792015-08-07 11:51:12 -0600856 assert(presentModes);
Ian Elliott7e40db92015-08-21 15:09:33 -0600857 err = m_fpGetSurfacePresentModesKHR(m_device.handle(),
858 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600859 &presentModeCount, presentModes);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600860 assert(!err);
861
Ian Elliott7e40db92015-08-21 15:09:33 -0600862 VkExtent2D swapchainExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600863 // width and height are either both -1, or both not -1.
Ian Elliott8b139792015-08-07 11:51:12 -0600864 if (surfProperties.currentExtent.width == -1)
Tony Barbour6a3faf02015-07-23 10:36:18 -0600865 {
866 // If the surface size is undefined, the size is set to
867 // the size of the images requested.
Ian Elliott7e40db92015-08-21 15:09:33 -0600868 swapchainExtent.width = m_width;
869 swapchainExtent.height = m_height;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600870 }
871 else
872 {
873 // If the surface size is defined, the swap chain size must match
Ian Elliott7e40db92015-08-21 15:09:33 -0600874 swapchainExtent = surfProperties.currentExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600875 }
876
877 // If mailbox mode is available, use it, as is the lowest-latency non-
Ian Elliottae0e8242015-08-10 13:20:49 -0600878 // tearing mode. If not, try IMMEDIATE which will usually be available,
879 // and is fastest (though it tears). If not, fall back to FIFO which is
880 // always available.
Ian Elliott7e40db92015-08-21 15:09:33 -0600881 VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600882 for (size_t i = 0; i < presentModeCount; i++) {
Ian Elliott7e40db92015-08-21 15:09:33 -0600883 if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
884 swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600885 break;
886 }
Ian Elliott7e40db92015-08-21 15:09:33 -0600887 if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) &&
888 (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
889 swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
Ian Elliottae0e8242015-08-10 13:20:49 -0600890 }
Tony Barbour6a3faf02015-07-23 10:36:18 -0600891 }
892
893 // Determine the number of VkImage's to use in the swap chain (we desire to
894 // own only 1 image at a time, besides the images being displayed and
895 // queued for display):
Ian Elliott7e40db92015-08-21 15:09:33 -0600896 uint32_t desiredNumberOfSwapchainImages = surfProperties.minImageCount + 1;
Ian Elliott8b139792015-08-07 11:51:12 -0600897 if ((surfProperties.maxImageCount > 0) &&
Ian Elliott7e40db92015-08-21 15:09:33 -0600898 (desiredNumberOfSwapchainImages > surfProperties.maxImageCount))
Tony Barbour6a3faf02015-07-23 10:36:18 -0600899 {
900 // Application must settle for fewer images than desired:
Ian Elliott7e40db92015-08-21 15:09:33 -0600901 desiredNumberOfSwapchainImages = surfProperties.maxImageCount;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600902 }
903
Ian Elliott7e40db92015-08-21 15:09:33 -0600904 VkSurfaceTransformKHR preTransform;
905 if (surfProperties.supportedTransforms & VK_SURFACE_TRANSFORM_NONE_BIT_KHR) {
906 preTransform = VK_SURFACE_TRANSFORM_NONE_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600907 } else {
Ian Elliott8b139792015-08-07 11:51:12 -0600908 preTransform = surfProperties.currentTransform;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600909 }
Ian Elliott1a3845b2015-07-06 14:33:04 -0600910
Cody Northropdf5b0922015-08-28 16:22:48 -0600911 // We want to blit to the swap chain, ensure the driver supports it. Color is always supported, per WSI spec.
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800912 assert((surfProperties.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) != 0);
Cody Northropdf5b0922015-08-28 16:22:48 -0600913
Ian Elliott7e40db92015-08-21 15:09:33 -0600914 VkSwapchainCreateInfoKHR swap_chain = {};
Ian Elliotta257eea2015-09-22 10:20:23 -0600915 swap_chain.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600916 swap_chain.pNext = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600917 swap_chain.pSurfaceDescription = (const VkSurfaceDescriptionKHR *)&m_surface_description;
918 swap_chain.minImageCount = desiredNumberOfSwapchainImages;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600919 swap_chain.imageFormat = m_format;
Ian Elliott8b139792015-08-07 11:51:12 -0600920 swap_chain.imageColorSpace = m_color_space;
Ian Elliott7e40db92015-08-21 15:09:33 -0600921 swap_chain.imageExtent.width = swapchainExtent.width;
922 swap_chain.imageExtent.height = swapchainExtent.height;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800923 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DST_BIT |
Cody Northropdf8f42a2015-08-05 15:38:39 -0600924 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600925 swap_chain.preTransform = preTransform;
Chia-I Wuf8693382015-04-16 22:02:10 +0800926 swap_chain.imageArraySize = 1;
Ian Elliott8b139792015-08-07 11:51:12 -0600927 swap_chain.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
928 swap_chain.queueFamilyCount = 0;
929 swap_chain.pQueueFamilyIndices = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600930 swap_chain.presentMode = swapchainPresentMode;
Chia-I Wue2fc5522015-10-26 20:04:44 +0800931 swap_chain.oldSwapchain = VK_NULL_HANDLE;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600932 swap_chain.clipped = true;
933
934 uint32_t i;
Chia-I Wuf8693382015-04-16 22:02:10 +0800935
Ian Elliott7e40db92015-08-21 15:09:33 -0600936 err = m_fpCreateSwapchainKHR(m_device.handle(), &swap_chain, &m_swap_chain);
Chia-I Wuf8693382015-04-16 22:02:10 +0800937 assert(!err);
938
Ian Elliott7e40db92015-08-21 15:09:33 -0600939 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
940 &m_swapchainImageCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600941 assert(!err);
942
Ian Elliott7e40db92015-08-21 15:09:33 -0600943 VkImage* swapchainImages = (VkImage*)malloc(m_swapchainImageCount * sizeof(VkImage));
944 assert(swapchainImages);
945 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
946 &m_swapchainImageCount, swapchainImages);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600947 assert(!err);
948
Ian Elliott7e40db92015-08-21 15:09:33 -0600949 m_buffers = (SwapchainBuffers*)malloc(sizeof(SwapchainBuffers)*m_swapchainImageCount);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600950 assert(m_buffers);
951
Ian Elliott7e40db92015-08-21 15:09:33 -0600952 for (i = 0; i < m_swapchainImageCount; i++) {
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600953 VkImageViewCreateInfo color_image_view = {};
954 color_image_view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
955 color_image_view.pNext = NULL;
Courtney Goeltzenleuchter00265c82015-09-11 15:22:06 -0600956 color_image_view.viewType = VK_IMAGE_VIEW_TYPE_2D;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600957 color_image_view.format = m_format;
Courtney Goeltzenleuchterba724512015-09-10 17:58:54 -0600958 color_image_view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600959 color_image_view.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800960 color_image_view.subresourceRange.levelCount = 1;
Courtney Goeltzenleuchter4a261892015-09-10 16:38:41 -0600961 color_image_view.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800962 color_image_view.subresourceRange.layerCount = 1;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600963
Ian Elliott7e40db92015-08-21 15:09:33 -0600964 m_buffers[i].image = swapchainImages[i];
Tony Barbour6a3faf02015-07-23 10:36:18 -0600965
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600966 color_image_view.image = m_buffers[i].image;
967 err = vkCreateImageView(m_device.handle(),
Chia-I Wuf7458c52015-10-26 21:10:41 +0800968 &color_image_view, NULL, &m_buffers[i].view);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600969 assert(!err);
Tony Barbourbd094ce2015-10-23 11:00:15 -0600970
971 /* Set image layout to PRESENT_SOURCE_KHR so that before the copy, it can be set to */
972 /* TRANSFER_DESTINATION_OPTIMAL */
973 SetImageLayout(m_buffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT,
974 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SOURCE_KHR);
975
Tony Barbour6a3faf02015-07-23 10:36:18 -0600976 }
Tony Barbour96db8822015-02-25 12:28:39 -0700977}
Tony Barbourbd094ce2015-10-23 11:00:15 -0600978void TestFrameworkVkPresent::SetImageLayout(VkImage image, VkImageAspectFlags aspectMask,
979 VkImageLayout old_image_layout, VkImageLayout new_image_layout)
980{
981 VkResult U_ASSERT_ONLY err;
982
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800983 VkCommandBufferBeginInfo cmd_buf_info = {};
984 cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600985 cmd_buf_info.pNext = NULL;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800986 cmd_buf_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600987 cmd_buf_info.renderPass = { VK_NULL_HANDLE };
988 cmd_buf_info.subpass = 0;
989 cmd_buf_info.framebuffer = { VK_NULL_HANDLE };
990
991 err = vkBeginCommandBuffer(m_cmdbuf.handle(), &cmd_buf_info);
992 assert(!err);
993
994 VkImageMemoryBarrier image_memory_barrier = {};
995 image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
996 image_memory_barrier.pNext = NULL;
Chia-I Wua4594202015-10-27 19:54:37 +0800997 image_memory_barrier.srcAccessMask = 0;
998 image_memory_barrier.dstAccessMask = 0;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600999 image_memory_barrier.oldLayout = old_image_layout;
1000 image_memory_barrier.newLayout = new_image_layout;
1001 image_memory_barrier.image = image;
1002 image_memory_barrier.subresourceRange.aspectMask = aspectMask;
1003 image_memory_barrier.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001004 image_memory_barrier.subresourceRange.levelCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001005 image_memory_barrier.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001006 image_memory_barrier.subresourceRange.layerCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001007
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001008 if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
Tony Barbourbd094ce2015-10-23 11:00:15 -06001009 /* Make sure anything that was copying from this image has completed */
Chia-I Wua4594202015-10-27 19:54:37 +08001010 image_memory_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001011 }
1012
1013 if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
1014 /* Make sure any Copy or CPU writes to image are flushed */
Chia-I Wua4594202015-10-27 19:54:37 +08001015 image_memory_barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001016 }
1017
1018 VkImageMemoryBarrier *pmemory_barrier = &image_memory_barrier;
1019
1020 VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1021 VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1022
Chia-I Wu53534662015-10-26 17:08:33 +08001023 vkCmdPipelineBarrier(m_cmdbuf.handle(), src_stages, dest_stages, 0, 1, (const void * const*)&pmemory_barrier);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001024
1025 err = vkEndCommandBuffer(m_cmdbuf.handle());
1026 assert(!err);
1027
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001028 const VkCommandBuffer cmd_bufs[] = { m_cmdbuf.handle() };
Tony Barbourbd094ce2015-10-23 11:00:15 -06001029 VkFence nullFence = { VK_NULL_HANDLE };
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001030 VkSubmitInfo submit_info;
Chia-I Wuf9be13c2015-10-26 20:37:06 +08001031 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1032 submit_info.pNext = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001033 submit_info.waitSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001034 submit_info.pWaitSemaphores = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001035 submit_info.commandBufferCount = 1;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001036 submit_info.pCommandBuffers = cmd_bufs;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001037 submit_info.signalSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001038 submit_info.pSignalSemaphores = NULL;
1039
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -06001040 err = vkQueueSubmit(m_queue.handle(), 1, &submit_info, nullFence);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001041 assert(!err);
1042
1043 err = vkQueueWaitIdle(m_queue.handle());
1044 assert(!err);
1045
1046}
Tony Barbour96db8822015-02-25 12:28:39 -07001047
Jon Ashburn07daee72015-05-21 18:13:33 -06001048void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -07001049{
Ian Elliott7e40db92015-08-21 15:09:33 -06001050 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceSupportKHR);
1051 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfacePropertiesKHR);
1052 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfaceFormatsKHR);
1053 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfacePresentModesKHR);
1054 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1055 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1056 GET_DEVICE_PROC_ADDR(m_device.handle(), DestroySwapchainKHR);
1057 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSwapchainImagesKHR);
1058 GET_DEVICE_PROC_ADDR(m_device.handle(), AcquireNextImageKHR);
1059 GET_DEVICE_PROC_ADDR(m_device.handle(), QueuePresentKHR);
Jon Ashburn07daee72015-05-21 18:13:33 -06001060
Tony Barbour96db8822015-02-25 12:28:39 -07001061 m_images = imagesIn;
1062}
1063
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001064#ifdef _WIN32
1065void TestFrameworkVkPresent::CreateMyWindow()
1066{
1067 WNDCLASSEX win_class;
1068 // const ::testing::TestInfo* const test_info =
1069 // ::testing::UnitTest::GetInstance()->current_test_info();
1070 m_connection = GetModuleHandle(NULL);
1071
1072 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1073 it != m_images.end(); it++) {
1074 if (m_width < it->m_width)
1075 m_width = it->m_width;
1076 if (m_height < it->m_height)
1077 m_height = it->m_height;
1078 }
1079 // Initialize the window class structure:
1080 win_class.cbSize = sizeof(WNDCLASSEX);
1081 win_class.style = CS_HREDRAW | CS_VREDRAW;
1082 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
1083 win_class.cbClsExtra = 0;
1084 win_class.cbWndExtra = 0;
1085 win_class.hInstance = m_connection; // hInstance
1086 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
1087 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
1088 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
1089 win_class.lpszMenuName = NULL;
1090 win_class.lpszClassName = "Test";
1091 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
1092 // Register window class:
1093 if (!RegisterClassEx(&win_class)) {
1094 // It didn't work, so try to give a useful error:
1095 printf("Unexpected error trying to start the application!\n");
1096 fflush(stdout);
1097 exit(1);
1098 }
1099 // Create window with the registered class:
Cody Northrop39582252015-08-05 15:39:31 -06001100 RECT wr = { 0, 0, m_width, m_height };
1101 AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001102 m_window = CreateWindowEx(0,
1103 "Test", // class name
1104 "Test", // app name
1105 WS_OVERLAPPEDWINDOW | // window style
1106 WS_VISIBLE |
1107 WS_SYSMENU,
1108 100,100, // x/y coords
Cody Northrop39582252015-08-05 15:39:31 -06001109 wr.right - wr.left, // width
1110 wr.bottom - wr.top, // height
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001111 NULL, // handle to parent
1112 NULL, // handle to menu
1113 m_connection, // hInstance
1114 NULL); // no extra parameters
1115
1116 if (!m_window) {
1117 // It didn't work, so try to give a useful error:
1118 DWORD error = GetLastError();
1119 char message[120];
1120 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
1121 MessageBox(NULL, message, "Error", MB_OK);
1122 exit(1);
1123 }
Tony-LunarG399dfca2015-05-19 14:08:26 -06001124 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
1125 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001126}
1127#else
Tony Barbour6918cd52015-04-09 12:58:51 -06001128void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -07001129{
Chia-I Wuf8693382015-04-16 22:02:10 +08001130 const xcb_setup_t *setup;
1131 xcb_screen_iterator_t iter;
1132 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -07001133 uint32_t value_mask, value_list[32];
1134
Chia-I Wuf8693382015-04-16 22:02:10 +08001135 m_connection = xcb_connect(NULL, &scr);
1136
1137 setup = xcb_get_setup(m_connection);
1138 iter = xcb_setup_roots_iterator(setup);
1139 while (scr-- > 0)
1140 xcb_screen_next(&iter);
1141
1142 m_screen = iter.data;
1143
1144 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1145 it != m_images.end(); it++) {
1146 if (m_width < it->m_width)
1147 m_width = it->m_width;
1148 if (m_height < it->m_height)
1149 m_height = it->m_height;
1150 }
1151
1152 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -07001153
1154 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +08001155 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -07001156 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
1157 XCB_EVENT_MASK_EXPOSURE |
1158 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
1159
Chia-I Wuf8693382015-04-16 22:02:10 +08001160 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -07001161 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001162 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -07001163 0, 0, m_width, m_height, 0,
1164 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001165 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -07001166 value_mask, value_list);
1167
1168 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +08001169 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -07001170 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +08001171 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001172
Chia-I Wuf8693382015-04-16 22:02:10 +08001173 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
1174 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001175
Chia-I Wuf8693382015-04-16 22:02:10 +08001176 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -07001177 m_window, (*reply).atom, 4, 32, 1,
1178 &(*m_atom_wm_delete_window).atom);
1179 free(reply);
1180
Chia-I Wuf8693382015-04-16 22:02:10 +08001181 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -07001182}
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001183#endif
Tony Barbour96db8822015-02-25 12:28:39 -07001184
Tony Barbour6918cd52015-04-09 12:58:51 -06001185void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -07001186{
Ian Elliott7e40db92015-08-21 15:09:33 -06001187 m_fpDestroySwapchainKHR(m_device.handle(), m_swap_chain);
Tony Barbour9226a822015-10-23 10:58:56 -06001188
1189 for (uint32_t i = 0; i < m_swapchainImageCount; i++) {
Chia-I Wuf7458c52015-10-26 21:10:41 +08001190 vkDestroyImageView(m_device.handle(), m_buffers[i].view, NULL);
Tony Barbour9226a822015-10-23 10:58:56 -06001191 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001192#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +08001193 xcb_destroy_window(m_connection, m_window);
1194 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001195#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001196}
1197
Tony Barbour6918cd52015-04-09 12:58:51 -06001198void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001199{
1200 if (m_images.size() == 0) return;
1201
Chia-I Wuf8693382015-04-16 22:02:10 +08001202 vk_testing::Environment env;
1203 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -07001204 {
Chia-I Wuf8693382015-04-16 22:02:10 +08001205 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -07001206
Jon Ashburn07daee72015-05-21 18:13:33 -06001207 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001208 vkPresent.CreateMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -06001209 vkPresent.CreateSwapchain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001210 vkPresent.Run();
1211 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -07001212 }
Chia-I Wuf8693382015-04-16 22:02:10 +08001213 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001214}
1215
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001216//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001217// These are the default resources for TBuiltInResources, used for both
1218// - parsing this string for the case where the user didn't supply one
1219// - dumping out a template for user construction of a config file
1220//
1221static const char* DefaultConfig =
1222 "MaxLights 32\n"
1223 "MaxClipPlanes 6\n"
1224 "MaxTextureUnits 32\n"
1225 "MaxTextureCoords 32\n"
1226 "MaxVertexAttribs 64\n"
1227 "MaxVertexUniformComponents 4096\n"
1228 "MaxVaryingFloats 64\n"
1229 "MaxVertexTextureImageUnits 32\n"
1230 "MaxCombinedTextureImageUnits 80\n"
1231 "MaxTextureImageUnits 32\n"
1232 "MaxFragmentUniformComponents 4096\n"
1233 "MaxDrawBuffers 32\n"
1234 "MaxVertexUniformVectors 128\n"
1235 "MaxVaryingVectors 8\n"
1236 "MaxFragmentUniformVectors 16\n"
1237 "MaxVertexOutputVectors 16\n"
1238 "MaxFragmentInputVectors 15\n"
1239 "MinProgramTexelOffset -8\n"
1240 "MaxProgramTexelOffset 7\n"
1241 "MaxClipDistances 8\n"
1242 "MaxComputeWorkGroupCountX 65535\n"
1243 "MaxComputeWorkGroupCountY 65535\n"
1244 "MaxComputeWorkGroupCountZ 65535\n"
1245 "MaxComputeWorkGroupSizeX 1024\n"
1246 "MaxComputeWorkGroupSizeY 1024\n"
1247 "MaxComputeWorkGroupSizeZ 64\n"
1248 "MaxComputeUniformComponents 1024\n"
1249 "MaxComputeTextureImageUnits 16\n"
1250 "MaxComputeImageUniforms 8\n"
1251 "MaxComputeAtomicCounters 8\n"
1252 "MaxComputeAtomicCounterBuffers 1\n"
1253 "MaxVaryingComponents 60\n"
1254 "MaxVertexOutputComponents 64\n"
1255 "MaxGeometryInputComponents 64\n"
1256 "MaxGeometryOutputComponents 128\n"
1257 "MaxFragmentInputComponents 128\n"
1258 "MaxImageUnits 8\n"
1259 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
1260 "MaxCombinedShaderOutputResources 8\n"
1261 "MaxImageSamples 0\n"
1262 "MaxVertexImageUniforms 0\n"
1263 "MaxTessControlImageUniforms 0\n"
1264 "MaxTessEvaluationImageUniforms 0\n"
1265 "MaxGeometryImageUniforms 0\n"
1266 "MaxFragmentImageUniforms 8\n"
1267 "MaxCombinedImageUniforms 8\n"
1268 "MaxGeometryTextureImageUnits 16\n"
1269 "MaxGeometryOutputVertices 256\n"
1270 "MaxGeometryTotalOutputComponents 1024\n"
1271 "MaxGeometryUniformComponents 1024\n"
1272 "MaxGeometryVaryingComponents 64\n"
1273 "MaxTessControlInputComponents 128\n"
1274 "MaxTessControlOutputComponents 128\n"
1275 "MaxTessControlTextureImageUnits 16\n"
1276 "MaxTessControlUniformComponents 1024\n"
1277 "MaxTessControlTotalOutputComponents 4096\n"
1278 "MaxTessEvaluationInputComponents 128\n"
1279 "MaxTessEvaluationOutputComponents 128\n"
1280 "MaxTessEvaluationTextureImageUnits 16\n"
1281 "MaxTessEvaluationUniformComponents 1024\n"
1282 "MaxTessPatchComponents 120\n"
1283 "MaxPatchVertices 32\n"
1284 "MaxTessGenLevel 64\n"
1285 "MaxViewports 16\n"
1286 "MaxVertexAtomicCounters 0\n"
1287 "MaxTessControlAtomicCounters 0\n"
1288 "MaxTessEvaluationAtomicCounters 0\n"
1289 "MaxGeometryAtomicCounters 0\n"
1290 "MaxFragmentAtomicCounters 8\n"
1291 "MaxCombinedAtomicCounters 8\n"
1292 "MaxAtomicCounterBindings 1\n"
1293 "MaxVertexAtomicCounterBuffers 0\n"
1294 "MaxTessControlAtomicCounterBuffers 0\n"
1295 "MaxTessEvaluationAtomicCounterBuffers 0\n"
1296 "MaxGeometryAtomicCounterBuffers 0\n"
1297 "MaxFragmentAtomicCounterBuffers 1\n"
1298 "MaxCombinedAtomicCounterBuffers 1\n"
1299 "MaxAtomicCounterBufferSize 16384\n"
1300 "MaxTransformFeedbackBuffers 4\n"
1301 "MaxTransformFeedbackInterleavedComponents 64\n"
1302 "MaxCullDistances 8\n"
1303 "MaxCombinedClipAndCullDistances 8\n"
1304 "MaxSamples 4\n"
1305
1306 "nonInductiveForLoops 1\n"
1307 "whileLoops 1\n"
1308 "doWhileLoops 1\n"
1309 "generalUniformIndexing 1\n"
1310 "generalAttributeMatrixVectorIndexing 1\n"
1311 "generalVaryingIndexing 1\n"
1312 "generalSamplerIndexing 1\n"
1313 "generalVariableIndexing 1\n"
1314 "generalConstantMatrixVectorIndexing 1\n"
1315 ;
1316
1317//
1318// *.conf => this is a config file that can set limits/resources
1319//
Tony Barbour6918cd52015-04-09 12:58:51 -06001320bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001321{
1322 if (name.size() < 5)
1323 return false;
1324
1325 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
1326 ConfigFile = name;
1327 return true;
1328 }
1329
1330 return false;
1331}
1332
1333//
1334// Parse either a .conf file provided by the user or the default string above.
1335//
Tony Barbour6918cd52015-04-09 12:58:51 -06001336void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001337{
1338 char** configStrings = 0;
1339 char* config = 0;
1340 if (ConfigFile.size() > 0) {
1341 configStrings = ReadFileData(ConfigFile.c_str());
1342 if (configStrings)
1343 config = *configStrings;
1344 else {
1345 printf("Error opening configuration file; will instead use the default configuration\n");
1346 }
1347 }
1348
1349 if (config == 0) {
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001350 config = (char *) alloca(strlen(DefaultConfig) + 1);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001351 strcpy(config, DefaultConfig);
1352 }
1353
1354 const char* delims = " \t\n\r";
1355 const char* token = strtok(config, delims);
1356 while (token) {
1357 const char* valueStr = strtok(0, delims);
1358 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1359 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1360 return;
1361 }
1362 int value = atoi(valueStr);
1363
1364 if (strcmp(token, "MaxLights") == 0)
1365 Resources.maxLights = value;
1366 else if (strcmp(token, "MaxClipPlanes") == 0)
1367 Resources.maxClipPlanes = value;
1368 else if (strcmp(token, "MaxTextureUnits") == 0)
1369 Resources.maxTextureUnits = value;
1370 else if (strcmp(token, "MaxTextureCoords") == 0)
1371 Resources.maxTextureCoords = value;
1372 else if (strcmp(token, "MaxVertexAttribs") == 0)
1373 Resources.maxVertexAttribs = value;
1374 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1375 Resources.maxVertexUniformComponents = value;
1376 else if (strcmp(token, "MaxVaryingFloats") == 0)
1377 Resources.maxVaryingFloats = value;
1378 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1379 Resources.maxVertexTextureImageUnits = value;
1380 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1381 Resources.maxCombinedTextureImageUnits = value;
1382 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1383 Resources.maxTextureImageUnits = value;
1384 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1385 Resources.maxFragmentUniformComponents = value;
1386 else if (strcmp(token, "MaxDrawBuffers") == 0)
1387 Resources.maxDrawBuffers = value;
1388 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1389 Resources.maxVertexUniformVectors = value;
1390 else if (strcmp(token, "MaxVaryingVectors") == 0)
1391 Resources.maxVaryingVectors = value;
1392 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1393 Resources.maxFragmentUniformVectors = value;
1394 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1395 Resources.maxVertexOutputVectors = value;
1396 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1397 Resources.maxFragmentInputVectors = value;
1398 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1399 Resources.minProgramTexelOffset = value;
1400 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1401 Resources.maxProgramTexelOffset = value;
1402 else if (strcmp(token, "MaxClipDistances") == 0)
1403 Resources.maxClipDistances = value;
1404 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1405 Resources.maxComputeWorkGroupCountX = value;
1406 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1407 Resources.maxComputeWorkGroupCountY = value;
1408 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1409 Resources.maxComputeWorkGroupCountZ = value;
1410 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1411 Resources.maxComputeWorkGroupSizeX = value;
1412 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1413 Resources.maxComputeWorkGroupSizeY = value;
1414 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1415 Resources.maxComputeWorkGroupSizeZ = value;
1416 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1417 Resources.maxComputeUniformComponents = value;
1418 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1419 Resources.maxComputeTextureImageUnits = value;
1420 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1421 Resources.maxComputeImageUniforms = value;
1422 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1423 Resources.maxComputeAtomicCounters = value;
1424 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1425 Resources.maxComputeAtomicCounterBuffers = value;
1426 else if (strcmp(token, "MaxVaryingComponents") == 0)
1427 Resources.maxVaryingComponents = value;
1428 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1429 Resources.maxVertexOutputComponents = value;
1430 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1431 Resources.maxGeometryInputComponents = value;
1432 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1433 Resources.maxGeometryOutputComponents = value;
1434 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1435 Resources.maxFragmentInputComponents = value;
1436 else if (strcmp(token, "MaxImageUnits") == 0)
1437 Resources.maxImageUnits = value;
1438 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1439 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1440 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1441 Resources.maxCombinedShaderOutputResources = value;
1442 else if (strcmp(token, "MaxImageSamples") == 0)
1443 Resources.maxImageSamples = value;
1444 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1445 Resources.maxVertexImageUniforms = value;
1446 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1447 Resources.maxTessControlImageUniforms = value;
1448 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1449 Resources.maxTessEvaluationImageUniforms = value;
1450 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1451 Resources.maxGeometryImageUniforms = value;
1452 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1453 Resources.maxFragmentImageUniforms = value;
1454 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1455 Resources.maxCombinedImageUniforms = value;
1456 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1457 Resources.maxGeometryTextureImageUnits = value;
1458 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1459 Resources.maxGeometryOutputVertices = value;
1460 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1461 Resources.maxGeometryTotalOutputComponents = value;
1462 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1463 Resources.maxGeometryUniformComponents = value;
1464 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1465 Resources.maxGeometryVaryingComponents = value;
1466 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1467 Resources.maxTessControlInputComponents = value;
1468 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1469 Resources.maxTessControlOutputComponents = value;
1470 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1471 Resources.maxTessControlTextureImageUnits = value;
1472 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1473 Resources.maxTessControlUniformComponents = value;
1474 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1475 Resources.maxTessControlTotalOutputComponents = value;
1476 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1477 Resources.maxTessEvaluationInputComponents = value;
1478 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1479 Resources.maxTessEvaluationOutputComponents = value;
1480 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1481 Resources.maxTessEvaluationTextureImageUnits = value;
1482 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1483 Resources.maxTessEvaluationUniformComponents = value;
1484 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1485 Resources.maxTessPatchComponents = value;
1486 else if (strcmp(token, "MaxPatchVertices") == 0)
1487 Resources.maxPatchVertices = value;
1488 else if (strcmp(token, "MaxTessGenLevel") == 0)
1489 Resources.maxTessGenLevel = value;
1490 else if (strcmp(token, "MaxViewports") == 0)
1491 Resources.maxViewports = value;
1492 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1493 Resources.maxVertexAtomicCounters = value;
1494 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1495 Resources.maxTessControlAtomicCounters = value;
1496 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1497 Resources.maxTessEvaluationAtomicCounters = value;
1498 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1499 Resources.maxGeometryAtomicCounters = value;
1500 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1501 Resources.maxFragmentAtomicCounters = value;
1502 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1503 Resources.maxCombinedAtomicCounters = value;
1504 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1505 Resources.maxAtomicCounterBindings = value;
1506 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1507 Resources.maxVertexAtomicCounterBuffers = value;
1508 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1509 Resources.maxTessControlAtomicCounterBuffers = value;
1510 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1511 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1512 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1513 Resources.maxGeometryAtomicCounterBuffers = value;
1514 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1515 Resources.maxFragmentAtomicCounterBuffers = value;
1516 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1517 Resources.maxCombinedAtomicCounterBuffers = value;
1518 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1519 Resources.maxAtomicCounterBufferSize = value;
1520 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1521 Resources.maxTransformFeedbackBuffers = value;
1522 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1523 Resources.maxTransformFeedbackInterleavedComponents = value;
1524 else if (strcmp(token, "MaxCullDistances") == 0)
1525 Resources.maxCullDistances = value;
1526 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1527 Resources.maxCombinedClipAndCullDistances = value;
1528 else if (strcmp(token, "MaxSamples") == 0)
1529 Resources.maxSamples = value;
1530
1531 else if (strcmp(token, "nonInductiveForLoops") == 0)
1532 Resources.limits.nonInductiveForLoops = (value != 0);
1533 else if (strcmp(token, "whileLoops") == 0)
1534 Resources.limits.whileLoops = (value != 0);
1535 else if (strcmp(token, "doWhileLoops") == 0)
1536 Resources.limits.doWhileLoops = (value != 0);
1537 else if (strcmp(token, "generalUniformIndexing") == 0)
1538 Resources.limits.generalUniformIndexing = (value != 0);
1539 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1540 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1541 else if (strcmp(token, "generalVaryingIndexing") == 0)
1542 Resources.limits.generalVaryingIndexing = (value != 0);
1543 else if (strcmp(token, "generalSamplerIndexing") == 0)
1544 Resources.limits.generalSamplerIndexing = (value != 0);
1545 else if (strcmp(token, "generalVariableIndexing") == 0)
1546 Resources.limits.generalVariableIndexing = (value != 0);
1547 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1548 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1549 else
1550 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1551
1552 token = strtok(0, delims);
1553 }
1554 if (configStrings)
1555 FreeFileData(configStrings);
1556}
1557
Tony Barbour6918cd52015-04-09 12:58:51 -06001558void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001559{
1560 if (m_compile_options & EOptionRelaxedErrors)
1561 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1562 if (m_compile_options & EOptionIntermediate)
1563 messages = (EShMessages)(messages | EShMsgAST);
1564 if (m_compile_options & EOptionSuppressWarnings)
1565 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1566}
1567
1568//
1569// Malloc a string of sufficient size and read a string into it.
1570//
Tony Barbour6918cd52015-04-09 12:58:51 -06001571char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001572{
1573 FILE *in;
1574 #if defined(_WIN32) && defined(__GNUC__)
1575 in = fopen(fileName, "r");
1576 int errorCode = in ? 0 : 1;
1577 #else
1578 int errorCode = fopen_s(&in, fileName, "r");
1579 #endif
1580
1581 char *fdata;
1582 int count = 0;
1583 const int maxSourceStrings = 5;
1584 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1585
1586 if (errorCode) {
1587 printf("Error: unable to open input file: %s\n", fileName);
1588 return 0;
1589 }
1590
1591 while (fgetc(in) != EOF)
1592 count++;
1593
1594 fseek(in, 0, SEEK_SET);
1595
1596 if (!(fdata = (char*)malloc(count+2))) {
1597 printf("Error allocating memory\n");
1598 return 0;
1599 }
1600 if (fread(fdata,1,count, in)!=count) {
1601 printf("Error reading input file: %s\n", fileName);
1602 return 0;
1603 }
1604 fdata[count] = '\0';
1605 fclose(in);
1606 if (count == 0) {
1607 return_data[0]=(char*)malloc(count+2);
1608 return_data[0][0]='\0';
1609 m_num_shader_strings = 0;
1610 return return_data;
1611 } else
1612 m_num_shader_strings = 1;
1613
1614 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1615 int ptr_len=0,i=0;
1616 while(count>0){
1617 return_data[i]=(char*)malloc(len+2);
1618 memcpy(return_data[i],fdata+ptr_len,len);
1619 return_data[i][len]='\0';
1620 count-=(len);
1621 ptr_len+=(len);
1622 if(count<len){
1623 if(count==0){
1624 m_num_shader_strings=(i+1);
1625 break;
1626 }
1627 len = count;
1628 }
1629 ++i;
1630 }
1631 return return_data;
1632}
1633
Tony Barbour6918cd52015-04-09 12:58:51 -06001634void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001635{
1636 for(int i=0;i<m_num_shader_strings;i++)
1637 free(data[i]);
1638}
1639
1640//
1641// Deduce the language from the filename. Files must end in one of the
1642// following extensions:
1643//
1644// .vert = vertex
1645// .tesc = tessellation control
1646// .tese = tessellation evaluation
1647// .geom = geometry
1648// .frag = fragment
1649// .comp = compute
1650//
Tony Barbour6918cd52015-04-09 12:58:51 -06001651EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001652{
1653 size_t ext = name.rfind('.');
1654 if (ext == std::string::npos) {
1655 return EShLangVertex;
1656 }
1657
1658 std::string suffix = name.substr(ext + 1, std::string::npos);
1659 if (suffix == "vert")
1660 return EShLangVertex;
1661 else if (suffix == "tesc")
1662 return EShLangTessControl;
1663 else if (suffix == "tese")
1664 return EShLangTessEvaluation;
1665 else if (suffix == "geom")
1666 return EShLangGeometry;
1667 else if (suffix == "frag")
1668 return EShLangFragment;
1669 else if (suffix == "comp")
1670 return EShLangCompute;
1671
1672 return EShLangVertex;
1673}
1674
1675//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001676// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001677//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001678EShLanguage VkTestFramework::FindLanguage(const VkShaderStageFlagBits shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001679{
1680 switch (shader_type) {
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001681 case VK_SHADER_STAGE_VERTEX_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001682 return EShLangVertex;
1683
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001684 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001685 return EShLangTessControl;
1686
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001687 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001688 return EShLangTessEvaluation;
1689
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001690 case VK_SHADER_STAGE_GEOMETRY_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001691 return EShLangGeometry;
1692
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001693 case VK_SHADER_STAGE_FRAGMENT_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001694 return EShLangFragment;
1695
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001696 case VK_SHADER_STAGE_COMPUTE_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001697 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001698
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001699 default:
1700 return EShLangVertex;
1701 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001702}
1703
1704
1705//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001706// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001707// Return value of false means an error was encountered.
1708//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001709bool VkTestFramework::GLSLtoSPV(const VkShaderStageFlagBits shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001710 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001711 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001712{
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001713 glslang::TProgram program;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001714 const char *shaderStrings[1];
1715
1716 // TODO: Do we want to load a special config file depending on the
1717 // shader source? Optional name maybe?
1718 // SetConfigFile(fileName);
1719
1720 ProcessConfigFile();
1721
1722 EShMessages messages = EShMsgDefault;
1723 SetMessageOptions(messages);
1724
1725 EShLanguage stage = FindLanguage(shader_type);
1726 glslang::TShader* shader = new glslang::TShader(stage);
1727
1728 shaderStrings[0] = pshader;
1729 shader->setStrings(shaderStrings, 1);
1730
1731 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1732
Cody Northrop195d6622014-11-03 12:54:37 -07001733 if (! (m_compile_options & EOptionSuppressInfolog)) {
1734 puts(shader->getInfoLog());
1735 puts(shader->getInfoDebugLog());
1736 }
1737
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001738 return false; // something didn't work
1739 }
1740
1741 program.addShader(shader);
1742
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001743
1744 //
1745 // Program-level processing...
1746 //
1747
Cody Northrop195d6622014-11-03 12:54:37 -07001748 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001749
Cody Northrop195d6622014-11-03 12:54:37 -07001750 if (! (m_compile_options & EOptionSuppressInfolog)) {
1751 puts(shader->getInfoLog());
1752 puts(shader->getInfoDebugLog());
1753 }
1754
1755 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001756 }
1757
1758 if (m_compile_options & EOptionDumpReflection) {
1759 program.buildReflection();
1760 program.dumpReflection();
1761 }
1762
Cody Northrop5a95b472015-06-03 13:01:54 -06001763 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1764
1765 //
1766 // Test the different modes of SPIR-V modification
1767 //
1768 if (this->m_canonicalize_spv) {
1769 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1770 }
1771
1772 if (this->m_strip_spv) {
1773 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1774 }
1775
1776 if (this->m_do_everything_spv) {
1777 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1778 }
1779
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001780 delete shader;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001781
1782 return true;
1783}
1784
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001785
1786
Tony Barbour6918cd52015-04-09 12:58:51 -06001787VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001788 m_width( 0 ),
1789 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001790 m_data( NULL ),
1791 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001792{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001793}
1794
Tony Barbour6918cd52015-04-09 12:58:51 -06001795VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001796{
1797
1798}
1799
Tony Barbour6918cd52015-04-09 12:58:51 -06001800VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001801{
1802 m_title = copyin.m_title;
1803 m_width = copyin.m_width;
1804 m_height = copyin.m_height;
1805 m_data_size = copyin.m_data_size;
1806 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1807}
1808
Tony Barbour6918cd52015-04-09 12:58:51 -06001809ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001810{
Tony Barbour6918cd52015-04-09 12:58:51 -06001811 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1812 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001813 return output;
1814}
1815
Tony Barbour6918cd52015-04-09 12:58:51 -06001816VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001817{
1818 m_title = rhs.m_title;
1819 m_width = rhs.m_width;
1820 m_height = rhs.m_height;
1821 m_data_size = rhs.m_data_size;
1822 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001823 return *this;
1824}
1825
Tony Barbour6918cd52015-04-09 12:58:51 -06001826int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001827{
1828 if( this->m_data != rhs.m_data) return 0;
1829 return 1;
1830}
1831
1832// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001833int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001834{
1835 if( this->m_data_size < rhs.m_data_size ) return 1;
1836 return 0;
1837}
1838