blob: eed63439829511235472182a0d5e511d5ba399d8 [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;
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600307 VkResult err;
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600308 uint32_t x, y;
Tony Barbour6918cd52015-04-09 12:58:51 -0600309 VkImageObj displayImage(image->device());
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600310 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbour84d448c2015-04-02 14:02:33 -0600311
Tony Barboure65788f2015-07-21 17:01:42 -0600312 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 -0600313 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600314
315 filename.append(basename);
316 filename.append(".ppm");
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600317
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600318 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600319 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600320 };
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600321 VkSubresourceLayout sr_layout;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600322
Tony Barbour59a47322015-06-24 16:06:58 -0600323 err = vkGetImageSubresourceLayout(image->device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600324 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600325
Tony Barbour84d448c2015-04-02 14:02:33 -0600326 char *ptr;
Chia-I Wu681d7a02015-07-03 13:44:34 +0800327 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600328 ptr += sr_layout.offset;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600329 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600330 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
331
332 file << "P6\n";
Tony Barbourfeb61962015-09-21 15:17:33 -0600333 file << displayImage.width() << " ";
Tony Barbour84d448c2015-04-02 14:02:33 -0600334 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600335 file << 255 << "\n";
336
Tony Barbour84d448c2015-04-02 14:02:33 -0600337 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700338 const int *row = (const int *) ptr;
339 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600340
Tony Barbourd1c35722015-04-16 15:59:00 -0600341 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700342 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600343 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700344 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
345 file.write((char *) &swapped, 3);
346 row++;
347 }
348 }
Tony Barbourd1c35722015-04-16 15:59:00 -0600349 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700350 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600351 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700352 file.write((char *) row, 3);
353 row++;
354 }
355 }
356 else {
357 printf("Unrecognized image format - will not write image files");
358 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600359 }
360
361 ptr += sr_layout.rowPitch;
362 }
363
364 file.close();
Chia-I Wu681d7a02015-07-03 13:44:34 +0800365 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600366}
367
Tony Barbour6918cd52015-04-09 12:58:51 -0600368void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour247bf372014-10-30 14:29:04 -0600369{
370
371 MagickWand *magick_wand_1;
372 MagickWand *magick_wand_2;
373 MagickWand *compare_wand;
374 MagickBooleanType status;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600375 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600376 double differenz;
377
Tony Barbour4ab45422014-12-10 17:00:20 -0700378 if (getenv("RENDERTEST_GOLDEN_DIR"))
379 {
380 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
381 }
382
Tony Barbour247bf372014-10-30 14:29:04 -0600383 MagickWandGenesis();
384 magick_wand_1=NewMagickWand();
385 sprintf(testimage,"%s.ppm",basename);
386 status=MagickReadImage(magick_wand_1,testimage);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600387 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour247bf372014-10-30 14:29:04 -0600388
389
390 MagickWandGenesis();
391 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700392 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600393 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600394 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour247bf372014-10-30 14:29:04 -0600395
Tony Barbour247bf372014-10-30 14:29:04 -0600396 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
397 if (differenz != 0.0)
398 {
399 char difference[256];
400
401 sprintf(difference,"%s-diff.ppm",basename);
402 status = MagickWriteImage(compare_wand, difference);
403 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
404 }
405 DestroyMagickWand(compare_wand);
406
407 DestroyMagickWand(magick_wand_1);
408 DestroyMagickWand(magick_wand_2);
409 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700410
411 if (differenz == 0.0)
412 {
413 /*
414 * If test image and golden image match, we do not need to
415 * keep around the test image.
416 */
417 remove(testimage);
418 }
Tony Barbour247bf372014-10-30 14:29:04 -0600419}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600420
Tony Barbour6918cd52015-04-09 12:58:51 -0600421void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600422{
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600423 VkResult err;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600424 VkSubresourceLayout sr_layout;
425 char *ptr;
426 VkTestImageRecord record;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600427 VkImageObj displayImage(image->device());
428 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
429
Cody Northropc9a69912015-06-18 17:05:15 -0600430 displayImage.init(image->extent().width, image->extent().height, image->format(), VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT, VK_IMAGE_TILING_LINEAR, reqs);
431
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600432 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600433
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600434 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600435 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600436 };
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600437
Tony Barbour59a47322015-06-24 16:06:58 -0600438 err = vkGetImageSubresourceLayout(displayImage.device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600439 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600440
Chia-I Wu681d7a02015-07-03 13:44:34 +0800441 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600442 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600443
444 ptr += sr_layout.offset;
445
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600446 record.m_title.append(comment);
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600447 record.m_width = displayImage.width();
448 record.m_height = displayImage.height();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600449 // TODO: Need to make this more robust to handle different image formats
Tony-LunarG399dfca2015-05-19 14:08:26 -0600450 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600451 record.m_data = malloc(record.m_data_size);
452 memcpy(record.m_data, ptr, record.m_data_size);
453 m_images.push_back(record);
454 m_display_image = --m_images.end();
455
Chia-I Wu681d7a02015-07-03 13:44:34 +0800456 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600457}
458
Tony Barbour6918cd52015-04-09 12:58:51 -0600459void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600460{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600461 for (int32_t i = 0; i < images.size(); i++) {
462 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600463 }
464}
465
Tony Barbour6918cd52015-04-09 12:58:51 -0600466void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600467{
468 const ::testing::TestInfo* const test_info =
469 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600470 ostringstream filestream;
471 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600472
Tony Barbour247bf372014-10-30 14:29:04 -0600473 m_width = 40;
474
475 if (strcmp(test_info->name(), m_testName.c_str())) {
476 filestream << test_info->name();
477 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700478 m_frameNum = 2;
479 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600480 }
481 else {
482 filestream << test_info->name() << "-" << m_frameNum;
483 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700484 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600485 }
486
Tony Barbour247bf372014-10-30 14:29:04 -0600487 // ToDo - scrub string for bad characters
488
489 if (m_save_images || m_compare_images) {
490 WritePPM(filename.c_str(), image);
491 if (m_compare_images) {
492 Compare(filename.c_str(), image);
493 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600494 }
495
496 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600497 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600498 }
499}
500
Chia-I Wuf8693382015-04-16 22:02:10 +0800501TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
502 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700503 m_queue(*m_device.graphics_queues()[0]),
Dana Jansens233a0ea2015-07-30 13:04:16 -0700504 m_cmdpool(m_device, vk_testing::CmdPool::create_info(m_device.graphics_queue_node_index_)),
505 m_cmdbuf(m_device, vk_testing::CmdBuffer::create_info(m_cmdpool.handle()))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600506{
Tony Barbour96db8822015-02-25 12:28:39 -0700507 m_quit = false;
508 m_pause = false;
509 m_width = 0;
510 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600511}
512
Tony Barbour6918cd52015-04-09 12:58:51 -0600513void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600514{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600515 VkResult U_ASSERT_ONLY err;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600516 vk_testing::Buffer buf;
517 void *dest_ptr;
518
Tony Barbour6a3faf02015-07-23 10:36:18 -0600519 VkSemaphore presentCompleteSemaphore;
520 VkSemaphoreCreateInfo presentCompleteSemaphoreCreateInfo = {};
521 presentCompleteSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
522 presentCompleteSemaphoreCreateInfo.pNext = NULL;
523 presentCompleteSemaphoreCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
524
525
526 err = vkCreateSemaphore(m_device.handle(),
527 &presentCompleteSemaphoreCreateInfo,
528 &presentCompleteSemaphore);
529 assert(!err);
530
531 // Get the index of the next available swapchain image:
Ian Elliott7e40db92015-08-21 15:09:33 -0600532 err = m_fpAcquireNextImageKHR(m_device.handle(), m_swap_chain,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600533 UINT64_MAX,
534 presentCompleteSemaphore,
535 &m_current_buffer);
Ian Elliott7e40db92015-08-21 15:09:33 -0600536 // TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
Tony Barbour6a3faf02015-07-23 10:36:18 -0600537 // return codes
538 assert(!err);
539
540 // Wait for the present complete semaphore to be signaled to ensure
541 // that the image won't be rendered to until the presentation
542 // engine has fully released ownership to the application, and it is
543 // okay to render to the image.
544 vkQueueWaitSemaphore(m_queue.handle(), presentCompleteSemaphore);
Tony Barbour9226a822015-10-23 10:58:56 -0600545 vkDestroySemaphore(m_device.handle(), presentCompleteSemaphore);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600546
547 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Cody Northrop7fb43862015-06-22 14:56:14 -0600548 buf.init_as_src(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800549 dest_ptr = buf.memory().map();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600550 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800551 buf.memory().unmap();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600552
553 m_cmdbuf.begin();
Tony Barbourbd094ce2015-10-23 11:00:15 -0600554 VkImageMemoryBarrier memoryBarrier = {};
555 memoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
556 memoryBarrier.pNext = NULL;
557 memoryBarrier.outputMask = VK_MEMORY_OUTPUT_COLOR_ATTACHMENT_BIT;
558 memoryBarrier.inputMask = 0;
559 memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SOURCE_KHR;
560 memoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL;
561 memoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
562 memoryBarrier.destQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
563 memoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
564 memoryBarrier.subresourceRange.baseMipLevel = 0;
565 memoryBarrier.subresourceRange.mipLevels = 1;
566 memoryBarrier.subresourceRange.baseArrayLayer = 0;
567 memoryBarrier.subresourceRange.arraySize = 1;
568 memoryBarrier.image = m_buffers[m_current_buffer].image;
569 VkImageMemoryBarrier *pmemory_barrier = &memoryBarrier;
570 vkCmdPipelineBarrier(m_cmdbuf.handle(), VK_PIPELINE_STAGE_ALL_GPU_COMMANDS, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
571 VK_FALSE, 1, (const void * const*)&pmemory_barrier);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600572
573 VkBufferImageCopy region = {};
574 region.imageExtent.height = m_display_image->m_height;
575 region.imageExtent.width = m_display_image->m_width;
576 region.imageExtent.depth = 1;
577
Chia-I Wube2b9172015-07-03 11:49:42 +0800578 vkCmdCopyBufferToImage(m_cmdbuf.handle(),
Chia-I Wu681d7a02015-07-03 13:44:34 +0800579 buf.handle(),
Tony Barbour6a3faf02015-07-23 10:36:18 -0600580 m_buffers[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600581 1, &region);
Tony Barbourbd094ce2015-10-23 11:00:15 -0600582
583 memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL;
584 memoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SOURCE_KHR;
585 vkCmdPipelineBarrier(m_cmdbuf.handle(), VK_PIPELINE_STAGE_ALL_GPU_COMMANDS, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
586 VK_FALSE, 1, (const void * const*)&pmemory_barrier);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600587 m_cmdbuf.end();
588
589 VkCmdBuffer cmdBufs[1];
Chia-I Wube2b9172015-07-03 11:49:42 +0800590 cmdBufs[0] = m_cmdbuf.handle();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600591
Tony Barbour67e99152015-07-10 14:10:27 -0600592 VkFence nullFence = { VK_NULL_HANDLE };
593 vkQueueSubmit(m_queue.handle(), 1, cmdBufs, nullFence);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600594 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700595
Ian Elliott7e40db92015-08-21 15:09:33 -0600596 VkPresentInfoKHR present = {};
597 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600598 present.pNext = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600599 present.swapchainCount = 1;
600 present.swapchains = & m_swap_chain;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600601 present.imageIndices = &m_current_buffer;
Tony Barbour96db8822015-02-25 12:28:39 -0700602
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600603#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800604 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700605 XCB_PROP_MODE_REPLACE,
606 m_window,
607 XCB_ATOM_WM_NAME,
608 XCB_ATOM_STRING,
609 8,
610 m_display_image->m_title.size(),
611 m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600612#endif
Jon Ashburn07daee72015-05-21 18:13:33 -0600613
Ian Elliott7e40db92015-08-21 15:09:33 -0600614 err = m_fpQueuePresentKHR(m_queue.handle(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700615 assert(!err);
616
617 m_queue.wait();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600618 m_current_buffer = (m_current_buffer + 1) % 2;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600619}
620
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600621#ifdef _WIN32
Tony-LunarG399dfca2015-05-19 14:08:26 -0600622# define PREVIOUSLY_DOWN 1<<29
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600623// MS-Windows event handling function:
624LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
625 UINT uMsg,
626 WPARAM wParam,
627 LPARAM lParam)
628{
629
630 switch(uMsg)
631 {
632 case WM_CLOSE:
633 PostQuitMessage(0);
634 break;
635
636 case WM_PAINT:
637 {
638 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
639 if (me) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600640 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600641 me->Display();
642 }
643 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600644 break;
645
646 case WM_KEYDOWN:
647 {
648 if (lParam & (PREVIOUSLY_DOWN)){
649 break;
650 }
651 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
652 // the window, we put the this pointer into the window's user data so we could get it back now
653 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
654 switch (wParam)
655 {
656 case VK_ESCAPE: me->m_quit = true;
657 break;
658
659 case VK_LEFT: // left arrow key
660 if (me->m_display_image == me->m_images.begin()) {
661 me->m_display_image = --me->m_images.end();
662 }
663 else {
664 --me->m_display_image;
665 }
666 break;
667
668 case VK_RIGHT: // right arrow key
669 ++me->m_display_image;
670 if (me->m_display_image == me->m_images.end()) {
671 me->m_display_image = me->m_images.begin();
672 }
673 break;
674
675 default:
676 break;
677 }
678 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
679 me->Display();
680 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600681 }
682 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
683}
684
685void TestFrameworkVkPresent::Run()
686{
687 MSG msg; // message
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600688
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600689 /* main message loop*/
Tony-LunarG399dfca2015-05-19 14:08:26 -0600690 while(! m_quit) {
691 GetMessage(&msg, m_window, 0, 0);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600692 if (msg.message == WM_QUIT) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600693 m_quit = true; //if found, quit app
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600694 } else {
695 /* Translate and dispatch to event queue*/
696 TranslateMessage(&msg);
697 DispatchMessage(&msg);
698 }
699 }
700}
701
702#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600703void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600704{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600705 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700706 switch (event_code) {
707 case XCB_EXPOSE:
708 Display(); // TODO: handle resize
709 break;
710 case XCB_CLIENT_MESSAGE:
711 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
712 (m_atom_wm_delete_window)->atom) {
713 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600714 }
715 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700716 case XCB_KEY_RELEASE:
717 {
718 const xcb_key_release_event_t *key =
719 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600720
Tony Barbour96db8822015-02-25 12:28:39 -0700721 switch (key->detail) {
722 case 0x9: // Escape
723 m_quit = true;
724 break;
725 case 0x71: // left arrow key
726 if (m_display_image == m_images.begin()) {
727 m_display_image = --m_images.end();
728 } else {
729 --m_display_image;
730 }
731 break;
732 case 0x72: // right arrow key
733 ++m_display_image;
734 if (m_display_image == m_images.end()) {
735 m_display_image = m_images.begin();
736 }
737 break;
738 case 0x41:
739 m_pause = !m_pause;
740 break;
741 }
742 Display();
743 }
744 break;
745 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600746 break;
747 }
Tony Barbour96db8822015-02-25 12:28:39 -0700748}
749
Tony Barbour6918cd52015-04-09 12:58:51 -0600750void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700751{
Chia-I Wuf8693382015-04-16 22:02:10 +0800752 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700753
754 while (! m_quit) {
755 xcb_generic_event_t *event;
756
757 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800758 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700759 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800760 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700761 }
762 if (event) {
763 HandleEvent(event);
764 free(event);
765 }
766 }
767}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600768#endif // _WIN32
Tony Barbour96db8822015-02-25 12:28:39 -0700769
Ian Elliott7e40db92015-08-21 15:09:33 -0600770void TestFrameworkVkPresent::CreateSwapchain()
Tony Barbour96db8822015-02-25 12:28:39 -0700771{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600772 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700773
Tony-LunarG399dfca2015-05-19 14:08:26 -0600774 m_display_image = m_images.begin();
775 m_current_buffer = 0;
776
Tony Barbour6a3faf02015-07-23 10:36:18 -0600777 // Construct the WSI surface description:
Ian Elliott7e40db92015-08-21 15:09:33 -0600778 m_surface_description.sType = VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600779 m_surface_description.pNext = NULL;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600780#ifdef _WIN32
Ian Elliott7e40db92015-08-21 15:09:33 -0600781 m_surface_description.platform = VK_PLATFORM_WIN32_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600782 m_surface_description.pPlatformHandle = m_connection;
783 m_surface_description.pPlatformWindow = m_window;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600784#else // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -0600785 m_platform_handle_xcb.connection = m_connection;
786 m_platform_handle_xcb.root = m_screen->root;
Ian Elliott7e40db92015-08-21 15:09:33 -0600787 m_surface_description.platform = VK_PLATFORM_XCB_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600788 m_surface_description.pPlatformHandle = &m_platform_handle_xcb;
789 m_surface_description.pPlatformWindow = &m_window;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600790#endif // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -0600791
792 // Iterate over each queue to learn whether it supports presenting to WSI:
793 VkBool32 supportsPresent;
794 m_present_queue_node_index = UINT32_MAX;
795 std::vector<vk_testing::Queue *> queues = m_device.graphics_queues();
796 for (int i=0; i < queues.size(); i++)
797 {
798 int family_index = queues[i]->get_family_index();
Ian Elliott7e40db92015-08-21 15:09:33 -0600799 m_fpGetPhysicalDeviceSurfaceSupportKHR(m_device.phy().handle(),
Tony Barbour6a3faf02015-07-23 10:36:18 -0600800 family_index,
Ian Elliott7e40db92015-08-21 15:09:33 -0600801 (VkSurfaceDescriptionKHR *) &m_surface_description,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600802 &supportsPresent);
803 if (supportsPresent) {
804 m_present_queue_node_index = family_index;
805 }
806 }
807
808 assert(m_present_queue_node_index != UINT32_MAX);
809
810
811 // Get the list of VkFormat's that are supported:
Ian Elliott8b139792015-08-07 11:51:12 -0600812 uint32_t formatCount;
Ian Elliott7e40db92015-08-21 15:09:33 -0600813 err = m_fpGetSurfaceFormatsKHR(m_device.handle(),
814 (VkSurfaceDescriptionKHR *) &m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600815 &formatCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600816 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600817 VkSurfaceFormatKHR *surfFormats =
818 (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
819 err = m_fpGetSurfaceFormatsKHR(m_device.handle(),
820 (VkSurfaceDescriptionKHR *) &m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600821 &formatCount, surfFormats);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600822 assert(!err);
823 // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
824 // the surface has no preferred format. Otherwise, at least one
825 // supported format will be returned.
Tony Barbour6a3faf02015-07-23 10:36:18 -0600826 if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED)
827 {
828 m_format = VK_FORMAT_B8G8R8A8_UNORM;
829 }
830 else
831 {
832 assert(formatCount >= 1);
833 m_format = surfFormats[0].format;
834 }
Ian Elliott8b139792015-08-07 11:51:12 -0600835 m_color_space = surfFormats[0].colorSpace;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600836
837 // Check the surface proprties and formats
Ian Elliott7e40db92015-08-21 15:09:33 -0600838 VkSurfacePropertiesKHR surfProperties;
839 err = m_fpGetSurfacePropertiesKHR(m_device.handle(),
840 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600841 &surfProperties);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600842 assert(!err);
843
Ian Elliott8b139792015-08-07 11:51:12 -0600844 uint32_t presentModeCount;
Ian Elliott7e40db92015-08-21 15:09:33 -0600845 err = m_fpGetSurfacePresentModesKHR(m_device.handle(),
846 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600847 &presentModeCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600848 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600849 VkPresentModeKHR *presentModes =
850 (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
Ian Elliott8b139792015-08-07 11:51:12 -0600851 assert(presentModes);
Ian Elliott7e40db92015-08-21 15:09:33 -0600852 err = m_fpGetSurfacePresentModesKHR(m_device.handle(),
853 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600854 &presentModeCount, presentModes);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600855 assert(!err);
856
Ian Elliott7e40db92015-08-21 15:09:33 -0600857 VkExtent2D swapchainExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600858 // width and height are either both -1, or both not -1.
Ian Elliott8b139792015-08-07 11:51:12 -0600859 if (surfProperties.currentExtent.width == -1)
Tony Barbour6a3faf02015-07-23 10:36:18 -0600860 {
861 // If the surface size is undefined, the size is set to
862 // the size of the images requested.
Ian Elliott7e40db92015-08-21 15:09:33 -0600863 swapchainExtent.width = m_width;
864 swapchainExtent.height = m_height;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600865 }
866 else
867 {
868 // If the surface size is defined, the swap chain size must match
Ian Elliott7e40db92015-08-21 15:09:33 -0600869 swapchainExtent = surfProperties.currentExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600870 }
871
872 // If mailbox mode is available, use it, as is the lowest-latency non-
Ian Elliottae0e8242015-08-10 13:20:49 -0600873 // tearing mode. If not, try IMMEDIATE which will usually be available,
874 // and is fastest (though it tears). If not, fall back to FIFO which is
875 // always available.
Ian Elliott7e40db92015-08-21 15:09:33 -0600876 VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600877 for (size_t i = 0; i < presentModeCount; i++) {
Ian Elliott7e40db92015-08-21 15:09:33 -0600878 if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
879 swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600880 break;
881 }
Ian Elliott7e40db92015-08-21 15:09:33 -0600882 if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) &&
883 (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
884 swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
Ian Elliottae0e8242015-08-10 13:20:49 -0600885 }
Tony Barbour6a3faf02015-07-23 10:36:18 -0600886 }
887
888 // Determine the number of VkImage's to use in the swap chain (we desire to
889 // own only 1 image at a time, besides the images being displayed and
890 // queued for display):
Ian Elliott7e40db92015-08-21 15:09:33 -0600891 uint32_t desiredNumberOfSwapchainImages = surfProperties.minImageCount + 1;
Ian Elliott8b139792015-08-07 11:51:12 -0600892 if ((surfProperties.maxImageCount > 0) &&
Ian Elliott7e40db92015-08-21 15:09:33 -0600893 (desiredNumberOfSwapchainImages > surfProperties.maxImageCount))
Tony Barbour6a3faf02015-07-23 10:36:18 -0600894 {
895 // Application must settle for fewer images than desired:
Ian Elliott7e40db92015-08-21 15:09:33 -0600896 desiredNumberOfSwapchainImages = surfProperties.maxImageCount;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600897 }
898
Ian Elliott7e40db92015-08-21 15:09:33 -0600899 VkSurfaceTransformKHR preTransform;
900 if (surfProperties.supportedTransforms & VK_SURFACE_TRANSFORM_NONE_BIT_KHR) {
901 preTransform = VK_SURFACE_TRANSFORM_NONE_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600902 } else {
Ian Elliott8b139792015-08-07 11:51:12 -0600903 preTransform = surfProperties.currentTransform;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600904 }
Ian Elliott1a3845b2015-07-06 14:33:04 -0600905
Cody Northropdf5b0922015-08-28 16:22:48 -0600906 // We want to blit to the swap chain, ensure the driver supports it. Color is always supported, per WSI spec.
907 assert((surfProperties.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT) != 0);
908
Ian Elliott7e40db92015-08-21 15:09:33 -0600909 VkSwapchainCreateInfoKHR swap_chain = {};
Ian Elliotta257eea2015-09-22 10:20:23 -0600910 swap_chain.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600911 swap_chain.pNext = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600912 swap_chain.pSurfaceDescription = (const VkSurfaceDescriptionKHR *)&m_surface_description;
913 swap_chain.minImageCount = desiredNumberOfSwapchainImages;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600914 swap_chain.imageFormat = m_format;
Ian Elliott8b139792015-08-07 11:51:12 -0600915 swap_chain.imageColorSpace = m_color_space;
Ian Elliott7e40db92015-08-21 15:09:33 -0600916 swap_chain.imageExtent.width = swapchainExtent.width;
917 swap_chain.imageExtent.height = swapchainExtent.height;
Cody Northropdf8f42a2015-08-05 15:38:39 -0600918 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT |
919 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600920 swap_chain.preTransform = preTransform;
Chia-I Wuf8693382015-04-16 22:02:10 +0800921 swap_chain.imageArraySize = 1;
Ian Elliott8b139792015-08-07 11:51:12 -0600922 swap_chain.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
923 swap_chain.queueFamilyCount = 0;
924 swap_chain.pQueueFamilyIndices = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600925 swap_chain.presentMode = swapchainPresentMode;
926 swap_chain.oldSwapchain.handle = 0;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600927 swap_chain.clipped = true;
928
929 uint32_t i;
Chia-I Wuf8693382015-04-16 22:02:10 +0800930
Ian Elliott7e40db92015-08-21 15:09:33 -0600931 err = m_fpCreateSwapchainKHR(m_device.handle(), &swap_chain, &m_swap_chain);
Chia-I Wuf8693382015-04-16 22:02:10 +0800932 assert(!err);
933
Ian Elliott7e40db92015-08-21 15:09:33 -0600934 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
935 &m_swapchainImageCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600936 assert(!err);
937
Ian Elliott7e40db92015-08-21 15:09:33 -0600938 VkImage* swapchainImages = (VkImage*)malloc(m_swapchainImageCount * sizeof(VkImage));
939 assert(swapchainImages);
940 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
941 &m_swapchainImageCount, swapchainImages);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600942 assert(!err);
943
Ian Elliott7e40db92015-08-21 15:09:33 -0600944 m_buffers = (SwapchainBuffers*)malloc(sizeof(SwapchainBuffers)*m_swapchainImageCount);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600945 assert(m_buffers);
946
Ian Elliott7e40db92015-08-21 15:09:33 -0600947 for (i = 0; i < m_swapchainImageCount; i++) {
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600948 VkImageViewCreateInfo color_image_view = {};
949 color_image_view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
950 color_image_view.pNext = NULL;
Courtney Goeltzenleuchter00265c82015-09-11 15:22:06 -0600951 color_image_view.viewType = VK_IMAGE_VIEW_TYPE_2D;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600952 color_image_view.format = m_format;
Courtney Goeltzenleuchterba724512015-09-10 17:58:54 -0600953 color_image_view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600954 color_image_view.subresourceRange.baseMipLevel = 0;
955 color_image_view.subresourceRange.mipLevels = 1;
Courtney Goeltzenleuchter4a261892015-09-10 16:38:41 -0600956 color_image_view.subresourceRange.baseArrayLayer = 0;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600957 color_image_view.subresourceRange.arraySize = 1;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600958
Ian Elliott7e40db92015-08-21 15:09:33 -0600959 m_buffers[i].image = swapchainImages[i];
Tony Barbour6a3faf02015-07-23 10:36:18 -0600960
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600961 color_image_view.image = m_buffers[i].image;
962 err = vkCreateImageView(m_device.handle(),
963 &color_image_view, &m_buffers[i].view);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600964 assert(!err);
Tony Barbourbd094ce2015-10-23 11:00:15 -0600965
966 /* Set image layout to PRESENT_SOURCE_KHR so that before the copy, it can be set to */
967 /* TRANSFER_DESTINATION_OPTIMAL */
968 SetImageLayout(m_buffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT,
969 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SOURCE_KHR);
970
Tony Barbour6a3faf02015-07-23 10:36:18 -0600971 }
Tony Barbour96db8822015-02-25 12:28:39 -0700972}
Tony Barbourbd094ce2015-10-23 11:00:15 -0600973void TestFrameworkVkPresent::SetImageLayout(VkImage image, VkImageAspectFlags aspectMask,
974 VkImageLayout old_image_layout, VkImageLayout new_image_layout)
975{
976 VkResult U_ASSERT_ONLY err;
977
978 VkCmdBufferBeginInfo cmd_buf_info = {};
979 cmd_buf_info.sType = VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO;
980 cmd_buf_info.pNext = NULL;
981 cmd_buf_info.flags = VK_CMD_BUFFER_OPTIMIZE_SMALL_BATCH_BIT |
982 VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT;
983 cmd_buf_info.renderPass = { VK_NULL_HANDLE };
984 cmd_buf_info.subpass = 0;
985 cmd_buf_info.framebuffer = { VK_NULL_HANDLE };
986
987 err = vkBeginCommandBuffer(m_cmdbuf.handle(), &cmd_buf_info);
988 assert(!err);
989
990 VkImageMemoryBarrier image_memory_barrier = {};
991 image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
992 image_memory_barrier.pNext = NULL;
993 image_memory_barrier.outputMask = 0;
994 image_memory_barrier.inputMask = 0;
995 image_memory_barrier.oldLayout = old_image_layout;
996 image_memory_barrier.newLayout = new_image_layout;
997 image_memory_barrier.image = image;
998 image_memory_barrier.subresourceRange.aspectMask = aspectMask;
999 image_memory_barrier.subresourceRange.baseMipLevel = 0;
1000 image_memory_barrier.subresourceRange.mipLevels = 1;
1001 image_memory_barrier.subresourceRange.baseArrayLayer = 0;
1002 image_memory_barrier.subresourceRange.arraySize = 1;
1003
1004 if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL) {
1005 /* Make sure anything that was copying from this image has completed */
1006 image_memory_barrier.inputMask = VK_MEMORY_INPUT_TRANSFER_BIT;
1007 }
1008
1009 if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
1010 /* Make sure any Copy or CPU writes to image are flushed */
1011 image_memory_barrier.outputMask = VK_MEMORY_OUTPUT_HOST_WRITE_BIT | VK_MEMORY_OUTPUT_TRANSFER_BIT;
1012 }
1013
1014 VkImageMemoryBarrier *pmemory_barrier = &image_memory_barrier;
1015
1016 VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1017 VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1018
1019 vkCmdPipelineBarrier(m_cmdbuf.handle(), src_stages, dest_stages, false, 1, (const void * const*)&pmemory_barrier);
1020
1021 err = vkEndCommandBuffer(m_cmdbuf.handle());
1022 assert(!err);
1023
1024 const VkCmdBuffer cmd_bufs[] = { m_cmdbuf.handle() };
1025 VkFence nullFence = { VK_NULL_HANDLE };
1026
1027 err = vkQueueSubmit(m_queue.handle(), 1, cmd_bufs, nullFence);
1028 assert(!err);
1029
1030 err = vkQueueWaitIdle(m_queue.handle());
1031 assert(!err);
1032
1033}
Tony Barbour96db8822015-02-25 12:28:39 -07001034
Jon Ashburn07daee72015-05-21 18:13:33 -06001035void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -07001036{
Ian Elliott7e40db92015-08-21 15:09:33 -06001037 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceSupportKHR);
1038 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfacePropertiesKHR);
1039 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfaceFormatsKHR);
1040 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfacePresentModesKHR);
1041 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1042 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1043 GET_DEVICE_PROC_ADDR(m_device.handle(), DestroySwapchainKHR);
1044 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSwapchainImagesKHR);
1045 GET_DEVICE_PROC_ADDR(m_device.handle(), AcquireNextImageKHR);
1046 GET_DEVICE_PROC_ADDR(m_device.handle(), QueuePresentKHR);
Jon Ashburn07daee72015-05-21 18:13:33 -06001047
Tony Barbour96db8822015-02-25 12:28:39 -07001048 m_images = imagesIn;
1049}
1050
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001051#ifdef _WIN32
1052void TestFrameworkVkPresent::CreateMyWindow()
1053{
1054 WNDCLASSEX win_class;
1055 // const ::testing::TestInfo* const test_info =
1056 // ::testing::UnitTest::GetInstance()->current_test_info();
1057 m_connection = GetModuleHandle(NULL);
1058
1059 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1060 it != m_images.end(); it++) {
1061 if (m_width < it->m_width)
1062 m_width = it->m_width;
1063 if (m_height < it->m_height)
1064 m_height = it->m_height;
1065 }
1066 // Initialize the window class structure:
1067 win_class.cbSize = sizeof(WNDCLASSEX);
1068 win_class.style = CS_HREDRAW | CS_VREDRAW;
1069 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
1070 win_class.cbClsExtra = 0;
1071 win_class.cbWndExtra = 0;
1072 win_class.hInstance = m_connection; // hInstance
1073 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
1074 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
1075 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
1076 win_class.lpszMenuName = NULL;
1077 win_class.lpszClassName = "Test";
1078 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
1079 // Register window class:
1080 if (!RegisterClassEx(&win_class)) {
1081 // It didn't work, so try to give a useful error:
1082 printf("Unexpected error trying to start the application!\n");
1083 fflush(stdout);
1084 exit(1);
1085 }
1086 // Create window with the registered class:
Cody Northrop39582252015-08-05 15:39:31 -06001087 RECT wr = { 0, 0, m_width, m_height };
1088 AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001089 m_window = CreateWindowEx(0,
1090 "Test", // class name
1091 "Test", // app name
1092 WS_OVERLAPPEDWINDOW | // window style
1093 WS_VISIBLE |
1094 WS_SYSMENU,
1095 100,100, // x/y coords
Cody Northrop39582252015-08-05 15:39:31 -06001096 wr.right - wr.left, // width
1097 wr.bottom - wr.top, // height
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001098 NULL, // handle to parent
1099 NULL, // handle to menu
1100 m_connection, // hInstance
1101 NULL); // no extra parameters
1102
1103 if (!m_window) {
1104 // It didn't work, so try to give a useful error:
1105 DWORD error = GetLastError();
1106 char message[120];
1107 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
1108 MessageBox(NULL, message, "Error", MB_OK);
1109 exit(1);
1110 }
Tony-LunarG399dfca2015-05-19 14:08:26 -06001111 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
1112 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001113}
1114#else
Tony Barbour6918cd52015-04-09 12:58:51 -06001115void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -07001116{
Chia-I Wuf8693382015-04-16 22:02:10 +08001117 const xcb_setup_t *setup;
1118 xcb_screen_iterator_t iter;
1119 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -07001120 uint32_t value_mask, value_list[32];
1121
Chia-I Wuf8693382015-04-16 22:02:10 +08001122 m_connection = xcb_connect(NULL, &scr);
1123
1124 setup = xcb_get_setup(m_connection);
1125 iter = xcb_setup_roots_iterator(setup);
1126 while (scr-- > 0)
1127 xcb_screen_next(&iter);
1128
1129 m_screen = iter.data;
1130
1131 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1132 it != m_images.end(); it++) {
1133 if (m_width < it->m_width)
1134 m_width = it->m_width;
1135 if (m_height < it->m_height)
1136 m_height = it->m_height;
1137 }
1138
1139 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -07001140
1141 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +08001142 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -07001143 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
1144 XCB_EVENT_MASK_EXPOSURE |
1145 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
1146
Chia-I Wuf8693382015-04-16 22:02:10 +08001147 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -07001148 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001149 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -07001150 0, 0, m_width, m_height, 0,
1151 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001152 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -07001153 value_mask, value_list);
1154
1155 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +08001156 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -07001157 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +08001158 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001159
Chia-I Wuf8693382015-04-16 22:02:10 +08001160 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
1161 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001162
Chia-I Wuf8693382015-04-16 22:02:10 +08001163 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -07001164 m_window, (*reply).atom, 4, 32, 1,
1165 &(*m_atom_wm_delete_window).atom);
1166 free(reply);
1167
Chia-I Wuf8693382015-04-16 22:02:10 +08001168 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -07001169}
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001170#endif
Tony Barbour96db8822015-02-25 12:28:39 -07001171
Tony Barbour6918cd52015-04-09 12:58:51 -06001172void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -07001173{
Ian Elliott7e40db92015-08-21 15:09:33 -06001174 m_fpDestroySwapchainKHR(m_device.handle(), m_swap_chain);
Tony Barbour9226a822015-10-23 10:58:56 -06001175
1176 for (uint32_t i = 0; i < m_swapchainImageCount; i++) {
1177 vkDestroyImageView(m_device.handle(), m_buffers[i].view);
1178 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001179#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +08001180 xcb_destroy_window(m_connection, m_window);
1181 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001182#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001183}
1184
Tony Barbour6918cd52015-04-09 12:58:51 -06001185void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001186{
1187 if (m_images.size() == 0) return;
1188
Chia-I Wuf8693382015-04-16 22:02:10 +08001189 vk_testing::Environment env;
1190 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -07001191 {
Chia-I Wuf8693382015-04-16 22:02:10 +08001192 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -07001193
Jon Ashburn07daee72015-05-21 18:13:33 -06001194 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001195 vkPresent.CreateMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -06001196 vkPresent.CreateSwapchain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001197 vkPresent.Run();
1198 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -07001199 }
Chia-I Wuf8693382015-04-16 22:02:10 +08001200 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001201}
1202
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001203//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001204// These are the default resources for TBuiltInResources, used for both
1205// - parsing this string for the case where the user didn't supply one
1206// - dumping out a template for user construction of a config file
1207//
1208static const char* DefaultConfig =
1209 "MaxLights 32\n"
1210 "MaxClipPlanes 6\n"
1211 "MaxTextureUnits 32\n"
1212 "MaxTextureCoords 32\n"
1213 "MaxVertexAttribs 64\n"
1214 "MaxVertexUniformComponents 4096\n"
1215 "MaxVaryingFloats 64\n"
1216 "MaxVertexTextureImageUnits 32\n"
1217 "MaxCombinedTextureImageUnits 80\n"
1218 "MaxTextureImageUnits 32\n"
1219 "MaxFragmentUniformComponents 4096\n"
1220 "MaxDrawBuffers 32\n"
1221 "MaxVertexUniformVectors 128\n"
1222 "MaxVaryingVectors 8\n"
1223 "MaxFragmentUniformVectors 16\n"
1224 "MaxVertexOutputVectors 16\n"
1225 "MaxFragmentInputVectors 15\n"
1226 "MinProgramTexelOffset -8\n"
1227 "MaxProgramTexelOffset 7\n"
1228 "MaxClipDistances 8\n"
1229 "MaxComputeWorkGroupCountX 65535\n"
1230 "MaxComputeWorkGroupCountY 65535\n"
1231 "MaxComputeWorkGroupCountZ 65535\n"
1232 "MaxComputeWorkGroupSizeX 1024\n"
1233 "MaxComputeWorkGroupSizeY 1024\n"
1234 "MaxComputeWorkGroupSizeZ 64\n"
1235 "MaxComputeUniformComponents 1024\n"
1236 "MaxComputeTextureImageUnits 16\n"
1237 "MaxComputeImageUniforms 8\n"
1238 "MaxComputeAtomicCounters 8\n"
1239 "MaxComputeAtomicCounterBuffers 1\n"
1240 "MaxVaryingComponents 60\n"
1241 "MaxVertexOutputComponents 64\n"
1242 "MaxGeometryInputComponents 64\n"
1243 "MaxGeometryOutputComponents 128\n"
1244 "MaxFragmentInputComponents 128\n"
1245 "MaxImageUnits 8\n"
1246 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
1247 "MaxCombinedShaderOutputResources 8\n"
1248 "MaxImageSamples 0\n"
1249 "MaxVertexImageUniforms 0\n"
1250 "MaxTessControlImageUniforms 0\n"
1251 "MaxTessEvaluationImageUniforms 0\n"
1252 "MaxGeometryImageUniforms 0\n"
1253 "MaxFragmentImageUniforms 8\n"
1254 "MaxCombinedImageUniforms 8\n"
1255 "MaxGeometryTextureImageUnits 16\n"
1256 "MaxGeometryOutputVertices 256\n"
1257 "MaxGeometryTotalOutputComponents 1024\n"
1258 "MaxGeometryUniformComponents 1024\n"
1259 "MaxGeometryVaryingComponents 64\n"
1260 "MaxTessControlInputComponents 128\n"
1261 "MaxTessControlOutputComponents 128\n"
1262 "MaxTessControlTextureImageUnits 16\n"
1263 "MaxTessControlUniformComponents 1024\n"
1264 "MaxTessControlTotalOutputComponents 4096\n"
1265 "MaxTessEvaluationInputComponents 128\n"
1266 "MaxTessEvaluationOutputComponents 128\n"
1267 "MaxTessEvaluationTextureImageUnits 16\n"
1268 "MaxTessEvaluationUniformComponents 1024\n"
1269 "MaxTessPatchComponents 120\n"
1270 "MaxPatchVertices 32\n"
1271 "MaxTessGenLevel 64\n"
1272 "MaxViewports 16\n"
1273 "MaxVertexAtomicCounters 0\n"
1274 "MaxTessControlAtomicCounters 0\n"
1275 "MaxTessEvaluationAtomicCounters 0\n"
1276 "MaxGeometryAtomicCounters 0\n"
1277 "MaxFragmentAtomicCounters 8\n"
1278 "MaxCombinedAtomicCounters 8\n"
1279 "MaxAtomicCounterBindings 1\n"
1280 "MaxVertexAtomicCounterBuffers 0\n"
1281 "MaxTessControlAtomicCounterBuffers 0\n"
1282 "MaxTessEvaluationAtomicCounterBuffers 0\n"
1283 "MaxGeometryAtomicCounterBuffers 0\n"
1284 "MaxFragmentAtomicCounterBuffers 1\n"
1285 "MaxCombinedAtomicCounterBuffers 1\n"
1286 "MaxAtomicCounterBufferSize 16384\n"
1287 "MaxTransformFeedbackBuffers 4\n"
1288 "MaxTransformFeedbackInterleavedComponents 64\n"
1289 "MaxCullDistances 8\n"
1290 "MaxCombinedClipAndCullDistances 8\n"
1291 "MaxSamples 4\n"
1292
1293 "nonInductiveForLoops 1\n"
1294 "whileLoops 1\n"
1295 "doWhileLoops 1\n"
1296 "generalUniformIndexing 1\n"
1297 "generalAttributeMatrixVectorIndexing 1\n"
1298 "generalVaryingIndexing 1\n"
1299 "generalSamplerIndexing 1\n"
1300 "generalVariableIndexing 1\n"
1301 "generalConstantMatrixVectorIndexing 1\n"
1302 ;
1303
1304//
1305// *.conf => this is a config file that can set limits/resources
1306//
Tony Barbour6918cd52015-04-09 12:58:51 -06001307bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001308{
1309 if (name.size() < 5)
1310 return false;
1311
1312 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
1313 ConfigFile = name;
1314 return true;
1315 }
1316
1317 return false;
1318}
1319
1320//
1321// Parse either a .conf file provided by the user or the default string above.
1322//
Tony Barbour6918cd52015-04-09 12:58:51 -06001323void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001324{
1325 char** configStrings = 0;
1326 char* config = 0;
1327 if (ConfigFile.size() > 0) {
1328 configStrings = ReadFileData(ConfigFile.c_str());
1329 if (configStrings)
1330 config = *configStrings;
1331 else {
1332 printf("Error opening configuration file; will instead use the default configuration\n");
1333 }
1334 }
1335
1336 if (config == 0) {
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001337 config = (char *) alloca(strlen(DefaultConfig) + 1);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001338 strcpy(config, DefaultConfig);
1339 }
1340
1341 const char* delims = " \t\n\r";
1342 const char* token = strtok(config, delims);
1343 while (token) {
1344 const char* valueStr = strtok(0, delims);
1345 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1346 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1347 return;
1348 }
1349 int value = atoi(valueStr);
1350
1351 if (strcmp(token, "MaxLights") == 0)
1352 Resources.maxLights = value;
1353 else if (strcmp(token, "MaxClipPlanes") == 0)
1354 Resources.maxClipPlanes = value;
1355 else if (strcmp(token, "MaxTextureUnits") == 0)
1356 Resources.maxTextureUnits = value;
1357 else if (strcmp(token, "MaxTextureCoords") == 0)
1358 Resources.maxTextureCoords = value;
1359 else if (strcmp(token, "MaxVertexAttribs") == 0)
1360 Resources.maxVertexAttribs = value;
1361 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1362 Resources.maxVertexUniformComponents = value;
1363 else if (strcmp(token, "MaxVaryingFloats") == 0)
1364 Resources.maxVaryingFloats = value;
1365 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1366 Resources.maxVertexTextureImageUnits = value;
1367 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1368 Resources.maxCombinedTextureImageUnits = value;
1369 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1370 Resources.maxTextureImageUnits = value;
1371 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1372 Resources.maxFragmentUniformComponents = value;
1373 else if (strcmp(token, "MaxDrawBuffers") == 0)
1374 Resources.maxDrawBuffers = value;
1375 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1376 Resources.maxVertexUniformVectors = value;
1377 else if (strcmp(token, "MaxVaryingVectors") == 0)
1378 Resources.maxVaryingVectors = value;
1379 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1380 Resources.maxFragmentUniformVectors = value;
1381 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1382 Resources.maxVertexOutputVectors = value;
1383 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1384 Resources.maxFragmentInputVectors = value;
1385 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1386 Resources.minProgramTexelOffset = value;
1387 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1388 Resources.maxProgramTexelOffset = value;
1389 else if (strcmp(token, "MaxClipDistances") == 0)
1390 Resources.maxClipDistances = value;
1391 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1392 Resources.maxComputeWorkGroupCountX = value;
1393 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1394 Resources.maxComputeWorkGroupCountY = value;
1395 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1396 Resources.maxComputeWorkGroupCountZ = value;
1397 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1398 Resources.maxComputeWorkGroupSizeX = value;
1399 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1400 Resources.maxComputeWorkGroupSizeY = value;
1401 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1402 Resources.maxComputeWorkGroupSizeZ = value;
1403 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1404 Resources.maxComputeUniformComponents = value;
1405 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1406 Resources.maxComputeTextureImageUnits = value;
1407 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1408 Resources.maxComputeImageUniforms = value;
1409 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1410 Resources.maxComputeAtomicCounters = value;
1411 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1412 Resources.maxComputeAtomicCounterBuffers = value;
1413 else if (strcmp(token, "MaxVaryingComponents") == 0)
1414 Resources.maxVaryingComponents = value;
1415 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1416 Resources.maxVertexOutputComponents = value;
1417 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1418 Resources.maxGeometryInputComponents = value;
1419 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1420 Resources.maxGeometryOutputComponents = value;
1421 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1422 Resources.maxFragmentInputComponents = value;
1423 else if (strcmp(token, "MaxImageUnits") == 0)
1424 Resources.maxImageUnits = value;
1425 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1426 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1427 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1428 Resources.maxCombinedShaderOutputResources = value;
1429 else if (strcmp(token, "MaxImageSamples") == 0)
1430 Resources.maxImageSamples = value;
1431 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1432 Resources.maxVertexImageUniforms = value;
1433 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1434 Resources.maxTessControlImageUniforms = value;
1435 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1436 Resources.maxTessEvaluationImageUniforms = value;
1437 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1438 Resources.maxGeometryImageUniforms = value;
1439 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1440 Resources.maxFragmentImageUniforms = value;
1441 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1442 Resources.maxCombinedImageUniforms = value;
1443 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1444 Resources.maxGeometryTextureImageUnits = value;
1445 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1446 Resources.maxGeometryOutputVertices = value;
1447 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1448 Resources.maxGeometryTotalOutputComponents = value;
1449 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1450 Resources.maxGeometryUniformComponents = value;
1451 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1452 Resources.maxGeometryVaryingComponents = value;
1453 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1454 Resources.maxTessControlInputComponents = value;
1455 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1456 Resources.maxTessControlOutputComponents = value;
1457 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1458 Resources.maxTessControlTextureImageUnits = value;
1459 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1460 Resources.maxTessControlUniformComponents = value;
1461 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1462 Resources.maxTessControlTotalOutputComponents = value;
1463 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1464 Resources.maxTessEvaluationInputComponents = value;
1465 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1466 Resources.maxTessEvaluationOutputComponents = value;
1467 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1468 Resources.maxTessEvaluationTextureImageUnits = value;
1469 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1470 Resources.maxTessEvaluationUniformComponents = value;
1471 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1472 Resources.maxTessPatchComponents = value;
1473 else if (strcmp(token, "MaxPatchVertices") == 0)
1474 Resources.maxPatchVertices = value;
1475 else if (strcmp(token, "MaxTessGenLevel") == 0)
1476 Resources.maxTessGenLevel = value;
1477 else if (strcmp(token, "MaxViewports") == 0)
1478 Resources.maxViewports = value;
1479 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1480 Resources.maxVertexAtomicCounters = value;
1481 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1482 Resources.maxTessControlAtomicCounters = value;
1483 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1484 Resources.maxTessEvaluationAtomicCounters = value;
1485 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1486 Resources.maxGeometryAtomicCounters = value;
1487 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1488 Resources.maxFragmentAtomicCounters = value;
1489 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1490 Resources.maxCombinedAtomicCounters = value;
1491 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1492 Resources.maxAtomicCounterBindings = value;
1493 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1494 Resources.maxVertexAtomicCounterBuffers = value;
1495 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1496 Resources.maxTessControlAtomicCounterBuffers = value;
1497 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1498 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1499 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1500 Resources.maxGeometryAtomicCounterBuffers = value;
1501 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1502 Resources.maxFragmentAtomicCounterBuffers = value;
1503 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1504 Resources.maxCombinedAtomicCounterBuffers = value;
1505 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1506 Resources.maxAtomicCounterBufferSize = value;
1507 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1508 Resources.maxTransformFeedbackBuffers = value;
1509 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1510 Resources.maxTransformFeedbackInterleavedComponents = value;
1511 else if (strcmp(token, "MaxCullDistances") == 0)
1512 Resources.maxCullDistances = value;
1513 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1514 Resources.maxCombinedClipAndCullDistances = value;
1515 else if (strcmp(token, "MaxSamples") == 0)
1516 Resources.maxSamples = value;
1517
1518 else if (strcmp(token, "nonInductiveForLoops") == 0)
1519 Resources.limits.nonInductiveForLoops = (value != 0);
1520 else if (strcmp(token, "whileLoops") == 0)
1521 Resources.limits.whileLoops = (value != 0);
1522 else if (strcmp(token, "doWhileLoops") == 0)
1523 Resources.limits.doWhileLoops = (value != 0);
1524 else if (strcmp(token, "generalUniformIndexing") == 0)
1525 Resources.limits.generalUniformIndexing = (value != 0);
1526 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1527 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1528 else if (strcmp(token, "generalVaryingIndexing") == 0)
1529 Resources.limits.generalVaryingIndexing = (value != 0);
1530 else if (strcmp(token, "generalSamplerIndexing") == 0)
1531 Resources.limits.generalSamplerIndexing = (value != 0);
1532 else if (strcmp(token, "generalVariableIndexing") == 0)
1533 Resources.limits.generalVariableIndexing = (value != 0);
1534 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1535 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1536 else
1537 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1538
1539 token = strtok(0, delims);
1540 }
1541 if (configStrings)
1542 FreeFileData(configStrings);
1543}
1544
Tony Barbour6918cd52015-04-09 12:58:51 -06001545void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001546{
1547 if (m_compile_options & EOptionRelaxedErrors)
1548 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1549 if (m_compile_options & EOptionIntermediate)
1550 messages = (EShMessages)(messages | EShMsgAST);
1551 if (m_compile_options & EOptionSuppressWarnings)
1552 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1553}
1554
1555//
1556// Malloc a string of sufficient size and read a string into it.
1557//
Tony Barbour6918cd52015-04-09 12:58:51 -06001558char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001559{
1560 FILE *in;
1561 #if defined(_WIN32) && defined(__GNUC__)
1562 in = fopen(fileName, "r");
1563 int errorCode = in ? 0 : 1;
1564 #else
1565 int errorCode = fopen_s(&in, fileName, "r");
1566 #endif
1567
1568 char *fdata;
1569 int count = 0;
1570 const int maxSourceStrings = 5;
1571 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1572
1573 if (errorCode) {
1574 printf("Error: unable to open input file: %s\n", fileName);
1575 return 0;
1576 }
1577
1578 while (fgetc(in) != EOF)
1579 count++;
1580
1581 fseek(in, 0, SEEK_SET);
1582
1583 if (!(fdata = (char*)malloc(count+2))) {
1584 printf("Error allocating memory\n");
1585 return 0;
1586 }
1587 if (fread(fdata,1,count, in)!=count) {
1588 printf("Error reading input file: %s\n", fileName);
1589 return 0;
1590 }
1591 fdata[count] = '\0';
1592 fclose(in);
1593 if (count == 0) {
1594 return_data[0]=(char*)malloc(count+2);
1595 return_data[0][0]='\0';
1596 m_num_shader_strings = 0;
1597 return return_data;
1598 } else
1599 m_num_shader_strings = 1;
1600
1601 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1602 int ptr_len=0,i=0;
1603 while(count>0){
1604 return_data[i]=(char*)malloc(len+2);
1605 memcpy(return_data[i],fdata+ptr_len,len);
1606 return_data[i][len]='\0';
1607 count-=(len);
1608 ptr_len+=(len);
1609 if(count<len){
1610 if(count==0){
1611 m_num_shader_strings=(i+1);
1612 break;
1613 }
1614 len = count;
1615 }
1616 ++i;
1617 }
1618 return return_data;
1619}
1620
Tony Barbour6918cd52015-04-09 12:58:51 -06001621void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001622{
1623 for(int i=0;i<m_num_shader_strings;i++)
1624 free(data[i]);
1625}
1626
1627//
1628// Deduce the language from the filename. Files must end in one of the
1629// following extensions:
1630//
1631// .vert = vertex
1632// .tesc = tessellation control
1633// .tese = tessellation evaluation
1634// .geom = geometry
1635// .frag = fragment
1636// .comp = compute
1637//
Tony Barbour6918cd52015-04-09 12:58:51 -06001638EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001639{
1640 size_t ext = name.rfind('.');
1641 if (ext == std::string::npos) {
1642 return EShLangVertex;
1643 }
1644
1645 std::string suffix = name.substr(ext + 1, std::string::npos);
1646 if (suffix == "vert")
1647 return EShLangVertex;
1648 else if (suffix == "tesc")
1649 return EShLangTessControl;
1650 else if (suffix == "tese")
1651 return EShLangTessEvaluation;
1652 else if (suffix == "geom")
1653 return EShLangGeometry;
1654 else if (suffix == "frag")
1655 return EShLangFragment;
1656 else if (suffix == "comp")
1657 return EShLangCompute;
1658
1659 return EShLangVertex;
1660}
1661
1662//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001663// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001664//
Tony Barbourd1c35722015-04-16 15:59:00 -06001665EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001666{
1667 switch (shader_type) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001668 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001669 return EShLangVertex;
1670
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001671 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001672 return EShLangTessControl;
1673
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001674 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001675 return EShLangTessEvaluation;
1676
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001677 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001678 return EShLangGeometry;
1679
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001680 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001681 return EShLangFragment;
1682
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001683 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001684 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001685
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001686 default:
1687 return EShLangVertex;
1688 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001689}
1690
1691
1692//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001693// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001694// Return value of false means an error was encountered.
1695//
Tony Barbourd1c35722015-04-16 15:59:00 -06001696bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001697 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001698 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001699{
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001700 glslang::TProgram program;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001701 const char *shaderStrings[1];
1702
1703 // TODO: Do we want to load a special config file depending on the
1704 // shader source? Optional name maybe?
1705 // SetConfigFile(fileName);
1706
1707 ProcessConfigFile();
1708
1709 EShMessages messages = EShMsgDefault;
1710 SetMessageOptions(messages);
1711
1712 EShLanguage stage = FindLanguage(shader_type);
1713 glslang::TShader* shader = new glslang::TShader(stage);
1714
1715 shaderStrings[0] = pshader;
1716 shader->setStrings(shaderStrings, 1);
1717
1718 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1719
Cody Northrop195d6622014-11-03 12:54:37 -07001720 if (! (m_compile_options & EOptionSuppressInfolog)) {
1721 puts(shader->getInfoLog());
1722 puts(shader->getInfoDebugLog());
1723 }
1724
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001725 return false; // something didn't work
1726 }
1727
1728 program.addShader(shader);
1729
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001730
1731 //
1732 // Program-level processing...
1733 //
1734
Cody Northrop195d6622014-11-03 12:54:37 -07001735 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001736
Cody Northrop195d6622014-11-03 12:54:37 -07001737 if (! (m_compile_options & EOptionSuppressInfolog)) {
1738 puts(shader->getInfoLog());
1739 puts(shader->getInfoDebugLog());
1740 }
1741
1742 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001743 }
1744
1745 if (m_compile_options & EOptionDumpReflection) {
1746 program.buildReflection();
1747 program.dumpReflection();
1748 }
1749
Cody Northrop5a95b472015-06-03 13:01:54 -06001750 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1751
1752 //
1753 // Test the different modes of SPIR-V modification
1754 //
1755 if (this->m_canonicalize_spv) {
1756 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1757 }
1758
1759 if (this->m_strip_spv) {
1760 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1761 }
1762
1763 if (this->m_do_everything_spv) {
1764 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1765 }
1766
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001767 delete shader;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001768
1769 return true;
1770}
1771
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001772
1773
Tony Barbour6918cd52015-04-09 12:58:51 -06001774VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001775 m_width( 0 ),
1776 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001777 m_data( NULL ),
1778 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001779{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001780}
1781
Tony Barbour6918cd52015-04-09 12:58:51 -06001782VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001783{
1784
1785}
1786
Tony Barbour6918cd52015-04-09 12:58:51 -06001787VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001788{
1789 m_title = copyin.m_title;
1790 m_width = copyin.m_width;
1791 m_height = copyin.m_height;
1792 m_data_size = copyin.m_data_size;
1793 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1794}
1795
Tony Barbour6918cd52015-04-09 12:58:51 -06001796ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001797{
Tony Barbour6918cd52015-04-09 12:58:51 -06001798 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1799 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001800 return output;
1801}
1802
Tony Barbour6918cd52015-04-09 12:58:51 -06001803VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001804{
1805 m_title = rhs.m_title;
1806 m_width = rhs.m_width;
1807 m_height = rhs.m_height;
1808 m_data_size = rhs.m_data_size;
1809 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001810 return *this;
1811}
1812
Tony Barbour6918cd52015-04-09 12:58:51 -06001813int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001814{
1815 if( this->m_data != rhs.m_data) return 0;
1816 return 1;
1817}
1818
1819// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001820int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001821{
1822 if( this->m_data_size < rhs.m_data_size ) return 1;
1823 return 0;
1824}
1825