blob: c5882644b2ce69e665898098d5495d26feaa0bd7 [file] [log] [blame]
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001// VK tests
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06002//
3// Copyright (C) 2014 LunarG, Inc.
4//
5// Permission is hereby granted, free of charge, to any person obtaining a
6// copy of this software and associated documentation files (the "Software"),
7// to deal in the Software without restriction, including without limitation
8// the rights to use, copy, modify, merge, publish, distribute, sublicense,
9// and/or sell copies of the Software, and to permit persons to whom the
10// Software is furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included
13// in all copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21// DEALINGS IN THE SOFTWARE.
22
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060023#include "vktestframework.h"
24#include "vkrenderframework.h"
Cody Northrop5a95b472015-06-03 13:01:54 -060025#include "SPIRV/GlslangToSpv.h"
26#include "SPIRV/SPVRemapper.h"
Tony Barbour4ab45422014-12-10 17:00:20 -070027#include <limits.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060028#include <math.h>
Chia-I Wuec664fa2014-12-02 11:54:24 +080029#include <wand/MagickWand.h>
Tony Barbourfeb61962015-09-21 15:17:33 -060030#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +080031#include <xcb/xcb.h>
Tony Barbourfeb61962015-09-21 15:17:33 -060032#endif
Ian Elliott7e40db92015-08-21 15:09:33 -060033#include "vk_ext_khr_swapchain.h"
34#include "vk_ext_khr_device_swapchain.h"
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060035
Tony Barbour3d69c9e2015-05-20 16:53:31 -060036#if defined(PATH_MAX) && !defined(MAX_PATH)
37#define MAX_PATH PATH_MAX
38#endif
39
Tony Barbour6a3faf02015-07-23 10:36:18 -060040#ifdef _WIN32
41#define ERR_EXIT(err_msg, err_class) \
42 do { \
43 MessageBox(NULL, err_msg, err_class, MB_OK); \
44 exit(1); \
45 } while (0)
46#else // _WIN32
47
48#define ERR_EXIT(err_msg, err_class) \
49 do { \
50 printf(err_msg); \
51 fflush(stdout); \
52 exit(1); \
53 } while (0)
54#endif // _WIN32
55
56#define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \
57{ \
58 m_fp##entrypoint = (PFN_vk##entrypoint) vkGetInstanceProcAddr(inst, "vk"#entrypoint); \
59 if (m_fp##entrypoint == NULL) { \
60 ERR_EXIT("vkGetInstanceProcAddr failed to find vk"#entrypoint, \
61 "vkGetInstanceProcAddr Failure"); \
62 } \
63}
64
65#define GET_DEVICE_PROC_ADDR(dev, entrypoint) \
66{ \
67 m_fp##entrypoint = (PFN_vk##entrypoint) vkGetDeviceProcAddr(dev, "vk"#entrypoint); \
68 if (m_fp##entrypoint == NULL) { \
69 ERR_EXIT("vkGetDeviceProcAddr failed to find vk"#entrypoint, \
70 "vkGetDeviceProcAddr Failure"); \
71 } \
72}
73
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060074// Command-line options
75enum TOptions {
76 EOptionNone = 0x000,
77 EOptionIntermediate = 0x001,
78 EOptionSuppressInfolog = 0x002,
79 EOptionMemoryLeakMode = 0x004,
80 EOptionRelaxedErrors = 0x008,
81 EOptionGiveWarnings = 0x010,
82 EOptionLinkProgram = 0x020,
83 EOptionMultiThreaded = 0x040,
84 EOptionDumpConfig = 0x080,
85 EOptionDumpReflection = 0x100,
86 EOptionSuppressWarnings = 0x200,
87 EOptionDumpVersions = 0x400,
Cody Northrop3bfd27c2015-03-17 15:55:58 -060088 EOptionSpv = 0x800,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060089 EOptionDefaultDesktop = 0x1000,
90};
91
Ian Elliott7e40db92015-08-21 15:09:33 -060092typedef struct _SwapchainBuffers {
Tony Barbour6a3faf02015-07-23 10:36:18 -060093 VkImage image;
94 VkCmdBuffer cmd;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -060095 VkImageView view;
Ian Elliott7e40db92015-08-21 15:09:33 -060096} SwapchainBuffers;
Tony Barbour6a3faf02015-07-23 10:36:18 -060097
Chia-I Wuf8693382015-04-16 22:02:10 +080098class TestFrameworkVkPresent
99{
100public:
101 TestFrameworkVkPresent(vk_testing::Device &device);
102
103 void Run();
Jon Ashburn07daee72015-05-21 18:13:33 -0600104 void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst);
Chia-I Wuf8693382015-04-16 22:02:10 +0800105 void CreateMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -0600106 void CreateSwapchain();
Tony Barbourbd094ce2015-10-23 11:00:15 -0600107 void SetImageLayout(VkImage image, VkImageAspectFlags aspectMask,
108 VkImageLayout old_image_layout, VkImageLayout new_image_layout);
Chia-I Wuf8693382015-04-16 22:02:10 +0800109 void TearDown();
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600110#ifdef _WIN32
111 static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
112#endif
113
Chia-I Wuf8693382015-04-16 22:02:10 +0800114
115protected:
116 vk_testing::Device &m_device;
117 vk_testing::Queue &m_queue;
Dana Jansens233a0ea2015-07-30 13:04:16 -0700118 vk_testing::CmdPool m_cmdpool;
Chia-I Wuf8693382015-04-16 22:02:10 +0800119 vk_testing::CmdBuffer m_cmdbuf;
120
121private:
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600122#ifdef _WIN32
123 HINSTANCE m_connection; // hInstance - Windows Instance
124 HWND m_window; // hWnd - window handle
125
126#else
Chia-I Wuf8693382015-04-16 22:02:10 +0800127 xcb_connection_t *m_connection;
128 xcb_screen_t *m_screen;
129 xcb_window_t m_window;
130 xcb_intern_atom_reply_t *m_atom_wm_delete_window;
Ian Elliott7e40db92015-08-21 15:09:33 -0600131 VkPlatformHandleXcbKHR m_platform_handle_xcb;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600132#endif
Courtney Goeltzenleuchterd6079ec2015-04-22 10:09:35 -0600133 std::list<VkTestImageRecord> m_images;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600134 uint32_t m_present_queue_node_index;
Chia-I Wuf8693382015-04-16 22:02:10 +0800135
Ian Elliott7e40db92015-08-21 15:09:33 -0600136 PFN_vkGetPhysicalDeviceSurfaceSupportKHR m_fpGetPhysicalDeviceSurfaceSupportKHR;
137 PFN_vkGetSurfacePropertiesKHR m_fpGetSurfacePropertiesKHR;
138 PFN_vkGetSurfaceFormatsKHR m_fpGetSurfaceFormatsKHR;
139 PFN_vkGetSurfacePresentModesKHR m_fpGetSurfacePresentModesKHR;
140 PFN_vkCreateSwapchainKHR m_fpCreateSwapchainKHR;
141 PFN_vkDestroySwapchainKHR m_fpDestroySwapchainKHR;
142 PFN_vkGetSwapchainImagesKHR m_fpGetSwapchainImagesKHR;
143 PFN_vkAcquireNextImageKHR m_fpAcquireNextImageKHR;
144 PFN_vkQueuePresentKHR m_fpQueuePresentKHR;
145 VkSurfaceDescriptionWindowKHR m_surface_description;
146 uint32_t m_swapchainImageCount;
147 VkSwapchainKHR m_swap_chain;
148 SwapchainBuffers *m_buffers;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600149 VkFormat m_format;
Ian Elliott7e40db92015-08-21 15:09:33 -0600150 VkColorSpaceKHR m_color_space;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600151
152 uint32_t m_current_buffer;
Chia-I Wuf8693382015-04-16 22:02:10 +0800153
154 bool m_quit;
155 bool m_pause;
156
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600157 int m_width;
158 int m_height;
Chia-I Wuf8693382015-04-16 22:02:10 +0800159
160 std::list<VkTestImageRecord>::iterator m_display_image;
161
162 void Display();
Tony Barbourfeb61962015-09-21 15:17:33 -0600163#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800164 void HandleEvent(xcb_generic_event_t *event);
Tony Barbourfeb61962015-09-21 15:17:33 -0600165#endif
Chia-I Wuf8693382015-04-16 22:02:10 +0800166};
167
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600168#ifndef _WIN32
169
170#include <errno.h>
171
172int fopen_s(
173 FILE** pFile,
174 const char* filename,
175 const char* mode
176)
177{
178 if (!pFile || !filename || !mode) {
179 return EINVAL;
180 }
181
182 FILE* f = fopen(filename, mode);
183 if (! f) {
184 if (errno != 0) {
185 return errno;
186 } else {
187 return ENOENT;
188 }
189 }
190 *pFile = f;
191
192 return 0;
193}
194
195#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600196
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600197
198
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600199// Set up environment for GLSL compiler
200// Must be done once per process
201void TestEnvironment::SetUp()
202{
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600203 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600204 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800205
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600206 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600207}
208
209void TestEnvironment::TearDown()
210{
211 glslang::FinalizeProcess();
212}
213
Tony Barbour6918cd52015-04-09 12:58:51 -0600214VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600215 m_compile_options( 0 ),
216 m_num_shader_strings( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600217{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600218
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600219}
220
Tony Barbour6918cd52015-04-09 12:58:51 -0600221VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600222{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600223
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600224}
225
226// Define all the static elements
Cody Northropa3673cf2015-06-09 13:00:45 -0600227bool VkTestFramework::m_show_images = false;
228bool VkTestFramework::m_save_images = false;
229bool VkTestFramework::m_compare_images = false;
230bool VkTestFramework::m_use_glsl = false;
231bool VkTestFramework::m_canonicalize_spv = false;
232bool VkTestFramework::m_strip_spv = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600233bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour6918cd52015-04-09 12:58:51 -0600234int VkTestFramework::m_width = 0;
235int VkTestFramework::m_height = 0;
236std::list<VkTestImageRecord> VkTestFramework::m_images;
237std::list<VkTestImageRecord>::iterator VkTestFramework::m_display_image;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600238int m_display_image_idx = 0;
239
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600240bool VkTestFramework::optionMatch(const char* option, char* optionLine)
241{
242 if (strncmp(option, optionLine, strlen(option)) == 0)
243 return true;
244 else
245 return false;
246}
247
Tony Barbour6918cd52015-04-09 12:58:51 -0600248void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600249{
250 int i, n;
251
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600252 for (i=1, n=1; i< *argc; i++) {
253 if (optionMatch("--show-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600254 m_show_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600255 else if (optionMatch("--save-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600256 m_save_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600257 else if (optionMatch("--no-SPV", argv[i]))
258 m_use_glsl = true;
259 else if (optionMatch("--strip-SPV", argv[i]))
260 m_strip_spv = true;
261 else if (optionMatch("--canonicalize-SPV", argv[i]))
262 m_canonicalize_spv = true;
263 else if (optionMatch("--compare-images", argv[i]))
Tony Barbour247bf372014-10-30 14:29:04 -0600264 m_compare_images = true;
Tony Barbour247bf372014-10-30 14:29:04 -0600265
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600266 else if (optionMatch("--help", argv[i]) ||
267 optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700268 printf("\nOther options:\n");
269 printf("\t--show-images\n"
270 "\t\tDisplay test images in viewer after tests complete.\n");
271 printf("\t--save-images\n"
272 "\t\tSave tests images as ppm files in current working directory.\n"
273 "\t\tUsed to generate golden images for compare-images.\n");
274 printf("\t--compare-images\n"
275 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barboura98d3932014-12-11 09:52:49 -0700276 "\t\tAlso saves the generated test image in current working\n"
277 "\t\t\tdirectory but only if the image is different from the golden\n"
278 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
279 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700280 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600281 printf("\t--no-SPV\n"
282 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600283 printf("\t--strip-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600284 "\t\tStrip SPIR-V debug information (line numbers, names, etc).\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600285 printf("\t--canonicalize-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600286 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600287 exit(0);
288 } else {
289 printf("\nUnrecognized option: %s\n", argv[i]);
290 printf("\nUse --help or -h for option list.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700291 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700292 }
293
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600294 /*
295 * Since the above "consume" inputs, update argv
296 * so that it contains the trimmed list of args for glutInit
297 */
298
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600299 argv[n] = argv[i];
300 n++;
301 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600302}
303
Tony Barbour6918cd52015-04-09 12:58:51 -0600304void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600305{
306 string filename;
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600307 uint32_t x, y;
Tony Barbour6918cd52015-04-09 12:58:51 -0600308 VkImageObj displayImage(image->device());
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600309 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbour84d448c2015-04-02 14:02:33 -0600310
Tony Barboure65788f2015-07-21 17:01:42 -0600311 displayImage.init(image->extent().width, image->extent().height, image->format(), VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT, VK_IMAGE_TILING_LINEAR, reqs);
Tony Barbour84d448c2015-04-02 14:02:33 -0600312 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600313
314 filename.append(basename);
315 filename.append(".ppm");
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600316
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600317 const VkImageSubresource sr = {
Courtney Goeltzenleuchter908e7672015-10-21 17:00:51 -0600318 VK_IMAGE_ASPECT_COLOR_BIT, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600319 };
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600320 VkSubresourceLayout sr_layout;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600321
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600322 vkGetImageSubresourceLayout(image->device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600323
Tony Barbour84d448c2015-04-02 14:02:33 -0600324 char *ptr;
Chia-I Wu681d7a02015-07-03 13:44:34 +0800325 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600326 ptr += sr_layout.offset;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600327 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600328 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
329
330 file << "P6\n";
Tony Barbourfeb61962015-09-21 15:17:33 -0600331 file << displayImage.width() << " ";
Tony Barbour84d448c2015-04-02 14:02:33 -0600332 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600333 file << 255 << "\n";
334
Tony Barbour84d448c2015-04-02 14:02:33 -0600335 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700336 const int *row = (const int *) ptr;
337 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600338
Tony Barbourd1c35722015-04-16 15:59:00 -0600339 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700340 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600341 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700342 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
343 file.write((char *) &swapped, 3);
344 row++;
345 }
346 }
Tony Barbourd1c35722015-04-16 15:59:00 -0600347 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700348 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600349 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700350 file.write((char *) row, 3);
351 row++;
352 }
353 }
354 else {
355 printf("Unrecognized image format - will not write image files");
356 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600357 }
358
359 ptr += sr_layout.rowPitch;
360 }
361
362 file.close();
Chia-I Wu681d7a02015-07-03 13:44:34 +0800363 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600364}
365
Tony Barbour6918cd52015-04-09 12:58:51 -0600366void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour247bf372014-10-30 14:29:04 -0600367{
368
369 MagickWand *magick_wand_1;
370 MagickWand *magick_wand_2;
371 MagickWand *compare_wand;
372 MagickBooleanType status;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600373 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600374 double differenz;
375
Tony Barbour4ab45422014-12-10 17:00:20 -0700376 if (getenv("RENDERTEST_GOLDEN_DIR"))
377 {
378 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
379 }
380
Tony Barbour247bf372014-10-30 14:29:04 -0600381 MagickWandGenesis();
382 magick_wand_1=NewMagickWand();
383 sprintf(testimage,"%s.ppm",basename);
384 status=MagickReadImage(magick_wand_1,testimage);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600385 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour247bf372014-10-30 14:29:04 -0600386
387
388 MagickWandGenesis();
389 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700390 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600391 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600392 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour247bf372014-10-30 14:29:04 -0600393
Tony Barbour247bf372014-10-30 14:29:04 -0600394 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
395 if (differenz != 0.0)
396 {
397 char difference[256];
398
399 sprintf(difference,"%s-diff.ppm",basename);
400 status = MagickWriteImage(compare_wand, difference);
401 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
402 }
403 DestroyMagickWand(compare_wand);
404
405 DestroyMagickWand(magick_wand_1);
406 DestroyMagickWand(magick_wand_2);
407 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700408
409 if (differenz == 0.0)
410 {
411 /*
412 * If test image and golden image match, we do not need to
413 * keep around the test image.
414 */
415 remove(testimage);
416 }
Tony Barbour247bf372014-10-30 14:29:04 -0600417}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600418
Tony Barbour6918cd52015-04-09 12:58:51 -0600419void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600420{
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600421 VkResult err;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600422 VkSubresourceLayout sr_layout;
423 char *ptr;
424 VkTestImageRecord record;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600425 VkImageObj displayImage(image->device());
426 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
427
Cody Northropc9a69912015-06-18 17:05:15 -0600428 displayImage.init(image->extent().width, image->extent().height, image->format(), VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT, VK_IMAGE_TILING_LINEAR, reqs);
429
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600430 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600431
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600432 const VkImageSubresource sr = {
Courtney Goeltzenleuchter908e7672015-10-21 17:00:51 -0600433 VK_IMAGE_ASPECT_COLOR_BIT, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600434 };
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600435
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600436 vkGetImageSubresourceLayout(displayImage.device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600437
Chia-I Wu681d7a02015-07-03 13:44:34 +0800438 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600439 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600440
441 ptr += sr_layout.offset;
442
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600443 record.m_title.append(comment);
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600444 record.m_width = displayImage.width();
445 record.m_height = displayImage.height();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600446 // TODO: Need to make this more robust to handle different image formats
Tony-LunarG399dfca2015-05-19 14:08:26 -0600447 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600448 record.m_data = malloc(record.m_data_size);
449 memcpy(record.m_data, ptr, record.m_data_size);
450 m_images.push_back(record);
451 m_display_image = --m_images.end();
452
Chia-I Wu681d7a02015-07-03 13:44:34 +0800453 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600454}
455
Tony Barbour6918cd52015-04-09 12:58:51 -0600456void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600457{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600458 for (int32_t i = 0; i < images.size(); i++) {
459 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600460 }
461}
462
Tony Barbour6918cd52015-04-09 12:58:51 -0600463void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600464{
465 const ::testing::TestInfo* const test_info =
466 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600467 ostringstream filestream;
468 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600469
Tony Barbour247bf372014-10-30 14:29:04 -0600470 m_width = 40;
471
472 if (strcmp(test_info->name(), m_testName.c_str())) {
473 filestream << test_info->name();
474 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700475 m_frameNum = 2;
476 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600477 }
478 else {
479 filestream << test_info->name() << "-" << m_frameNum;
480 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700481 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600482 }
483
Tony Barbour247bf372014-10-30 14:29:04 -0600484 // ToDo - scrub string for bad characters
485
486 if (m_save_images || m_compare_images) {
487 WritePPM(filename.c_str(), image);
488 if (m_compare_images) {
489 Compare(filename.c_str(), image);
490 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600491 }
492
493 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600494 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600495 }
496}
497
Chia-I Wuf8693382015-04-16 22:02:10 +0800498TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
499 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700500 m_queue(*m_device.graphics_queues()[0]),
Dana Jansens233a0ea2015-07-30 13:04:16 -0700501 m_cmdpool(m_device, vk_testing::CmdPool::create_info(m_device.graphics_queue_node_index_)),
502 m_cmdbuf(m_device, vk_testing::CmdBuffer::create_info(m_cmdpool.handle()))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600503{
Tony Barbour96db8822015-02-25 12:28:39 -0700504 m_quit = false;
505 m_pause = false;
506 m_width = 0;
507 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600508}
509
Tony Barbour6918cd52015-04-09 12:58:51 -0600510void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600511{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600512 VkResult U_ASSERT_ONLY err;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600513 vk_testing::Buffer buf;
514 void *dest_ptr;
515
Tony Barbour6a3faf02015-07-23 10:36:18 -0600516 VkSemaphore presentCompleteSemaphore;
517 VkSemaphoreCreateInfo presentCompleteSemaphoreCreateInfo = {};
518 presentCompleteSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
519 presentCompleteSemaphoreCreateInfo.pNext = NULL;
520 presentCompleteSemaphoreCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
521
522
523 err = vkCreateSemaphore(m_device.handle(),
524 &presentCompleteSemaphoreCreateInfo,
525 &presentCompleteSemaphore);
526 assert(!err);
527
528 // Get the index of the next available swapchain image:
Ian Elliott7e40db92015-08-21 15:09:33 -0600529 err = m_fpAcquireNextImageKHR(m_device.handle(), m_swap_chain,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600530 UINT64_MAX,
531 presentCompleteSemaphore,
532 &m_current_buffer);
Ian Elliott7e40db92015-08-21 15:09:33 -0600533 // TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
Tony Barbour6a3faf02015-07-23 10:36:18 -0600534 // return codes
535 assert(!err);
536
537 // Wait for the present complete semaphore to be signaled to ensure
538 // that the image won't be rendered to until the presentation
539 // engine has fully released ownership to the application, and it is
540 // okay to render to the image.
541 vkQueueWaitSemaphore(m_queue.handle(), presentCompleteSemaphore);
Tony Barbour9226a822015-10-23 10:58:56 -0600542 vkDestroySemaphore(m_device.handle(), presentCompleteSemaphore);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600543
544 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Cody Northrop7fb43862015-06-22 14:56:14 -0600545 buf.init_as_src(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800546 dest_ptr = buf.memory().map();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600547 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800548 buf.memory().unmap();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600549
550 m_cmdbuf.begin();
Tony Barbourbd094ce2015-10-23 11:00:15 -0600551 VkImageMemoryBarrier memoryBarrier = {};
552 memoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
553 memoryBarrier.pNext = NULL;
554 memoryBarrier.outputMask = VK_MEMORY_OUTPUT_COLOR_ATTACHMENT_BIT;
555 memoryBarrier.inputMask = 0;
556 memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SOURCE_KHR;
557 memoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL;
558 memoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
559 memoryBarrier.destQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
560 memoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
561 memoryBarrier.subresourceRange.baseMipLevel = 0;
Courtney Goeltzenleuchter8367ce02015-10-16 09:46:00 -0600562 memoryBarrier.subresourceRange.numLevels = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600563 memoryBarrier.subresourceRange.baseArrayLayer = 0;
Courtney Goeltzenleuchter8367ce02015-10-16 09:46:00 -0600564 memoryBarrier.subresourceRange.numLayers = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600565 memoryBarrier.image = m_buffers[m_current_buffer].image;
566 VkImageMemoryBarrier *pmemory_barrier = &memoryBarrier;
567 vkCmdPipelineBarrier(m_cmdbuf.handle(), VK_PIPELINE_STAGE_ALL_GPU_COMMANDS, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
568 VK_FALSE, 1, (const void * const*)&pmemory_barrier);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600569
570 VkBufferImageCopy region = {};
571 region.imageExtent.height = m_display_image->m_height;
572 region.imageExtent.width = m_display_image->m_width;
573 region.imageExtent.depth = 1;
574
Chia-I Wube2b9172015-07-03 11:49:42 +0800575 vkCmdCopyBufferToImage(m_cmdbuf.handle(),
Chia-I Wu681d7a02015-07-03 13:44:34 +0800576 buf.handle(),
Tony Barbour6a3faf02015-07-23 10:36:18 -0600577 m_buffers[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600578 1, &region);
Tony Barbourbd094ce2015-10-23 11:00:15 -0600579
580 memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL;
581 memoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SOURCE_KHR;
582 vkCmdPipelineBarrier(m_cmdbuf.handle(), VK_PIPELINE_STAGE_ALL_GPU_COMMANDS, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
583 VK_FALSE, 1, (const void * const*)&pmemory_barrier);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600584 m_cmdbuf.end();
585
586 VkCmdBuffer cmdBufs[1];
Chia-I Wube2b9172015-07-03 11:49:42 +0800587 cmdBufs[0] = m_cmdbuf.handle();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600588
Tony Barbour67e99152015-07-10 14:10:27 -0600589 VkFence nullFence = { VK_NULL_HANDLE };
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600590 VkSubmitInfo submit_info;
591 submit_info.waitSemCount = 0;
592 submit_info.pWaitSemaphores = NULL;
593 submit_info.cmdBufferCount = 1;
594 submit_info.pCommandBuffers = cmdBufs;
595 submit_info.signalSemCount = 0;
596 submit_info.pSignalSemaphores = NULL;
597
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -0600598 vkQueueSubmit(m_queue.handle(), 1, &submit_info, nullFence);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600599 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700600
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.
912 assert((surfProperties.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT) != 0);
913
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;
Cody Northropdf8f42a2015-08-05 15:38:39 -0600923 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT |
924 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;
931 swap_chain.oldSwapchain.handle = 0;
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;
Courtney Goeltzenleuchter8367ce02015-10-16 09:46:00 -0600960 color_image_view.subresourceRange.numLevels = 1;
Courtney Goeltzenleuchter4a261892015-09-10 16:38:41 -0600961 color_image_view.subresourceRange.baseArrayLayer = 0;
Courtney Goeltzenleuchter8367ce02015-10-16 09:46:00 -0600962 color_image_view.subresourceRange.numLayers = 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(),
968 &color_image_view, &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
983 VkCmdBufferBeginInfo cmd_buf_info = {};
984 cmd_buf_info.sType = VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO;
985 cmd_buf_info.pNext = NULL;
Courtney Goeltzenleuchter04bb5f82015-10-21 18:11:04 -0600986 cmd_buf_info.flags = VK_CMD_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;
997 image_memory_barrier.outputMask = 0;
998 image_memory_barrier.inputMask = 0;
999 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;
Courtney Goeltzenleuchter8367ce02015-10-16 09:46:00 -06001004 image_memory_barrier.subresourceRange.numLevels = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001005 image_memory_barrier.subresourceRange.baseArrayLayer = 0;
Courtney Goeltzenleuchter8367ce02015-10-16 09:46:00 -06001006 image_memory_barrier.subresourceRange.numLayers = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001007
1008 if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL) {
1009 /* Make sure anything that was copying from this image has completed */
1010 image_memory_barrier.inputMask = VK_MEMORY_INPUT_TRANSFER_BIT;
1011 }
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 */
1015 image_memory_barrier.outputMask = VK_MEMORY_OUTPUT_HOST_WRITE_BIT | VK_MEMORY_OUTPUT_TRANSFER_BIT;
1016 }
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
1023 vkCmdPipelineBarrier(m_cmdbuf.handle(), src_stages, dest_stages, false, 1, (const void * const*)&pmemory_barrier);
1024
1025 err = vkEndCommandBuffer(m_cmdbuf.handle());
1026 assert(!err);
1027
1028 const VkCmdBuffer cmd_bufs[] = { m_cmdbuf.handle() };
1029 VkFence nullFence = { VK_NULL_HANDLE };
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001030 VkSubmitInfo submit_info;
1031 submit_info.waitSemCount = 0;
1032 submit_info.pWaitSemaphores = NULL;
1033 submit_info.cmdBufferCount = 1;
1034 submit_info.pCommandBuffers = cmd_bufs;
1035 submit_info.signalSemCount = 0;
1036 submit_info.pSignalSemaphores = NULL;
1037
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -06001038 err = vkQueueSubmit(m_queue.handle(), 1, &submit_info, nullFence);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001039 assert(!err);
1040
1041 err = vkQueueWaitIdle(m_queue.handle());
1042 assert(!err);
1043
1044}
Tony Barbour96db8822015-02-25 12:28:39 -07001045
Jon Ashburn07daee72015-05-21 18:13:33 -06001046void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -07001047{
Ian Elliott7e40db92015-08-21 15:09:33 -06001048 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceSupportKHR);
1049 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfacePropertiesKHR);
1050 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfaceFormatsKHR);
1051 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfacePresentModesKHR);
1052 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1053 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1054 GET_DEVICE_PROC_ADDR(m_device.handle(), DestroySwapchainKHR);
1055 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSwapchainImagesKHR);
1056 GET_DEVICE_PROC_ADDR(m_device.handle(), AcquireNextImageKHR);
1057 GET_DEVICE_PROC_ADDR(m_device.handle(), QueuePresentKHR);
Jon Ashburn07daee72015-05-21 18:13:33 -06001058
Tony Barbour96db8822015-02-25 12:28:39 -07001059 m_images = imagesIn;
1060}
1061
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001062#ifdef _WIN32
1063void TestFrameworkVkPresent::CreateMyWindow()
1064{
1065 WNDCLASSEX win_class;
1066 // const ::testing::TestInfo* const test_info =
1067 // ::testing::UnitTest::GetInstance()->current_test_info();
1068 m_connection = GetModuleHandle(NULL);
1069
1070 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1071 it != m_images.end(); it++) {
1072 if (m_width < it->m_width)
1073 m_width = it->m_width;
1074 if (m_height < it->m_height)
1075 m_height = it->m_height;
1076 }
1077 // Initialize the window class structure:
1078 win_class.cbSize = sizeof(WNDCLASSEX);
1079 win_class.style = CS_HREDRAW | CS_VREDRAW;
1080 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
1081 win_class.cbClsExtra = 0;
1082 win_class.cbWndExtra = 0;
1083 win_class.hInstance = m_connection; // hInstance
1084 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
1085 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
1086 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
1087 win_class.lpszMenuName = NULL;
1088 win_class.lpszClassName = "Test";
1089 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
1090 // Register window class:
1091 if (!RegisterClassEx(&win_class)) {
1092 // It didn't work, so try to give a useful error:
1093 printf("Unexpected error trying to start the application!\n");
1094 fflush(stdout);
1095 exit(1);
1096 }
1097 // Create window with the registered class:
Cody Northrop39582252015-08-05 15:39:31 -06001098 RECT wr = { 0, 0, m_width, m_height };
1099 AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001100 m_window = CreateWindowEx(0,
1101 "Test", // class name
1102 "Test", // app name
1103 WS_OVERLAPPEDWINDOW | // window style
1104 WS_VISIBLE |
1105 WS_SYSMENU,
1106 100,100, // x/y coords
Cody Northrop39582252015-08-05 15:39:31 -06001107 wr.right - wr.left, // width
1108 wr.bottom - wr.top, // height
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001109 NULL, // handle to parent
1110 NULL, // handle to menu
1111 m_connection, // hInstance
1112 NULL); // no extra parameters
1113
1114 if (!m_window) {
1115 // It didn't work, so try to give a useful error:
1116 DWORD error = GetLastError();
1117 char message[120];
1118 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
1119 MessageBox(NULL, message, "Error", MB_OK);
1120 exit(1);
1121 }
Tony-LunarG399dfca2015-05-19 14:08:26 -06001122 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
1123 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001124}
1125#else
Tony Barbour6918cd52015-04-09 12:58:51 -06001126void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -07001127{
Chia-I Wuf8693382015-04-16 22:02:10 +08001128 const xcb_setup_t *setup;
1129 xcb_screen_iterator_t iter;
1130 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -07001131 uint32_t value_mask, value_list[32];
1132
Chia-I Wuf8693382015-04-16 22:02:10 +08001133 m_connection = xcb_connect(NULL, &scr);
1134
1135 setup = xcb_get_setup(m_connection);
1136 iter = xcb_setup_roots_iterator(setup);
1137 while (scr-- > 0)
1138 xcb_screen_next(&iter);
1139
1140 m_screen = iter.data;
1141
1142 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1143 it != m_images.end(); it++) {
1144 if (m_width < it->m_width)
1145 m_width = it->m_width;
1146 if (m_height < it->m_height)
1147 m_height = it->m_height;
1148 }
1149
1150 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -07001151
1152 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +08001153 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -07001154 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
1155 XCB_EVENT_MASK_EXPOSURE |
1156 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
1157
Chia-I Wuf8693382015-04-16 22:02:10 +08001158 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -07001159 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001160 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -07001161 0, 0, m_width, m_height, 0,
1162 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001163 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -07001164 value_mask, value_list);
1165
1166 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +08001167 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -07001168 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +08001169 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001170
Chia-I Wuf8693382015-04-16 22:02:10 +08001171 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
1172 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001173
Chia-I Wuf8693382015-04-16 22:02:10 +08001174 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -07001175 m_window, (*reply).atom, 4, 32, 1,
1176 &(*m_atom_wm_delete_window).atom);
1177 free(reply);
1178
Chia-I Wuf8693382015-04-16 22:02:10 +08001179 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -07001180}
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001181#endif
Tony Barbour96db8822015-02-25 12:28:39 -07001182
Tony Barbour6918cd52015-04-09 12:58:51 -06001183void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -07001184{
Ian Elliott7e40db92015-08-21 15:09:33 -06001185 m_fpDestroySwapchainKHR(m_device.handle(), m_swap_chain);
Tony Barbour9226a822015-10-23 10:58:56 -06001186
1187 for (uint32_t i = 0; i < m_swapchainImageCount; i++) {
1188 vkDestroyImageView(m_device.handle(), m_buffers[i].view);
1189 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001190#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +08001191 xcb_destroy_window(m_connection, m_window);
1192 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001193#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001194}
1195
Tony Barbour6918cd52015-04-09 12:58:51 -06001196void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001197{
1198 if (m_images.size() == 0) return;
1199
Chia-I Wuf8693382015-04-16 22:02:10 +08001200 vk_testing::Environment env;
1201 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -07001202 {
Chia-I Wuf8693382015-04-16 22:02:10 +08001203 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -07001204
Jon Ashburn07daee72015-05-21 18:13:33 -06001205 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001206 vkPresent.CreateMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -06001207 vkPresent.CreateSwapchain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001208 vkPresent.Run();
1209 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -07001210 }
Chia-I Wuf8693382015-04-16 22:02:10 +08001211 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001212}
1213
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001214//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001215// These are the default resources for TBuiltInResources, used for both
1216// - parsing this string for the case where the user didn't supply one
1217// - dumping out a template for user construction of a config file
1218//
1219static const char* DefaultConfig =
1220 "MaxLights 32\n"
1221 "MaxClipPlanes 6\n"
1222 "MaxTextureUnits 32\n"
1223 "MaxTextureCoords 32\n"
1224 "MaxVertexAttribs 64\n"
1225 "MaxVertexUniformComponents 4096\n"
1226 "MaxVaryingFloats 64\n"
1227 "MaxVertexTextureImageUnits 32\n"
1228 "MaxCombinedTextureImageUnits 80\n"
1229 "MaxTextureImageUnits 32\n"
1230 "MaxFragmentUniformComponents 4096\n"
1231 "MaxDrawBuffers 32\n"
1232 "MaxVertexUniformVectors 128\n"
1233 "MaxVaryingVectors 8\n"
1234 "MaxFragmentUniformVectors 16\n"
1235 "MaxVertexOutputVectors 16\n"
1236 "MaxFragmentInputVectors 15\n"
1237 "MinProgramTexelOffset -8\n"
1238 "MaxProgramTexelOffset 7\n"
1239 "MaxClipDistances 8\n"
1240 "MaxComputeWorkGroupCountX 65535\n"
1241 "MaxComputeWorkGroupCountY 65535\n"
1242 "MaxComputeWorkGroupCountZ 65535\n"
1243 "MaxComputeWorkGroupSizeX 1024\n"
1244 "MaxComputeWorkGroupSizeY 1024\n"
1245 "MaxComputeWorkGroupSizeZ 64\n"
1246 "MaxComputeUniformComponents 1024\n"
1247 "MaxComputeTextureImageUnits 16\n"
1248 "MaxComputeImageUniforms 8\n"
1249 "MaxComputeAtomicCounters 8\n"
1250 "MaxComputeAtomicCounterBuffers 1\n"
1251 "MaxVaryingComponents 60\n"
1252 "MaxVertexOutputComponents 64\n"
1253 "MaxGeometryInputComponents 64\n"
1254 "MaxGeometryOutputComponents 128\n"
1255 "MaxFragmentInputComponents 128\n"
1256 "MaxImageUnits 8\n"
1257 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
1258 "MaxCombinedShaderOutputResources 8\n"
1259 "MaxImageSamples 0\n"
1260 "MaxVertexImageUniforms 0\n"
1261 "MaxTessControlImageUniforms 0\n"
1262 "MaxTessEvaluationImageUniforms 0\n"
1263 "MaxGeometryImageUniforms 0\n"
1264 "MaxFragmentImageUniforms 8\n"
1265 "MaxCombinedImageUniforms 8\n"
1266 "MaxGeometryTextureImageUnits 16\n"
1267 "MaxGeometryOutputVertices 256\n"
1268 "MaxGeometryTotalOutputComponents 1024\n"
1269 "MaxGeometryUniformComponents 1024\n"
1270 "MaxGeometryVaryingComponents 64\n"
1271 "MaxTessControlInputComponents 128\n"
1272 "MaxTessControlOutputComponents 128\n"
1273 "MaxTessControlTextureImageUnits 16\n"
1274 "MaxTessControlUniformComponents 1024\n"
1275 "MaxTessControlTotalOutputComponents 4096\n"
1276 "MaxTessEvaluationInputComponents 128\n"
1277 "MaxTessEvaluationOutputComponents 128\n"
1278 "MaxTessEvaluationTextureImageUnits 16\n"
1279 "MaxTessEvaluationUniformComponents 1024\n"
1280 "MaxTessPatchComponents 120\n"
1281 "MaxPatchVertices 32\n"
1282 "MaxTessGenLevel 64\n"
1283 "MaxViewports 16\n"
1284 "MaxVertexAtomicCounters 0\n"
1285 "MaxTessControlAtomicCounters 0\n"
1286 "MaxTessEvaluationAtomicCounters 0\n"
1287 "MaxGeometryAtomicCounters 0\n"
1288 "MaxFragmentAtomicCounters 8\n"
1289 "MaxCombinedAtomicCounters 8\n"
1290 "MaxAtomicCounterBindings 1\n"
1291 "MaxVertexAtomicCounterBuffers 0\n"
1292 "MaxTessControlAtomicCounterBuffers 0\n"
1293 "MaxTessEvaluationAtomicCounterBuffers 0\n"
1294 "MaxGeometryAtomicCounterBuffers 0\n"
1295 "MaxFragmentAtomicCounterBuffers 1\n"
1296 "MaxCombinedAtomicCounterBuffers 1\n"
1297 "MaxAtomicCounterBufferSize 16384\n"
1298 "MaxTransformFeedbackBuffers 4\n"
1299 "MaxTransformFeedbackInterleavedComponents 64\n"
1300 "MaxCullDistances 8\n"
1301 "MaxCombinedClipAndCullDistances 8\n"
1302 "MaxSamples 4\n"
1303
1304 "nonInductiveForLoops 1\n"
1305 "whileLoops 1\n"
1306 "doWhileLoops 1\n"
1307 "generalUniformIndexing 1\n"
1308 "generalAttributeMatrixVectorIndexing 1\n"
1309 "generalVaryingIndexing 1\n"
1310 "generalSamplerIndexing 1\n"
1311 "generalVariableIndexing 1\n"
1312 "generalConstantMatrixVectorIndexing 1\n"
1313 ;
1314
1315//
1316// *.conf => this is a config file that can set limits/resources
1317//
Tony Barbour6918cd52015-04-09 12:58:51 -06001318bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001319{
1320 if (name.size() < 5)
1321 return false;
1322
1323 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
1324 ConfigFile = name;
1325 return true;
1326 }
1327
1328 return false;
1329}
1330
1331//
1332// Parse either a .conf file provided by the user or the default string above.
1333//
Tony Barbour6918cd52015-04-09 12:58:51 -06001334void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001335{
1336 char** configStrings = 0;
1337 char* config = 0;
1338 if (ConfigFile.size() > 0) {
1339 configStrings = ReadFileData(ConfigFile.c_str());
1340 if (configStrings)
1341 config = *configStrings;
1342 else {
1343 printf("Error opening configuration file; will instead use the default configuration\n");
1344 }
1345 }
1346
1347 if (config == 0) {
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001348 config = (char *) alloca(strlen(DefaultConfig) + 1);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001349 strcpy(config, DefaultConfig);
1350 }
1351
1352 const char* delims = " \t\n\r";
1353 const char* token = strtok(config, delims);
1354 while (token) {
1355 const char* valueStr = strtok(0, delims);
1356 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1357 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1358 return;
1359 }
1360 int value = atoi(valueStr);
1361
1362 if (strcmp(token, "MaxLights") == 0)
1363 Resources.maxLights = value;
1364 else if (strcmp(token, "MaxClipPlanes") == 0)
1365 Resources.maxClipPlanes = value;
1366 else if (strcmp(token, "MaxTextureUnits") == 0)
1367 Resources.maxTextureUnits = value;
1368 else if (strcmp(token, "MaxTextureCoords") == 0)
1369 Resources.maxTextureCoords = value;
1370 else if (strcmp(token, "MaxVertexAttribs") == 0)
1371 Resources.maxVertexAttribs = value;
1372 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1373 Resources.maxVertexUniformComponents = value;
1374 else if (strcmp(token, "MaxVaryingFloats") == 0)
1375 Resources.maxVaryingFloats = value;
1376 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1377 Resources.maxVertexTextureImageUnits = value;
1378 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1379 Resources.maxCombinedTextureImageUnits = value;
1380 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1381 Resources.maxTextureImageUnits = value;
1382 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1383 Resources.maxFragmentUniformComponents = value;
1384 else if (strcmp(token, "MaxDrawBuffers") == 0)
1385 Resources.maxDrawBuffers = value;
1386 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1387 Resources.maxVertexUniformVectors = value;
1388 else if (strcmp(token, "MaxVaryingVectors") == 0)
1389 Resources.maxVaryingVectors = value;
1390 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1391 Resources.maxFragmentUniformVectors = value;
1392 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1393 Resources.maxVertexOutputVectors = value;
1394 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1395 Resources.maxFragmentInputVectors = value;
1396 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1397 Resources.minProgramTexelOffset = value;
1398 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1399 Resources.maxProgramTexelOffset = value;
1400 else if (strcmp(token, "MaxClipDistances") == 0)
1401 Resources.maxClipDistances = value;
1402 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1403 Resources.maxComputeWorkGroupCountX = value;
1404 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1405 Resources.maxComputeWorkGroupCountY = value;
1406 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1407 Resources.maxComputeWorkGroupCountZ = value;
1408 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1409 Resources.maxComputeWorkGroupSizeX = value;
1410 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1411 Resources.maxComputeWorkGroupSizeY = value;
1412 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1413 Resources.maxComputeWorkGroupSizeZ = value;
1414 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1415 Resources.maxComputeUniformComponents = value;
1416 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1417 Resources.maxComputeTextureImageUnits = value;
1418 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1419 Resources.maxComputeImageUniforms = value;
1420 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1421 Resources.maxComputeAtomicCounters = value;
1422 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1423 Resources.maxComputeAtomicCounterBuffers = value;
1424 else if (strcmp(token, "MaxVaryingComponents") == 0)
1425 Resources.maxVaryingComponents = value;
1426 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1427 Resources.maxVertexOutputComponents = value;
1428 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1429 Resources.maxGeometryInputComponents = value;
1430 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1431 Resources.maxGeometryOutputComponents = value;
1432 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1433 Resources.maxFragmentInputComponents = value;
1434 else if (strcmp(token, "MaxImageUnits") == 0)
1435 Resources.maxImageUnits = value;
1436 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1437 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1438 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1439 Resources.maxCombinedShaderOutputResources = value;
1440 else if (strcmp(token, "MaxImageSamples") == 0)
1441 Resources.maxImageSamples = value;
1442 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1443 Resources.maxVertexImageUniforms = value;
1444 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1445 Resources.maxTessControlImageUniforms = value;
1446 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1447 Resources.maxTessEvaluationImageUniforms = value;
1448 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1449 Resources.maxGeometryImageUniforms = value;
1450 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1451 Resources.maxFragmentImageUniforms = value;
1452 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1453 Resources.maxCombinedImageUniforms = value;
1454 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1455 Resources.maxGeometryTextureImageUnits = value;
1456 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1457 Resources.maxGeometryOutputVertices = value;
1458 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1459 Resources.maxGeometryTotalOutputComponents = value;
1460 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1461 Resources.maxGeometryUniformComponents = value;
1462 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1463 Resources.maxGeometryVaryingComponents = value;
1464 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1465 Resources.maxTessControlInputComponents = value;
1466 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1467 Resources.maxTessControlOutputComponents = value;
1468 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1469 Resources.maxTessControlTextureImageUnits = value;
1470 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1471 Resources.maxTessControlUniformComponents = value;
1472 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1473 Resources.maxTessControlTotalOutputComponents = value;
1474 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1475 Resources.maxTessEvaluationInputComponents = value;
1476 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1477 Resources.maxTessEvaluationOutputComponents = value;
1478 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1479 Resources.maxTessEvaluationTextureImageUnits = value;
1480 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1481 Resources.maxTessEvaluationUniformComponents = value;
1482 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1483 Resources.maxTessPatchComponents = value;
1484 else if (strcmp(token, "MaxPatchVertices") == 0)
1485 Resources.maxPatchVertices = value;
1486 else if (strcmp(token, "MaxTessGenLevel") == 0)
1487 Resources.maxTessGenLevel = value;
1488 else if (strcmp(token, "MaxViewports") == 0)
1489 Resources.maxViewports = value;
1490 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1491 Resources.maxVertexAtomicCounters = value;
1492 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1493 Resources.maxTessControlAtomicCounters = value;
1494 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1495 Resources.maxTessEvaluationAtomicCounters = value;
1496 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1497 Resources.maxGeometryAtomicCounters = value;
1498 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1499 Resources.maxFragmentAtomicCounters = value;
1500 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1501 Resources.maxCombinedAtomicCounters = value;
1502 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1503 Resources.maxAtomicCounterBindings = value;
1504 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1505 Resources.maxVertexAtomicCounterBuffers = value;
1506 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1507 Resources.maxTessControlAtomicCounterBuffers = value;
1508 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1509 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1510 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1511 Resources.maxGeometryAtomicCounterBuffers = value;
1512 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1513 Resources.maxFragmentAtomicCounterBuffers = value;
1514 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1515 Resources.maxCombinedAtomicCounterBuffers = value;
1516 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1517 Resources.maxAtomicCounterBufferSize = value;
1518 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1519 Resources.maxTransformFeedbackBuffers = value;
1520 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1521 Resources.maxTransformFeedbackInterleavedComponents = value;
1522 else if (strcmp(token, "MaxCullDistances") == 0)
1523 Resources.maxCullDistances = value;
1524 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1525 Resources.maxCombinedClipAndCullDistances = value;
1526 else if (strcmp(token, "MaxSamples") == 0)
1527 Resources.maxSamples = value;
1528
1529 else if (strcmp(token, "nonInductiveForLoops") == 0)
1530 Resources.limits.nonInductiveForLoops = (value != 0);
1531 else if (strcmp(token, "whileLoops") == 0)
1532 Resources.limits.whileLoops = (value != 0);
1533 else if (strcmp(token, "doWhileLoops") == 0)
1534 Resources.limits.doWhileLoops = (value != 0);
1535 else if (strcmp(token, "generalUniformIndexing") == 0)
1536 Resources.limits.generalUniformIndexing = (value != 0);
1537 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1538 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1539 else if (strcmp(token, "generalVaryingIndexing") == 0)
1540 Resources.limits.generalVaryingIndexing = (value != 0);
1541 else if (strcmp(token, "generalSamplerIndexing") == 0)
1542 Resources.limits.generalSamplerIndexing = (value != 0);
1543 else if (strcmp(token, "generalVariableIndexing") == 0)
1544 Resources.limits.generalVariableIndexing = (value != 0);
1545 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1546 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1547 else
1548 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1549
1550 token = strtok(0, delims);
1551 }
1552 if (configStrings)
1553 FreeFileData(configStrings);
1554}
1555
Tony Barbour6918cd52015-04-09 12:58:51 -06001556void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001557{
1558 if (m_compile_options & EOptionRelaxedErrors)
1559 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1560 if (m_compile_options & EOptionIntermediate)
1561 messages = (EShMessages)(messages | EShMsgAST);
1562 if (m_compile_options & EOptionSuppressWarnings)
1563 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1564}
1565
1566//
1567// Malloc a string of sufficient size and read a string into it.
1568//
Tony Barbour6918cd52015-04-09 12:58:51 -06001569char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001570{
1571 FILE *in;
1572 #if defined(_WIN32) && defined(__GNUC__)
1573 in = fopen(fileName, "r");
1574 int errorCode = in ? 0 : 1;
1575 #else
1576 int errorCode = fopen_s(&in, fileName, "r");
1577 #endif
1578
1579 char *fdata;
1580 int count = 0;
1581 const int maxSourceStrings = 5;
1582 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1583
1584 if (errorCode) {
1585 printf("Error: unable to open input file: %s\n", fileName);
1586 return 0;
1587 }
1588
1589 while (fgetc(in) != EOF)
1590 count++;
1591
1592 fseek(in, 0, SEEK_SET);
1593
1594 if (!(fdata = (char*)malloc(count+2))) {
1595 printf("Error allocating memory\n");
1596 return 0;
1597 }
1598 if (fread(fdata,1,count, in)!=count) {
1599 printf("Error reading input file: %s\n", fileName);
1600 return 0;
1601 }
1602 fdata[count] = '\0';
1603 fclose(in);
1604 if (count == 0) {
1605 return_data[0]=(char*)malloc(count+2);
1606 return_data[0][0]='\0';
1607 m_num_shader_strings = 0;
1608 return return_data;
1609 } else
1610 m_num_shader_strings = 1;
1611
1612 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1613 int ptr_len=0,i=0;
1614 while(count>0){
1615 return_data[i]=(char*)malloc(len+2);
1616 memcpy(return_data[i],fdata+ptr_len,len);
1617 return_data[i][len]='\0';
1618 count-=(len);
1619 ptr_len+=(len);
1620 if(count<len){
1621 if(count==0){
1622 m_num_shader_strings=(i+1);
1623 break;
1624 }
1625 len = count;
1626 }
1627 ++i;
1628 }
1629 return return_data;
1630}
1631
Tony Barbour6918cd52015-04-09 12:58:51 -06001632void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001633{
1634 for(int i=0;i<m_num_shader_strings;i++)
1635 free(data[i]);
1636}
1637
1638//
1639// Deduce the language from the filename. Files must end in one of the
1640// following extensions:
1641//
1642// .vert = vertex
1643// .tesc = tessellation control
1644// .tese = tessellation evaluation
1645// .geom = geometry
1646// .frag = fragment
1647// .comp = compute
1648//
Tony Barbour6918cd52015-04-09 12:58:51 -06001649EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001650{
1651 size_t ext = name.rfind('.');
1652 if (ext == std::string::npos) {
1653 return EShLangVertex;
1654 }
1655
1656 std::string suffix = name.substr(ext + 1, std::string::npos);
1657 if (suffix == "vert")
1658 return EShLangVertex;
1659 else if (suffix == "tesc")
1660 return EShLangTessControl;
1661 else if (suffix == "tese")
1662 return EShLangTessEvaluation;
1663 else if (suffix == "geom")
1664 return EShLangGeometry;
1665 else if (suffix == "frag")
1666 return EShLangFragment;
1667 else if (suffix == "comp")
1668 return EShLangCompute;
1669
1670 return EShLangVertex;
1671}
1672
1673//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001674// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001675//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001676EShLanguage VkTestFramework::FindLanguage(const VkShaderStageFlagBits shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001677{
1678 switch (shader_type) {
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001679 case VK_SHADER_STAGE_VERTEX_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001680 return EShLangVertex;
1681
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001682 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001683 return EShLangTessControl;
1684
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001685 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001686 return EShLangTessEvaluation;
1687
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001688 case VK_SHADER_STAGE_GEOMETRY_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001689 return EShLangGeometry;
1690
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001691 case VK_SHADER_STAGE_FRAGMENT_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001692 return EShLangFragment;
1693
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001694 case VK_SHADER_STAGE_COMPUTE_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001695 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001696
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001697 default:
1698 return EShLangVertex;
1699 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001700}
1701
1702
1703//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001704// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001705// Return value of false means an error was encountered.
1706//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001707bool VkTestFramework::GLSLtoSPV(const VkShaderStageFlagBits shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001708 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001709 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001710{
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001711 glslang::TProgram program;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001712 const char *shaderStrings[1];
1713
1714 // TODO: Do we want to load a special config file depending on the
1715 // shader source? Optional name maybe?
1716 // SetConfigFile(fileName);
1717
1718 ProcessConfigFile();
1719
1720 EShMessages messages = EShMsgDefault;
1721 SetMessageOptions(messages);
1722
1723 EShLanguage stage = FindLanguage(shader_type);
1724 glslang::TShader* shader = new glslang::TShader(stage);
1725
1726 shaderStrings[0] = pshader;
1727 shader->setStrings(shaderStrings, 1);
1728
1729 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1730
Cody Northrop195d6622014-11-03 12:54:37 -07001731 if (! (m_compile_options & EOptionSuppressInfolog)) {
1732 puts(shader->getInfoLog());
1733 puts(shader->getInfoDebugLog());
1734 }
1735
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001736 return false; // something didn't work
1737 }
1738
1739 program.addShader(shader);
1740
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001741
1742 //
1743 // Program-level processing...
1744 //
1745
Cody Northrop195d6622014-11-03 12:54:37 -07001746 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001747
Cody Northrop195d6622014-11-03 12:54:37 -07001748 if (! (m_compile_options & EOptionSuppressInfolog)) {
1749 puts(shader->getInfoLog());
1750 puts(shader->getInfoDebugLog());
1751 }
1752
1753 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001754 }
1755
1756 if (m_compile_options & EOptionDumpReflection) {
1757 program.buildReflection();
1758 program.dumpReflection();
1759 }
1760
Cody Northrop5a95b472015-06-03 13:01:54 -06001761 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1762
1763 //
1764 // Test the different modes of SPIR-V modification
1765 //
1766 if (this->m_canonicalize_spv) {
1767 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1768 }
1769
1770 if (this->m_strip_spv) {
1771 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1772 }
1773
1774 if (this->m_do_everything_spv) {
1775 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1776 }
1777
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001778 delete shader;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001779
1780 return true;
1781}
1782
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001783
1784
Tony Barbour6918cd52015-04-09 12:58:51 -06001785VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001786 m_width( 0 ),
1787 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001788 m_data( NULL ),
1789 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001790{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001791}
1792
Tony Barbour6918cd52015-04-09 12:58:51 -06001793VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001794{
1795
1796}
1797
Tony Barbour6918cd52015-04-09 12:58:51 -06001798VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001799{
1800 m_title = copyin.m_title;
1801 m_width = copyin.m_width;
1802 m_height = copyin.m_height;
1803 m_data_size = copyin.m_data_size;
1804 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1805}
1806
Tony Barbour6918cd52015-04-09 12:58:51 -06001807ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001808{
Tony Barbour6918cd52015-04-09 12:58:51 -06001809 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1810 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001811 return output;
1812}
1813
Tony Barbour6918cd52015-04-09 12:58:51 -06001814VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001815{
1816 m_title = rhs.m_title;
1817 m_width = rhs.m_width;
1818 m_height = rhs.m_height;
1819 m_data_size = rhs.m_data_size;
1820 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001821 return *this;
1822}
1823
Tony Barbour6918cd52015-04-09 12:58:51 -06001824int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001825{
1826 if( this->m_data != rhs.m_data) return 0;
1827 return 1;
1828}
1829
1830// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001831int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001832{
1833 if( this->m_data_size < rhs.m_data_size ) return 1;
1834 return 0;
1835}
1836