blob: 0551600ca81b8cf7fab1a415574315074cec9993 [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
Tony-LunarG399dfca2015-05-19 14:08:26 -0600537 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Cody Northrop7fb43862015-06-22 14:56:14 -0600538 buf.init_as_src(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800539 dest_ptr = buf.memory().map();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600540 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800541 buf.memory().unmap();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600542
543 m_cmdbuf.begin();
Tony Barbourbd094ce2015-10-23 11:00:15 -0600544 VkImageMemoryBarrier memoryBarrier = {};
545 memoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
546 memoryBarrier.pNext = NULL;
547 memoryBarrier.outputMask = VK_MEMORY_OUTPUT_COLOR_ATTACHMENT_BIT;
548 memoryBarrier.inputMask = 0;
549 memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SOURCE_KHR;
550 memoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL;
551 memoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
552 memoryBarrier.destQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
553 memoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
554 memoryBarrier.subresourceRange.baseMipLevel = 0;
Courtney Goeltzenleuchter8367ce02015-10-16 09:46:00 -0600555 memoryBarrier.subresourceRange.numLevels = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600556 memoryBarrier.subresourceRange.baseArrayLayer = 0;
Courtney Goeltzenleuchter8367ce02015-10-16 09:46:00 -0600557 memoryBarrier.subresourceRange.numLayers = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600558 memoryBarrier.image = m_buffers[m_current_buffer].image;
559 VkImageMemoryBarrier *pmemory_barrier = &memoryBarrier;
560 vkCmdPipelineBarrier(m_cmdbuf.handle(), VK_PIPELINE_STAGE_ALL_GPU_COMMANDS, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
561 VK_FALSE, 1, (const void * const*)&pmemory_barrier);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600562
563 VkBufferImageCopy region = {};
564 region.imageExtent.height = m_display_image->m_height;
565 region.imageExtent.width = m_display_image->m_width;
566 region.imageExtent.depth = 1;
567
Chia-I Wube2b9172015-07-03 11:49:42 +0800568 vkCmdCopyBufferToImage(m_cmdbuf.handle(),
Chia-I Wu681d7a02015-07-03 13:44:34 +0800569 buf.handle(),
Tony Barbour6a3faf02015-07-23 10:36:18 -0600570 m_buffers[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600571 1, &region);
Tony Barbourbd094ce2015-10-23 11:00:15 -0600572
573 memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL;
574 memoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SOURCE_KHR;
575 vkCmdPipelineBarrier(m_cmdbuf.handle(), VK_PIPELINE_STAGE_ALL_GPU_COMMANDS, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
576 VK_FALSE, 1, (const void * const*)&pmemory_barrier);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600577 m_cmdbuf.end();
578
579 VkCmdBuffer cmdBufs[1];
Chia-I Wube2b9172015-07-03 11:49:42 +0800580 cmdBufs[0] = m_cmdbuf.handle();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600581
Chia-I Wua690b412015-10-29 22:01:53 +0800582 // Wait for the present complete semaphore to be signaled to ensure
583 // that the image won't be rendered to until the presentation
584 // engine has fully released ownership to the application, and it is
585 // okay to render to the image.
Tony Barbour67e99152015-07-10 14:10:27 -0600586 VkFence nullFence = { VK_NULL_HANDLE };
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600587 VkSubmitInfo submit_info;
Chia-I Wua690b412015-10-29 22:01:53 +0800588 submit_info.waitSemCount = 1;
589 submit_info.pWaitSemaphores = &presentCompleteSemaphore,
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600590 submit_info.cmdBufferCount = 1;
591 submit_info.pCommandBuffers = cmdBufs;
592 submit_info.signalSemCount = 0;
593 submit_info.pSignalSemaphores = NULL;
594
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -0600595 vkQueueSubmit(m_queue.handle(), 1, &submit_info, nullFence);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600596 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700597
Chia-I Wua690b412015-10-29 22:01:53 +0800598 vkDestroySemaphore(m_device.handle(), presentCompleteSemaphore);
599
Ian Elliott7e40db92015-08-21 15:09:33 -0600600 VkPresentInfoKHR present = {};
601 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600602 present.pNext = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600603 present.swapchainCount = 1;
604 present.swapchains = & m_swap_chain;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600605 present.imageIndices = &m_current_buffer;
Tony Barbour96db8822015-02-25 12:28:39 -0700606
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600607#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800608 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700609 XCB_PROP_MODE_REPLACE,
610 m_window,
611 XCB_ATOM_WM_NAME,
612 XCB_ATOM_STRING,
613 8,
614 m_display_image->m_title.size(),
615 m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600616#endif
Jon Ashburn07daee72015-05-21 18:13:33 -0600617
Ian Elliott7e40db92015-08-21 15:09:33 -0600618 err = m_fpQueuePresentKHR(m_queue.handle(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700619 assert(!err);
620
621 m_queue.wait();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600622 m_current_buffer = (m_current_buffer + 1) % 2;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600623}
624
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600625#ifdef _WIN32
Tony-LunarG399dfca2015-05-19 14:08:26 -0600626# define PREVIOUSLY_DOWN 1<<29
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600627// MS-Windows event handling function:
628LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
629 UINT uMsg,
630 WPARAM wParam,
631 LPARAM lParam)
632{
633
634 switch(uMsg)
635 {
636 case WM_CLOSE:
637 PostQuitMessage(0);
638 break;
639
640 case WM_PAINT:
641 {
642 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
643 if (me) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600644 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600645 me->Display();
646 }
647 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600648 break;
649
650 case WM_KEYDOWN:
651 {
652 if (lParam & (PREVIOUSLY_DOWN)){
653 break;
654 }
655 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
656 // the window, we put the this pointer into the window's user data so we could get it back now
657 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
658 switch (wParam)
659 {
660 case VK_ESCAPE: me->m_quit = true;
661 break;
662
663 case VK_LEFT: // left arrow key
664 if (me->m_display_image == me->m_images.begin()) {
665 me->m_display_image = --me->m_images.end();
666 }
667 else {
668 --me->m_display_image;
669 }
670 break;
671
672 case VK_RIGHT: // right arrow key
673 ++me->m_display_image;
674 if (me->m_display_image == me->m_images.end()) {
675 me->m_display_image = me->m_images.begin();
676 }
677 break;
678
679 default:
680 break;
681 }
682 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
683 me->Display();
684 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600685 }
686 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
687}
688
689void TestFrameworkVkPresent::Run()
690{
691 MSG msg; // message
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600692
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600693 /* main message loop*/
Tony-LunarG399dfca2015-05-19 14:08:26 -0600694 while(! m_quit) {
695 GetMessage(&msg, m_window, 0, 0);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600696 if (msg.message == WM_QUIT) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600697 m_quit = true; //if found, quit app
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600698 } else {
699 /* Translate and dispatch to event queue*/
700 TranslateMessage(&msg);
701 DispatchMessage(&msg);
702 }
703 }
704}
705
706#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600707void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600708{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600709 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700710 switch (event_code) {
711 case XCB_EXPOSE:
712 Display(); // TODO: handle resize
713 break;
714 case XCB_CLIENT_MESSAGE:
715 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
716 (m_atom_wm_delete_window)->atom) {
717 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600718 }
719 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700720 case XCB_KEY_RELEASE:
721 {
722 const xcb_key_release_event_t *key =
723 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600724
Tony Barbour96db8822015-02-25 12:28:39 -0700725 switch (key->detail) {
726 case 0x9: // Escape
727 m_quit = true;
728 break;
729 case 0x71: // left arrow key
730 if (m_display_image == m_images.begin()) {
731 m_display_image = --m_images.end();
732 } else {
733 --m_display_image;
734 }
735 break;
736 case 0x72: // right arrow key
737 ++m_display_image;
738 if (m_display_image == m_images.end()) {
739 m_display_image = m_images.begin();
740 }
741 break;
742 case 0x41:
743 m_pause = !m_pause;
744 break;
745 }
746 Display();
747 }
748 break;
749 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600750 break;
751 }
Tony Barbour96db8822015-02-25 12:28:39 -0700752}
753
Tony Barbour6918cd52015-04-09 12:58:51 -0600754void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700755{
Chia-I Wuf8693382015-04-16 22:02:10 +0800756 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700757
758 while (! m_quit) {
759 xcb_generic_event_t *event;
760
761 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800762 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700763 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800764 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700765 }
766 if (event) {
767 HandleEvent(event);
768 free(event);
769 }
770 }
771}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600772#endif // _WIN32
Tony Barbour96db8822015-02-25 12:28:39 -0700773
Ian Elliott7e40db92015-08-21 15:09:33 -0600774void TestFrameworkVkPresent::CreateSwapchain()
Tony Barbour96db8822015-02-25 12:28:39 -0700775{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600776 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700777
Tony-LunarG399dfca2015-05-19 14:08:26 -0600778 m_display_image = m_images.begin();
779 m_current_buffer = 0;
780
Tony Barbour6a3faf02015-07-23 10:36:18 -0600781 // Construct the WSI surface description:
Ian Elliott7e40db92015-08-21 15:09:33 -0600782 m_surface_description.sType = VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600783 m_surface_description.pNext = NULL;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600784#ifdef _WIN32
Ian Elliott7e40db92015-08-21 15:09:33 -0600785 m_surface_description.platform = VK_PLATFORM_WIN32_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600786 m_surface_description.pPlatformHandle = m_connection;
787 m_surface_description.pPlatformWindow = m_window;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600788#else // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -0600789 m_platform_handle_xcb.connection = m_connection;
790 m_platform_handle_xcb.root = m_screen->root;
Ian Elliott7e40db92015-08-21 15:09:33 -0600791 m_surface_description.platform = VK_PLATFORM_XCB_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600792 m_surface_description.pPlatformHandle = &m_platform_handle_xcb;
793 m_surface_description.pPlatformWindow = &m_window;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600794#endif // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -0600795
796 // Iterate over each queue to learn whether it supports presenting to WSI:
797 VkBool32 supportsPresent;
798 m_present_queue_node_index = UINT32_MAX;
799 std::vector<vk_testing::Queue *> queues = m_device.graphics_queues();
800 for (int i=0; i < queues.size(); i++)
801 {
802 int family_index = queues[i]->get_family_index();
Ian Elliott7e40db92015-08-21 15:09:33 -0600803 m_fpGetPhysicalDeviceSurfaceSupportKHR(m_device.phy().handle(),
Tony Barbour6a3faf02015-07-23 10:36:18 -0600804 family_index,
Ian Elliott7e40db92015-08-21 15:09:33 -0600805 (VkSurfaceDescriptionKHR *) &m_surface_description,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600806 &supportsPresent);
807 if (supportsPresent) {
808 m_present_queue_node_index = family_index;
809 }
810 }
811
812 assert(m_present_queue_node_index != UINT32_MAX);
813
814
815 // Get the list of VkFormat's that are supported:
Ian Elliott8b139792015-08-07 11:51:12 -0600816 uint32_t formatCount;
Ian Elliott7e40db92015-08-21 15:09:33 -0600817 err = m_fpGetSurfaceFormatsKHR(m_device.handle(),
818 (VkSurfaceDescriptionKHR *) &m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600819 &formatCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600820 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600821 VkSurfaceFormatKHR *surfFormats =
822 (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
823 err = m_fpGetSurfaceFormatsKHR(m_device.handle(),
824 (VkSurfaceDescriptionKHR *) &m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600825 &formatCount, surfFormats);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600826 assert(!err);
827 // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
828 // the surface has no preferred format. Otherwise, at least one
829 // supported format will be returned.
Tony Barbour6a3faf02015-07-23 10:36:18 -0600830 if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED)
831 {
832 m_format = VK_FORMAT_B8G8R8A8_UNORM;
833 }
834 else
835 {
836 assert(formatCount >= 1);
837 m_format = surfFormats[0].format;
838 }
Ian Elliott8b139792015-08-07 11:51:12 -0600839 m_color_space = surfFormats[0].colorSpace;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600840
841 // Check the surface proprties and formats
Ian Elliott7e40db92015-08-21 15:09:33 -0600842 VkSurfacePropertiesKHR surfProperties;
843 err = m_fpGetSurfacePropertiesKHR(m_device.handle(),
844 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600845 &surfProperties);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600846 assert(!err);
847
Ian Elliott8b139792015-08-07 11:51:12 -0600848 uint32_t presentModeCount;
Ian Elliott7e40db92015-08-21 15:09:33 -0600849 err = m_fpGetSurfacePresentModesKHR(m_device.handle(),
850 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600851 &presentModeCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600852 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600853 VkPresentModeKHR *presentModes =
854 (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
Ian Elliott8b139792015-08-07 11:51:12 -0600855 assert(presentModes);
Ian Elliott7e40db92015-08-21 15:09:33 -0600856 err = m_fpGetSurfacePresentModesKHR(m_device.handle(),
857 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600858 &presentModeCount, presentModes);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600859 assert(!err);
860
Ian Elliott7e40db92015-08-21 15:09:33 -0600861 VkExtent2D swapchainExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600862 // width and height are either both -1, or both not -1.
Ian Elliott8b139792015-08-07 11:51:12 -0600863 if (surfProperties.currentExtent.width == -1)
Tony Barbour6a3faf02015-07-23 10:36:18 -0600864 {
865 // If the surface size is undefined, the size is set to
866 // the size of the images requested.
Ian Elliott7e40db92015-08-21 15:09:33 -0600867 swapchainExtent.width = m_width;
868 swapchainExtent.height = m_height;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600869 }
870 else
871 {
872 // If the surface size is defined, the swap chain size must match
Ian Elliott7e40db92015-08-21 15:09:33 -0600873 swapchainExtent = surfProperties.currentExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600874 }
875
876 // If mailbox mode is available, use it, as is the lowest-latency non-
Ian Elliottae0e8242015-08-10 13:20:49 -0600877 // tearing mode. If not, try IMMEDIATE which will usually be available,
878 // and is fastest (though it tears). If not, fall back to FIFO which is
879 // always available.
Ian Elliott7e40db92015-08-21 15:09:33 -0600880 VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600881 for (size_t i = 0; i < presentModeCount; i++) {
Ian Elliott7e40db92015-08-21 15:09:33 -0600882 if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
883 swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600884 break;
885 }
Ian Elliott7e40db92015-08-21 15:09:33 -0600886 if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) &&
887 (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
888 swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
Ian Elliottae0e8242015-08-10 13:20:49 -0600889 }
Tony Barbour6a3faf02015-07-23 10:36:18 -0600890 }
891
892 // Determine the number of VkImage's to use in the swap chain (we desire to
893 // own only 1 image at a time, besides the images being displayed and
894 // queued for display):
Ian Elliott7e40db92015-08-21 15:09:33 -0600895 uint32_t desiredNumberOfSwapchainImages = surfProperties.minImageCount + 1;
Ian Elliott8b139792015-08-07 11:51:12 -0600896 if ((surfProperties.maxImageCount > 0) &&
Ian Elliott7e40db92015-08-21 15:09:33 -0600897 (desiredNumberOfSwapchainImages > surfProperties.maxImageCount))
Tony Barbour6a3faf02015-07-23 10:36:18 -0600898 {
899 // Application must settle for fewer images than desired:
Ian Elliott7e40db92015-08-21 15:09:33 -0600900 desiredNumberOfSwapchainImages = surfProperties.maxImageCount;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600901 }
902
Ian Elliott7e40db92015-08-21 15:09:33 -0600903 VkSurfaceTransformKHR preTransform;
904 if (surfProperties.supportedTransforms & VK_SURFACE_TRANSFORM_NONE_BIT_KHR) {
905 preTransform = VK_SURFACE_TRANSFORM_NONE_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600906 } else {
Ian Elliott8b139792015-08-07 11:51:12 -0600907 preTransform = surfProperties.currentTransform;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600908 }
Ian Elliott1a3845b2015-07-06 14:33:04 -0600909
Cody Northropdf5b0922015-08-28 16:22:48 -0600910 // We want to blit to the swap chain, ensure the driver supports it. Color is always supported, per WSI spec.
911 assert((surfProperties.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT) != 0);
912
Ian Elliott7e40db92015-08-21 15:09:33 -0600913 VkSwapchainCreateInfoKHR swap_chain = {};
Ian Elliotta257eea2015-09-22 10:20:23 -0600914 swap_chain.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600915 swap_chain.pNext = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600916 swap_chain.pSurfaceDescription = (const VkSurfaceDescriptionKHR *)&m_surface_description;
917 swap_chain.minImageCount = desiredNumberOfSwapchainImages;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600918 swap_chain.imageFormat = m_format;
Ian Elliott8b139792015-08-07 11:51:12 -0600919 swap_chain.imageColorSpace = m_color_space;
Ian Elliott7e40db92015-08-21 15:09:33 -0600920 swap_chain.imageExtent.width = swapchainExtent.width;
921 swap_chain.imageExtent.height = swapchainExtent.height;
Cody Northropdf8f42a2015-08-05 15:38:39 -0600922 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT |
923 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600924 swap_chain.preTransform = preTransform;
Chia-I Wuf8693382015-04-16 22:02:10 +0800925 swap_chain.imageArraySize = 1;
Ian Elliott8b139792015-08-07 11:51:12 -0600926 swap_chain.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
927 swap_chain.queueFamilyCount = 0;
928 swap_chain.pQueueFamilyIndices = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600929 swap_chain.presentMode = swapchainPresentMode;
Chia-I Wue2fc5522015-10-26 20:04:44 +0800930 swap_chain.oldSwapchain = VK_NULL_HANDLE;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600931 swap_chain.clipped = true;
932
933 uint32_t i;
Chia-I Wuf8693382015-04-16 22:02:10 +0800934
Ian Elliott7e40db92015-08-21 15:09:33 -0600935 err = m_fpCreateSwapchainKHR(m_device.handle(), &swap_chain, &m_swap_chain);
Chia-I Wuf8693382015-04-16 22:02:10 +0800936 assert(!err);
937
Ian Elliott7e40db92015-08-21 15:09:33 -0600938 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
939 &m_swapchainImageCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600940 assert(!err);
941
Ian Elliott7e40db92015-08-21 15:09:33 -0600942 VkImage* swapchainImages = (VkImage*)malloc(m_swapchainImageCount * sizeof(VkImage));
943 assert(swapchainImages);
944 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
945 &m_swapchainImageCount, swapchainImages);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600946 assert(!err);
947
Ian Elliott7e40db92015-08-21 15:09:33 -0600948 m_buffers = (SwapchainBuffers*)malloc(sizeof(SwapchainBuffers)*m_swapchainImageCount);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600949 assert(m_buffers);
950
Ian Elliott7e40db92015-08-21 15:09:33 -0600951 for (i = 0; i < m_swapchainImageCount; i++) {
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600952 VkImageViewCreateInfo color_image_view = {};
953 color_image_view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
954 color_image_view.pNext = NULL;
Courtney Goeltzenleuchter00265c82015-09-11 15:22:06 -0600955 color_image_view.viewType = VK_IMAGE_VIEW_TYPE_2D;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600956 color_image_view.format = m_format;
Courtney Goeltzenleuchterba724512015-09-10 17:58:54 -0600957 color_image_view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600958 color_image_view.subresourceRange.baseMipLevel = 0;
Courtney Goeltzenleuchter8367ce02015-10-16 09:46:00 -0600959 color_image_view.subresourceRange.numLevels = 1;
Courtney Goeltzenleuchter4a261892015-09-10 16:38:41 -0600960 color_image_view.subresourceRange.baseArrayLayer = 0;
Courtney Goeltzenleuchter8367ce02015-10-16 09:46:00 -0600961 color_image_view.subresourceRange.numLayers = 1;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600962
Ian Elliott7e40db92015-08-21 15:09:33 -0600963 m_buffers[i].image = swapchainImages[i];
Tony Barbour6a3faf02015-07-23 10:36:18 -0600964
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600965 color_image_view.image = m_buffers[i].image;
966 err = vkCreateImageView(m_device.handle(),
967 &color_image_view, &m_buffers[i].view);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600968 assert(!err);
Tony Barbourbd094ce2015-10-23 11:00:15 -0600969
970 /* Set image layout to PRESENT_SOURCE_KHR so that before the copy, it can be set to */
971 /* TRANSFER_DESTINATION_OPTIMAL */
972 SetImageLayout(m_buffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT,
973 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SOURCE_KHR);
974
Tony Barbour6a3faf02015-07-23 10:36:18 -0600975 }
Tony Barbour96db8822015-02-25 12:28:39 -0700976}
Tony Barbourbd094ce2015-10-23 11:00:15 -0600977void TestFrameworkVkPresent::SetImageLayout(VkImage image, VkImageAspectFlags aspectMask,
978 VkImageLayout old_image_layout, VkImageLayout new_image_layout)
979{
980 VkResult U_ASSERT_ONLY err;
981
982 VkCmdBufferBeginInfo cmd_buf_info = {};
983 cmd_buf_info.sType = VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO;
984 cmd_buf_info.pNext = NULL;
Courtney Goeltzenleuchter04bb5f82015-10-21 18:11:04 -0600985 cmd_buf_info.flags = VK_CMD_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600986 cmd_buf_info.renderPass = { VK_NULL_HANDLE };
987 cmd_buf_info.subpass = 0;
988 cmd_buf_info.framebuffer = { VK_NULL_HANDLE };
989
990 err = vkBeginCommandBuffer(m_cmdbuf.handle(), &cmd_buf_info);
991 assert(!err);
992
993 VkImageMemoryBarrier image_memory_barrier = {};
994 image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
995 image_memory_barrier.pNext = NULL;
996 image_memory_barrier.outputMask = 0;
997 image_memory_barrier.inputMask = 0;
998 image_memory_barrier.oldLayout = old_image_layout;
999 image_memory_barrier.newLayout = new_image_layout;
1000 image_memory_barrier.image = image;
1001 image_memory_barrier.subresourceRange.aspectMask = aspectMask;
1002 image_memory_barrier.subresourceRange.baseMipLevel = 0;
Courtney Goeltzenleuchter8367ce02015-10-16 09:46:00 -06001003 image_memory_barrier.subresourceRange.numLevels = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001004 image_memory_barrier.subresourceRange.baseArrayLayer = 0;
Courtney Goeltzenleuchter8367ce02015-10-16 09:46:00 -06001005 image_memory_barrier.subresourceRange.numLayers = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001006
1007 if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL) {
1008 /* Make sure anything that was copying from this image has completed */
1009 image_memory_barrier.inputMask = VK_MEMORY_INPUT_TRANSFER_BIT;
1010 }
1011
1012 if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
1013 /* Make sure any Copy or CPU writes to image are flushed */
1014 image_memory_barrier.outputMask = VK_MEMORY_OUTPUT_HOST_WRITE_BIT | VK_MEMORY_OUTPUT_TRANSFER_BIT;
1015 }
1016
1017 VkImageMemoryBarrier *pmemory_barrier = &image_memory_barrier;
1018
1019 VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1020 VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1021
1022 vkCmdPipelineBarrier(m_cmdbuf.handle(), src_stages, dest_stages, false, 1, (const void * const*)&pmemory_barrier);
1023
1024 err = vkEndCommandBuffer(m_cmdbuf.handle());
1025 assert(!err);
1026
1027 const VkCmdBuffer cmd_bufs[] = { m_cmdbuf.handle() };
1028 VkFence nullFence = { VK_NULL_HANDLE };
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001029 VkSubmitInfo submit_info;
1030 submit_info.waitSemCount = 0;
1031 submit_info.pWaitSemaphores = NULL;
1032 submit_info.cmdBufferCount = 1;
1033 submit_info.pCommandBuffers = cmd_bufs;
1034 submit_info.signalSemCount = 0;
1035 submit_info.pSignalSemaphores = NULL;
1036
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -06001037 err = vkQueueSubmit(m_queue.handle(), 1, &submit_info, nullFence);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001038 assert(!err);
1039
1040 err = vkQueueWaitIdle(m_queue.handle());
1041 assert(!err);
1042
1043}
Tony Barbour96db8822015-02-25 12:28:39 -07001044
Jon Ashburn07daee72015-05-21 18:13:33 -06001045void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -07001046{
Ian Elliott7e40db92015-08-21 15:09:33 -06001047 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceSupportKHR);
1048 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfacePropertiesKHR);
1049 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfaceFormatsKHR);
1050 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfacePresentModesKHR);
1051 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1052 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1053 GET_DEVICE_PROC_ADDR(m_device.handle(), DestroySwapchainKHR);
1054 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSwapchainImagesKHR);
1055 GET_DEVICE_PROC_ADDR(m_device.handle(), AcquireNextImageKHR);
1056 GET_DEVICE_PROC_ADDR(m_device.handle(), QueuePresentKHR);
Jon Ashburn07daee72015-05-21 18:13:33 -06001057
Tony Barbour96db8822015-02-25 12:28:39 -07001058 m_images = imagesIn;
1059}
1060
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001061#ifdef _WIN32
1062void TestFrameworkVkPresent::CreateMyWindow()
1063{
1064 WNDCLASSEX win_class;
1065 // const ::testing::TestInfo* const test_info =
1066 // ::testing::UnitTest::GetInstance()->current_test_info();
1067 m_connection = GetModuleHandle(NULL);
1068
1069 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1070 it != m_images.end(); it++) {
1071 if (m_width < it->m_width)
1072 m_width = it->m_width;
1073 if (m_height < it->m_height)
1074 m_height = it->m_height;
1075 }
1076 // Initialize the window class structure:
1077 win_class.cbSize = sizeof(WNDCLASSEX);
1078 win_class.style = CS_HREDRAW | CS_VREDRAW;
1079 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
1080 win_class.cbClsExtra = 0;
1081 win_class.cbWndExtra = 0;
1082 win_class.hInstance = m_connection; // hInstance
1083 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
1084 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
1085 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
1086 win_class.lpszMenuName = NULL;
1087 win_class.lpszClassName = "Test";
1088 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
1089 // Register window class:
1090 if (!RegisterClassEx(&win_class)) {
1091 // It didn't work, so try to give a useful error:
1092 printf("Unexpected error trying to start the application!\n");
1093 fflush(stdout);
1094 exit(1);
1095 }
1096 // Create window with the registered class:
Cody Northrop39582252015-08-05 15:39:31 -06001097 RECT wr = { 0, 0, m_width, m_height };
1098 AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001099 m_window = CreateWindowEx(0,
1100 "Test", // class name
1101 "Test", // app name
1102 WS_OVERLAPPEDWINDOW | // window style
1103 WS_VISIBLE |
1104 WS_SYSMENU,
1105 100,100, // x/y coords
Cody Northrop39582252015-08-05 15:39:31 -06001106 wr.right - wr.left, // width
1107 wr.bottom - wr.top, // height
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001108 NULL, // handle to parent
1109 NULL, // handle to menu
1110 m_connection, // hInstance
1111 NULL); // no extra parameters
1112
1113 if (!m_window) {
1114 // It didn't work, so try to give a useful error:
1115 DWORD error = GetLastError();
1116 char message[120];
1117 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
1118 MessageBox(NULL, message, "Error", MB_OK);
1119 exit(1);
1120 }
Tony-LunarG399dfca2015-05-19 14:08:26 -06001121 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
1122 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001123}
1124#else
Tony Barbour6918cd52015-04-09 12:58:51 -06001125void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -07001126{
Chia-I Wuf8693382015-04-16 22:02:10 +08001127 const xcb_setup_t *setup;
1128 xcb_screen_iterator_t iter;
1129 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -07001130 uint32_t value_mask, value_list[32];
1131
Chia-I Wuf8693382015-04-16 22:02:10 +08001132 m_connection = xcb_connect(NULL, &scr);
1133
1134 setup = xcb_get_setup(m_connection);
1135 iter = xcb_setup_roots_iterator(setup);
1136 while (scr-- > 0)
1137 xcb_screen_next(&iter);
1138
1139 m_screen = iter.data;
1140
1141 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1142 it != m_images.end(); it++) {
1143 if (m_width < it->m_width)
1144 m_width = it->m_width;
1145 if (m_height < it->m_height)
1146 m_height = it->m_height;
1147 }
1148
1149 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -07001150
1151 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +08001152 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -07001153 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
1154 XCB_EVENT_MASK_EXPOSURE |
1155 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
1156
Chia-I Wuf8693382015-04-16 22:02:10 +08001157 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -07001158 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001159 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -07001160 0, 0, m_width, m_height, 0,
1161 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001162 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -07001163 value_mask, value_list);
1164
1165 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +08001166 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -07001167 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +08001168 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001169
Chia-I Wuf8693382015-04-16 22:02:10 +08001170 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
1171 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001172
Chia-I Wuf8693382015-04-16 22:02:10 +08001173 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -07001174 m_window, (*reply).atom, 4, 32, 1,
1175 &(*m_atom_wm_delete_window).atom);
1176 free(reply);
1177
Chia-I Wuf8693382015-04-16 22:02:10 +08001178 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -07001179}
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001180#endif
Tony Barbour96db8822015-02-25 12:28:39 -07001181
Tony Barbour6918cd52015-04-09 12:58:51 -06001182void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -07001183{
Ian Elliott7e40db92015-08-21 15:09:33 -06001184 m_fpDestroySwapchainKHR(m_device.handle(), m_swap_chain);
Tony Barbour9226a822015-10-23 10:58:56 -06001185
1186 for (uint32_t i = 0; i < m_swapchainImageCount; i++) {
1187 vkDestroyImageView(m_device.handle(), m_buffers[i].view);
1188 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001189#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +08001190 xcb_destroy_window(m_connection, m_window);
1191 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001192#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001193}
1194
Tony Barbour6918cd52015-04-09 12:58:51 -06001195void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001196{
1197 if (m_images.size() == 0) return;
1198
Chia-I Wuf8693382015-04-16 22:02:10 +08001199 vk_testing::Environment env;
1200 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -07001201 {
Chia-I Wuf8693382015-04-16 22:02:10 +08001202 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -07001203
Jon Ashburn07daee72015-05-21 18:13:33 -06001204 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001205 vkPresent.CreateMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -06001206 vkPresent.CreateSwapchain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001207 vkPresent.Run();
1208 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -07001209 }
Chia-I Wuf8693382015-04-16 22:02:10 +08001210 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001211}
1212
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001213//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001214// These are the default resources for TBuiltInResources, used for both
1215// - parsing this string for the case where the user didn't supply one
1216// - dumping out a template for user construction of a config file
1217//
1218static const char* DefaultConfig =
1219 "MaxLights 32\n"
1220 "MaxClipPlanes 6\n"
1221 "MaxTextureUnits 32\n"
1222 "MaxTextureCoords 32\n"
1223 "MaxVertexAttribs 64\n"
1224 "MaxVertexUniformComponents 4096\n"
1225 "MaxVaryingFloats 64\n"
1226 "MaxVertexTextureImageUnits 32\n"
1227 "MaxCombinedTextureImageUnits 80\n"
1228 "MaxTextureImageUnits 32\n"
1229 "MaxFragmentUniformComponents 4096\n"
1230 "MaxDrawBuffers 32\n"
1231 "MaxVertexUniformVectors 128\n"
1232 "MaxVaryingVectors 8\n"
1233 "MaxFragmentUniformVectors 16\n"
1234 "MaxVertexOutputVectors 16\n"
1235 "MaxFragmentInputVectors 15\n"
1236 "MinProgramTexelOffset -8\n"
1237 "MaxProgramTexelOffset 7\n"
1238 "MaxClipDistances 8\n"
1239 "MaxComputeWorkGroupCountX 65535\n"
1240 "MaxComputeWorkGroupCountY 65535\n"
1241 "MaxComputeWorkGroupCountZ 65535\n"
1242 "MaxComputeWorkGroupSizeX 1024\n"
1243 "MaxComputeWorkGroupSizeY 1024\n"
1244 "MaxComputeWorkGroupSizeZ 64\n"
1245 "MaxComputeUniformComponents 1024\n"
1246 "MaxComputeTextureImageUnits 16\n"
1247 "MaxComputeImageUniforms 8\n"
1248 "MaxComputeAtomicCounters 8\n"
1249 "MaxComputeAtomicCounterBuffers 1\n"
1250 "MaxVaryingComponents 60\n"
1251 "MaxVertexOutputComponents 64\n"
1252 "MaxGeometryInputComponents 64\n"
1253 "MaxGeometryOutputComponents 128\n"
1254 "MaxFragmentInputComponents 128\n"
1255 "MaxImageUnits 8\n"
1256 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
1257 "MaxCombinedShaderOutputResources 8\n"
1258 "MaxImageSamples 0\n"
1259 "MaxVertexImageUniforms 0\n"
1260 "MaxTessControlImageUniforms 0\n"
1261 "MaxTessEvaluationImageUniforms 0\n"
1262 "MaxGeometryImageUniforms 0\n"
1263 "MaxFragmentImageUniforms 8\n"
1264 "MaxCombinedImageUniforms 8\n"
1265 "MaxGeometryTextureImageUnits 16\n"
1266 "MaxGeometryOutputVertices 256\n"
1267 "MaxGeometryTotalOutputComponents 1024\n"
1268 "MaxGeometryUniformComponents 1024\n"
1269 "MaxGeometryVaryingComponents 64\n"
1270 "MaxTessControlInputComponents 128\n"
1271 "MaxTessControlOutputComponents 128\n"
1272 "MaxTessControlTextureImageUnits 16\n"
1273 "MaxTessControlUniformComponents 1024\n"
1274 "MaxTessControlTotalOutputComponents 4096\n"
1275 "MaxTessEvaluationInputComponents 128\n"
1276 "MaxTessEvaluationOutputComponents 128\n"
1277 "MaxTessEvaluationTextureImageUnits 16\n"
1278 "MaxTessEvaluationUniformComponents 1024\n"
1279 "MaxTessPatchComponents 120\n"
1280 "MaxPatchVertices 32\n"
1281 "MaxTessGenLevel 64\n"
1282 "MaxViewports 16\n"
1283 "MaxVertexAtomicCounters 0\n"
1284 "MaxTessControlAtomicCounters 0\n"
1285 "MaxTessEvaluationAtomicCounters 0\n"
1286 "MaxGeometryAtomicCounters 0\n"
1287 "MaxFragmentAtomicCounters 8\n"
1288 "MaxCombinedAtomicCounters 8\n"
1289 "MaxAtomicCounterBindings 1\n"
1290 "MaxVertexAtomicCounterBuffers 0\n"
1291 "MaxTessControlAtomicCounterBuffers 0\n"
1292 "MaxTessEvaluationAtomicCounterBuffers 0\n"
1293 "MaxGeometryAtomicCounterBuffers 0\n"
1294 "MaxFragmentAtomicCounterBuffers 1\n"
1295 "MaxCombinedAtomicCounterBuffers 1\n"
1296 "MaxAtomicCounterBufferSize 16384\n"
1297 "MaxTransformFeedbackBuffers 4\n"
1298 "MaxTransformFeedbackInterleavedComponents 64\n"
1299 "MaxCullDistances 8\n"
1300 "MaxCombinedClipAndCullDistances 8\n"
1301 "MaxSamples 4\n"
1302
1303 "nonInductiveForLoops 1\n"
1304 "whileLoops 1\n"
1305 "doWhileLoops 1\n"
1306 "generalUniformIndexing 1\n"
1307 "generalAttributeMatrixVectorIndexing 1\n"
1308 "generalVaryingIndexing 1\n"
1309 "generalSamplerIndexing 1\n"
1310 "generalVariableIndexing 1\n"
1311 "generalConstantMatrixVectorIndexing 1\n"
1312 ;
1313
1314//
1315// *.conf => this is a config file that can set limits/resources
1316//
Tony Barbour6918cd52015-04-09 12:58:51 -06001317bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001318{
1319 if (name.size() < 5)
1320 return false;
1321
1322 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
1323 ConfigFile = name;
1324 return true;
1325 }
1326
1327 return false;
1328}
1329
1330//
1331// Parse either a .conf file provided by the user or the default string above.
1332//
Tony Barbour6918cd52015-04-09 12:58:51 -06001333void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001334{
1335 char** configStrings = 0;
1336 char* config = 0;
1337 if (ConfigFile.size() > 0) {
1338 configStrings = ReadFileData(ConfigFile.c_str());
1339 if (configStrings)
1340 config = *configStrings;
1341 else {
1342 printf("Error opening configuration file; will instead use the default configuration\n");
1343 }
1344 }
1345
1346 if (config == 0) {
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001347 config = (char *) alloca(strlen(DefaultConfig) + 1);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001348 strcpy(config, DefaultConfig);
1349 }
1350
1351 const char* delims = " \t\n\r";
1352 const char* token = strtok(config, delims);
1353 while (token) {
1354 const char* valueStr = strtok(0, delims);
1355 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1356 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1357 return;
1358 }
1359 int value = atoi(valueStr);
1360
1361 if (strcmp(token, "MaxLights") == 0)
1362 Resources.maxLights = value;
1363 else if (strcmp(token, "MaxClipPlanes") == 0)
1364 Resources.maxClipPlanes = value;
1365 else if (strcmp(token, "MaxTextureUnits") == 0)
1366 Resources.maxTextureUnits = value;
1367 else if (strcmp(token, "MaxTextureCoords") == 0)
1368 Resources.maxTextureCoords = value;
1369 else if (strcmp(token, "MaxVertexAttribs") == 0)
1370 Resources.maxVertexAttribs = value;
1371 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1372 Resources.maxVertexUniformComponents = value;
1373 else if (strcmp(token, "MaxVaryingFloats") == 0)
1374 Resources.maxVaryingFloats = value;
1375 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1376 Resources.maxVertexTextureImageUnits = value;
1377 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1378 Resources.maxCombinedTextureImageUnits = value;
1379 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1380 Resources.maxTextureImageUnits = value;
1381 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1382 Resources.maxFragmentUniformComponents = value;
1383 else if (strcmp(token, "MaxDrawBuffers") == 0)
1384 Resources.maxDrawBuffers = value;
1385 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1386 Resources.maxVertexUniformVectors = value;
1387 else if (strcmp(token, "MaxVaryingVectors") == 0)
1388 Resources.maxVaryingVectors = value;
1389 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1390 Resources.maxFragmentUniformVectors = value;
1391 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1392 Resources.maxVertexOutputVectors = value;
1393 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1394 Resources.maxFragmentInputVectors = value;
1395 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1396 Resources.minProgramTexelOffset = value;
1397 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1398 Resources.maxProgramTexelOffset = value;
1399 else if (strcmp(token, "MaxClipDistances") == 0)
1400 Resources.maxClipDistances = value;
1401 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1402 Resources.maxComputeWorkGroupCountX = value;
1403 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1404 Resources.maxComputeWorkGroupCountY = value;
1405 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1406 Resources.maxComputeWorkGroupCountZ = value;
1407 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1408 Resources.maxComputeWorkGroupSizeX = value;
1409 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1410 Resources.maxComputeWorkGroupSizeY = value;
1411 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1412 Resources.maxComputeWorkGroupSizeZ = value;
1413 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1414 Resources.maxComputeUniformComponents = value;
1415 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1416 Resources.maxComputeTextureImageUnits = value;
1417 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1418 Resources.maxComputeImageUniforms = value;
1419 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1420 Resources.maxComputeAtomicCounters = value;
1421 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1422 Resources.maxComputeAtomicCounterBuffers = value;
1423 else if (strcmp(token, "MaxVaryingComponents") == 0)
1424 Resources.maxVaryingComponents = value;
1425 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1426 Resources.maxVertexOutputComponents = value;
1427 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1428 Resources.maxGeometryInputComponents = value;
1429 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1430 Resources.maxGeometryOutputComponents = value;
1431 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1432 Resources.maxFragmentInputComponents = value;
1433 else if (strcmp(token, "MaxImageUnits") == 0)
1434 Resources.maxImageUnits = value;
1435 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1436 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1437 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1438 Resources.maxCombinedShaderOutputResources = value;
1439 else if (strcmp(token, "MaxImageSamples") == 0)
1440 Resources.maxImageSamples = value;
1441 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1442 Resources.maxVertexImageUniforms = value;
1443 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1444 Resources.maxTessControlImageUniforms = value;
1445 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1446 Resources.maxTessEvaluationImageUniforms = value;
1447 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1448 Resources.maxGeometryImageUniforms = value;
1449 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1450 Resources.maxFragmentImageUniforms = value;
1451 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1452 Resources.maxCombinedImageUniforms = value;
1453 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1454 Resources.maxGeometryTextureImageUnits = value;
1455 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1456 Resources.maxGeometryOutputVertices = value;
1457 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1458 Resources.maxGeometryTotalOutputComponents = value;
1459 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1460 Resources.maxGeometryUniformComponents = value;
1461 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1462 Resources.maxGeometryVaryingComponents = value;
1463 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1464 Resources.maxTessControlInputComponents = value;
1465 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1466 Resources.maxTessControlOutputComponents = value;
1467 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1468 Resources.maxTessControlTextureImageUnits = value;
1469 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1470 Resources.maxTessControlUniformComponents = value;
1471 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1472 Resources.maxTessControlTotalOutputComponents = value;
1473 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1474 Resources.maxTessEvaluationInputComponents = value;
1475 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1476 Resources.maxTessEvaluationOutputComponents = value;
1477 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1478 Resources.maxTessEvaluationTextureImageUnits = value;
1479 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1480 Resources.maxTessEvaluationUniformComponents = value;
1481 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1482 Resources.maxTessPatchComponents = value;
1483 else if (strcmp(token, "MaxPatchVertices") == 0)
1484 Resources.maxPatchVertices = value;
1485 else if (strcmp(token, "MaxTessGenLevel") == 0)
1486 Resources.maxTessGenLevel = value;
1487 else if (strcmp(token, "MaxViewports") == 0)
1488 Resources.maxViewports = value;
1489 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1490 Resources.maxVertexAtomicCounters = value;
1491 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1492 Resources.maxTessControlAtomicCounters = value;
1493 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1494 Resources.maxTessEvaluationAtomicCounters = value;
1495 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1496 Resources.maxGeometryAtomicCounters = value;
1497 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1498 Resources.maxFragmentAtomicCounters = value;
1499 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1500 Resources.maxCombinedAtomicCounters = value;
1501 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1502 Resources.maxAtomicCounterBindings = value;
1503 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1504 Resources.maxVertexAtomicCounterBuffers = value;
1505 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1506 Resources.maxTessControlAtomicCounterBuffers = value;
1507 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1508 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1509 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1510 Resources.maxGeometryAtomicCounterBuffers = value;
1511 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1512 Resources.maxFragmentAtomicCounterBuffers = value;
1513 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1514 Resources.maxCombinedAtomicCounterBuffers = value;
1515 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1516 Resources.maxAtomicCounterBufferSize = value;
1517 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1518 Resources.maxTransformFeedbackBuffers = value;
1519 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1520 Resources.maxTransformFeedbackInterleavedComponents = value;
1521 else if (strcmp(token, "MaxCullDistances") == 0)
1522 Resources.maxCullDistances = value;
1523 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1524 Resources.maxCombinedClipAndCullDistances = value;
1525 else if (strcmp(token, "MaxSamples") == 0)
1526 Resources.maxSamples = value;
1527
1528 else if (strcmp(token, "nonInductiveForLoops") == 0)
1529 Resources.limits.nonInductiveForLoops = (value != 0);
1530 else if (strcmp(token, "whileLoops") == 0)
1531 Resources.limits.whileLoops = (value != 0);
1532 else if (strcmp(token, "doWhileLoops") == 0)
1533 Resources.limits.doWhileLoops = (value != 0);
1534 else if (strcmp(token, "generalUniformIndexing") == 0)
1535 Resources.limits.generalUniformIndexing = (value != 0);
1536 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1537 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1538 else if (strcmp(token, "generalVaryingIndexing") == 0)
1539 Resources.limits.generalVaryingIndexing = (value != 0);
1540 else if (strcmp(token, "generalSamplerIndexing") == 0)
1541 Resources.limits.generalSamplerIndexing = (value != 0);
1542 else if (strcmp(token, "generalVariableIndexing") == 0)
1543 Resources.limits.generalVariableIndexing = (value != 0);
1544 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1545 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1546 else
1547 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1548
1549 token = strtok(0, delims);
1550 }
1551 if (configStrings)
1552 FreeFileData(configStrings);
1553}
1554
Tony Barbour6918cd52015-04-09 12:58:51 -06001555void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001556{
1557 if (m_compile_options & EOptionRelaxedErrors)
1558 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1559 if (m_compile_options & EOptionIntermediate)
1560 messages = (EShMessages)(messages | EShMsgAST);
1561 if (m_compile_options & EOptionSuppressWarnings)
1562 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1563}
1564
1565//
1566// Malloc a string of sufficient size and read a string into it.
1567//
Tony Barbour6918cd52015-04-09 12:58:51 -06001568char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001569{
1570 FILE *in;
1571 #if defined(_WIN32) && defined(__GNUC__)
1572 in = fopen(fileName, "r");
1573 int errorCode = in ? 0 : 1;
1574 #else
1575 int errorCode = fopen_s(&in, fileName, "r");
1576 #endif
1577
1578 char *fdata;
1579 int count = 0;
1580 const int maxSourceStrings = 5;
1581 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1582
1583 if (errorCode) {
1584 printf("Error: unable to open input file: %s\n", fileName);
1585 return 0;
1586 }
1587
1588 while (fgetc(in) != EOF)
1589 count++;
1590
1591 fseek(in, 0, SEEK_SET);
1592
1593 if (!(fdata = (char*)malloc(count+2))) {
1594 printf("Error allocating memory\n");
1595 return 0;
1596 }
1597 if (fread(fdata,1,count, in)!=count) {
1598 printf("Error reading input file: %s\n", fileName);
1599 return 0;
1600 }
1601 fdata[count] = '\0';
1602 fclose(in);
1603 if (count == 0) {
1604 return_data[0]=(char*)malloc(count+2);
1605 return_data[0][0]='\0';
1606 m_num_shader_strings = 0;
1607 return return_data;
1608 } else
1609 m_num_shader_strings = 1;
1610
1611 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1612 int ptr_len=0,i=0;
1613 while(count>0){
1614 return_data[i]=(char*)malloc(len+2);
1615 memcpy(return_data[i],fdata+ptr_len,len);
1616 return_data[i][len]='\0';
1617 count-=(len);
1618 ptr_len+=(len);
1619 if(count<len){
1620 if(count==0){
1621 m_num_shader_strings=(i+1);
1622 break;
1623 }
1624 len = count;
1625 }
1626 ++i;
1627 }
1628 return return_data;
1629}
1630
Tony Barbour6918cd52015-04-09 12:58:51 -06001631void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001632{
1633 for(int i=0;i<m_num_shader_strings;i++)
1634 free(data[i]);
1635}
1636
1637//
1638// Deduce the language from the filename. Files must end in one of the
1639// following extensions:
1640//
1641// .vert = vertex
1642// .tesc = tessellation control
1643// .tese = tessellation evaluation
1644// .geom = geometry
1645// .frag = fragment
1646// .comp = compute
1647//
Tony Barbour6918cd52015-04-09 12:58:51 -06001648EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001649{
1650 size_t ext = name.rfind('.');
1651 if (ext == std::string::npos) {
1652 return EShLangVertex;
1653 }
1654
1655 std::string suffix = name.substr(ext + 1, std::string::npos);
1656 if (suffix == "vert")
1657 return EShLangVertex;
1658 else if (suffix == "tesc")
1659 return EShLangTessControl;
1660 else if (suffix == "tese")
1661 return EShLangTessEvaluation;
1662 else if (suffix == "geom")
1663 return EShLangGeometry;
1664 else if (suffix == "frag")
1665 return EShLangFragment;
1666 else if (suffix == "comp")
1667 return EShLangCompute;
1668
1669 return EShLangVertex;
1670}
1671
1672//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001673// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001674//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001675EShLanguage VkTestFramework::FindLanguage(const VkShaderStageFlagBits shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001676{
1677 switch (shader_type) {
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001678 case VK_SHADER_STAGE_VERTEX_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001679 return EShLangVertex;
1680
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001681 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001682 return EShLangTessControl;
1683
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001684 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001685 return EShLangTessEvaluation;
1686
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001687 case VK_SHADER_STAGE_GEOMETRY_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001688 return EShLangGeometry;
1689
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001690 case VK_SHADER_STAGE_FRAGMENT_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001691 return EShLangFragment;
1692
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001693 case VK_SHADER_STAGE_COMPUTE_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001694 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001695
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001696 default:
1697 return EShLangVertex;
1698 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001699}
1700
1701
1702//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001703// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001704// Return value of false means an error was encountered.
1705//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001706bool VkTestFramework::GLSLtoSPV(const VkShaderStageFlagBits shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001707 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001708 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001709{
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001710 glslang::TProgram program;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001711 const char *shaderStrings[1];
1712
1713 // TODO: Do we want to load a special config file depending on the
1714 // shader source? Optional name maybe?
1715 // SetConfigFile(fileName);
1716
1717 ProcessConfigFile();
1718
1719 EShMessages messages = EShMsgDefault;
1720 SetMessageOptions(messages);
1721
1722 EShLanguage stage = FindLanguage(shader_type);
1723 glslang::TShader* shader = new glslang::TShader(stage);
1724
1725 shaderStrings[0] = pshader;
1726 shader->setStrings(shaderStrings, 1);
1727
1728 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1729
Cody Northrop195d6622014-11-03 12:54:37 -07001730 if (! (m_compile_options & EOptionSuppressInfolog)) {
1731 puts(shader->getInfoLog());
1732 puts(shader->getInfoDebugLog());
1733 }
1734
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001735 return false; // something didn't work
1736 }
1737
1738 program.addShader(shader);
1739
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001740
1741 //
1742 // Program-level processing...
1743 //
1744
Cody Northrop195d6622014-11-03 12:54:37 -07001745 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001746
Cody Northrop195d6622014-11-03 12:54:37 -07001747 if (! (m_compile_options & EOptionSuppressInfolog)) {
1748 puts(shader->getInfoLog());
1749 puts(shader->getInfoDebugLog());
1750 }
1751
1752 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001753 }
1754
1755 if (m_compile_options & EOptionDumpReflection) {
1756 program.buildReflection();
1757 program.dumpReflection();
1758 }
1759
Cody Northrop5a95b472015-06-03 13:01:54 -06001760 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1761
1762 //
1763 // Test the different modes of SPIR-V modification
1764 //
1765 if (this->m_canonicalize_spv) {
1766 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1767 }
1768
1769 if (this->m_strip_spv) {
1770 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1771 }
1772
1773 if (this->m_do_everything_spv) {
1774 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1775 }
1776
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001777 delete shader;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001778
1779 return true;
1780}
1781
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001782
1783
Tony Barbour6918cd52015-04-09 12:58:51 -06001784VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001785 m_width( 0 ),
1786 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001787 m_data( NULL ),
1788 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001789{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001790}
1791
Tony Barbour6918cd52015-04-09 12:58:51 -06001792VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001793{
1794
1795}
1796
Tony Barbour6918cd52015-04-09 12:58:51 -06001797VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001798{
1799 m_title = copyin.m_title;
1800 m_width = copyin.m_width;
1801 m_height = copyin.m_height;
1802 m_data_size = copyin.m_data_size;
1803 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1804}
1805
Tony Barbour6918cd52015-04-09 12:58:51 -06001806ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001807{
Tony Barbour6918cd52015-04-09 12:58:51 -06001808 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1809 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001810 return output;
1811}
1812
Tony Barbour6918cd52015-04-09 12:58:51 -06001813VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001814{
1815 m_title = rhs.m_title;
1816 m_width = rhs.m_width;
1817 m_height = rhs.m_height;
1818 m_data_size = rhs.m_data_size;
1819 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001820 return *this;
1821}
1822
Tony Barbour6918cd52015-04-09 12:58:51 -06001823int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001824{
1825 if( this->m_data != rhs.m_data) return 0;
1826 return 1;
1827}
1828
1829// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001830int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001831{
1832 if( this->m_data_size < rhs.m_data_size ) return 1;
1833 return 0;
1834}
1835