blob: cc396466023d7d80403d4707b1e002fdf1470a7a [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 Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600318 VK_IMAGE_ASPECT_COLOR, 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 Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600433 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600434 };
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600435
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600436 vkGetImageSubresourceLayout(displayImage.device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600437
Chia-I Wu681d7a02015-07-03 13:44:34 +0800438 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600439 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600440
441 ptr += sr_layout.offset;
442
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600443 record.m_title.append(comment);
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600444 record.m_width = displayImage.width();
445 record.m_height = displayImage.height();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600446 // TODO: Need to make this more robust to handle different image formats
Tony-LunarG399dfca2015-05-19 14:08:26 -0600447 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600448 record.m_data = malloc(record.m_data_size);
449 memcpy(record.m_data, ptr, record.m_data_size);
450 m_images.push_back(record);
451 m_display_image = --m_images.end();
452
Chia-I Wu681d7a02015-07-03 13:44:34 +0800453 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600454}
455
Tony Barbour6918cd52015-04-09 12:58:51 -0600456void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600457{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600458 for (int32_t i = 0; i < images.size(); i++) {
459 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600460 }
461}
462
Tony Barbour6918cd52015-04-09 12:58:51 -0600463void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600464{
465 const ::testing::TestInfo* const test_info =
466 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600467 ostringstream filestream;
468 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600469
Tony Barbour247bf372014-10-30 14:29:04 -0600470 m_width = 40;
471
472 if (strcmp(test_info->name(), m_testName.c_str())) {
473 filestream << test_info->name();
474 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700475 m_frameNum = 2;
476 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600477 }
478 else {
479 filestream << test_info->name() << "-" << m_frameNum;
480 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700481 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600482 }
483
Tony Barbour247bf372014-10-30 14:29:04 -0600484 // ToDo - scrub string for bad characters
485
486 if (m_save_images || m_compare_images) {
487 WritePPM(filename.c_str(), image);
488 if (m_compare_images) {
489 Compare(filename.c_str(), image);
490 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600491 }
492
493 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600494 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600495 }
496}
497
Chia-I Wuf8693382015-04-16 22:02:10 +0800498TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
499 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700500 m_queue(*m_device.graphics_queues()[0]),
Dana Jansens233a0ea2015-07-30 13:04:16 -0700501 m_cmdpool(m_device, vk_testing::CmdPool::create_info(m_device.graphics_queue_node_index_)),
502 m_cmdbuf(m_device, vk_testing::CmdBuffer::create_info(m_cmdpool.handle()))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600503{
Tony Barbour96db8822015-02-25 12:28:39 -0700504 m_quit = false;
505 m_pause = false;
506 m_width = 0;
507 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600508}
509
Tony Barbour6918cd52015-04-09 12:58:51 -0600510void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600511{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600512 VkResult U_ASSERT_ONLY err;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600513 vk_testing::Buffer buf;
514 void *dest_ptr;
515
Tony Barbour6a3faf02015-07-23 10:36:18 -0600516 VkSemaphore presentCompleteSemaphore;
517 VkSemaphoreCreateInfo presentCompleteSemaphoreCreateInfo = {};
518 presentCompleteSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
519 presentCompleteSemaphoreCreateInfo.pNext = NULL;
520 presentCompleteSemaphoreCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
521
522
523 err = vkCreateSemaphore(m_device.handle(),
524 &presentCompleteSemaphoreCreateInfo,
525 &presentCompleteSemaphore);
526 assert(!err);
527
528 // Get the index of the next available swapchain image:
Ian Elliott7e40db92015-08-21 15:09:33 -0600529 err = m_fpAcquireNextImageKHR(m_device.handle(), m_swap_chain,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600530 UINT64_MAX,
531 presentCompleteSemaphore,
532 &m_current_buffer);
Ian Elliott7e40db92015-08-21 15:09:33 -0600533 // TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
Tony Barbour6a3faf02015-07-23 10:36:18 -0600534 // return codes
535 assert(!err);
536
537 // Wait for the present complete semaphore to be signaled to ensure
538 // that the image won't be rendered to until the presentation
539 // engine has fully released ownership to the application, and it is
540 // okay to render to the image.
541 vkQueueWaitSemaphore(m_queue.handle(), presentCompleteSemaphore);
Tony Barbour9226a822015-10-23 10:58:56 -0600542 vkDestroySemaphore(m_device.handle(), presentCompleteSemaphore);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600543
544 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Cody Northrop7fb43862015-06-22 14:56:14 -0600545 buf.init_as_src(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800546 dest_ptr = buf.memory().map();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600547 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800548 buf.memory().unmap();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600549
550 m_cmdbuf.begin();
Tony Barbourbd094ce2015-10-23 11:00:15 -0600551 VkImageMemoryBarrier memoryBarrier = {};
552 memoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
553 memoryBarrier.pNext = NULL;
554 memoryBarrier.outputMask = VK_MEMORY_OUTPUT_COLOR_ATTACHMENT_BIT;
555 memoryBarrier.inputMask = 0;
556 memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SOURCE_KHR;
557 memoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL;
558 memoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
559 memoryBarrier.destQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
560 memoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
561 memoryBarrier.subresourceRange.baseMipLevel = 0;
562 memoryBarrier.subresourceRange.mipLevels = 1;
563 memoryBarrier.subresourceRange.baseArrayLayer = 0;
564 memoryBarrier.subresourceRange.arraySize = 1;
565 memoryBarrier.image = m_buffers[m_current_buffer].image;
566 VkImageMemoryBarrier *pmemory_barrier = &memoryBarrier;
567 vkCmdPipelineBarrier(m_cmdbuf.handle(), VK_PIPELINE_STAGE_ALL_GPU_COMMANDS, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
568 VK_FALSE, 1, (const void * const*)&pmemory_barrier);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600569
570 VkBufferImageCopy region = {};
571 region.imageExtent.height = m_display_image->m_height;
572 region.imageExtent.width = m_display_image->m_width;
573 region.imageExtent.depth = 1;
574
Chia-I Wube2b9172015-07-03 11:49:42 +0800575 vkCmdCopyBufferToImage(m_cmdbuf.handle(),
Chia-I Wu681d7a02015-07-03 13:44:34 +0800576 buf.handle(),
Tony Barbour6a3faf02015-07-23 10:36:18 -0600577 m_buffers[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600578 1, &region);
Tony Barbourbd094ce2015-10-23 11:00:15 -0600579
580 memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL;
581 memoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SOURCE_KHR;
582 vkCmdPipelineBarrier(m_cmdbuf.handle(), VK_PIPELINE_STAGE_ALL_GPU_COMMANDS, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
583 VK_FALSE, 1, (const void * const*)&pmemory_barrier);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600584 m_cmdbuf.end();
585
586 VkCmdBuffer cmdBufs[1];
Chia-I Wube2b9172015-07-03 11:49:42 +0800587 cmdBufs[0] = m_cmdbuf.handle();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600588
Tony Barbour67e99152015-07-10 14:10:27 -0600589 VkFence nullFence = { VK_NULL_HANDLE };
590 vkQueueSubmit(m_queue.handle(), 1, cmdBufs, nullFence);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600591 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700592
Ian Elliott7e40db92015-08-21 15:09:33 -0600593 VkPresentInfoKHR present = {};
594 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600595 present.pNext = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600596 present.swapchainCount = 1;
597 present.swapchains = & m_swap_chain;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600598 present.imageIndices = &m_current_buffer;
Tony Barbour96db8822015-02-25 12:28:39 -0700599
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600600#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800601 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700602 XCB_PROP_MODE_REPLACE,
603 m_window,
604 XCB_ATOM_WM_NAME,
605 XCB_ATOM_STRING,
606 8,
607 m_display_image->m_title.size(),
608 m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600609#endif
Jon Ashburn07daee72015-05-21 18:13:33 -0600610
Ian Elliott7e40db92015-08-21 15:09:33 -0600611 err = m_fpQueuePresentKHR(m_queue.handle(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700612 assert(!err);
613
614 m_queue.wait();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600615 m_current_buffer = (m_current_buffer + 1) % 2;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600616}
617
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600618#ifdef _WIN32
Tony-LunarG399dfca2015-05-19 14:08:26 -0600619# define PREVIOUSLY_DOWN 1<<29
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600620// MS-Windows event handling function:
621LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
622 UINT uMsg,
623 WPARAM wParam,
624 LPARAM lParam)
625{
626
627 switch(uMsg)
628 {
629 case WM_CLOSE:
630 PostQuitMessage(0);
631 break;
632
633 case WM_PAINT:
634 {
635 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
636 if (me) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600637 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600638 me->Display();
639 }
640 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600641 break;
642
643 case WM_KEYDOWN:
644 {
645 if (lParam & (PREVIOUSLY_DOWN)){
646 break;
647 }
648 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
649 // the window, we put the this pointer into the window's user data so we could get it back now
650 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
651 switch (wParam)
652 {
653 case VK_ESCAPE: me->m_quit = true;
654 break;
655
656 case VK_LEFT: // left arrow key
657 if (me->m_display_image == me->m_images.begin()) {
658 me->m_display_image = --me->m_images.end();
659 }
660 else {
661 --me->m_display_image;
662 }
663 break;
664
665 case VK_RIGHT: // right arrow key
666 ++me->m_display_image;
667 if (me->m_display_image == me->m_images.end()) {
668 me->m_display_image = me->m_images.begin();
669 }
670 break;
671
672 default:
673 break;
674 }
675 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
676 me->Display();
677 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600678 }
679 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
680}
681
682void TestFrameworkVkPresent::Run()
683{
684 MSG msg; // message
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600685
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600686 /* main message loop*/
Tony-LunarG399dfca2015-05-19 14:08:26 -0600687 while(! m_quit) {
688 GetMessage(&msg, m_window, 0, 0);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600689 if (msg.message == WM_QUIT) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600690 m_quit = true; //if found, quit app
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600691 } else {
692 /* Translate and dispatch to event queue*/
693 TranslateMessage(&msg);
694 DispatchMessage(&msg);
695 }
696 }
697}
698
699#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600700void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600701{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600702 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700703 switch (event_code) {
704 case XCB_EXPOSE:
705 Display(); // TODO: handle resize
706 break;
707 case XCB_CLIENT_MESSAGE:
708 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
709 (m_atom_wm_delete_window)->atom) {
710 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600711 }
712 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700713 case XCB_KEY_RELEASE:
714 {
715 const xcb_key_release_event_t *key =
716 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600717
Tony Barbour96db8822015-02-25 12:28:39 -0700718 switch (key->detail) {
719 case 0x9: // Escape
720 m_quit = true;
721 break;
722 case 0x71: // left arrow key
723 if (m_display_image == m_images.begin()) {
724 m_display_image = --m_images.end();
725 } else {
726 --m_display_image;
727 }
728 break;
729 case 0x72: // right arrow key
730 ++m_display_image;
731 if (m_display_image == m_images.end()) {
732 m_display_image = m_images.begin();
733 }
734 break;
735 case 0x41:
736 m_pause = !m_pause;
737 break;
738 }
739 Display();
740 }
741 break;
742 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600743 break;
744 }
Tony Barbour96db8822015-02-25 12:28:39 -0700745}
746
Tony Barbour6918cd52015-04-09 12:58:51 -0600747void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700748{
Chia-I Wuf8693382015-04-16 22:02:10 +0800749 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700750
751 while (! m_quit) {
752 xcb_generic_event_t *event;
753
754 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800755 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700756 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800757 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700758 }
759 if (event) {
760 HandleEvent(event);
761 free(event);
762 }
763 }
764}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600765#endif // _WIN32
Tony Barbour96db8822015-02-25 12:28:39 -0700766
Ian Elliott7e40db92015-08-21 15:09:33 -0600767void TestFrameworkVkPresent::CreateSwapchain()
Tony Barbour96db8822015-02-25 12:28:39 -0700768{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600769 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700770
Tony-LunarG399dfca2015-05-19 14:08:26 -0600771 m_display_image = m_images.begin();
772 m_current_buffer = 0;
773
Tony Barbour6a3faf02015-07-23 10:36:18 -0600774 // Construct the WSI surface description:
Ian Elliott7e40db92015-08-21 15:09:33 -0600775 m_surface_description.sType = VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600776 m_surface_description.pNext = NULL;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600777#ifdef _WIN32
Ian Elliott7e40db92015-08-21 15:09:33 -0600778 m_surface_description.platform = VK_PLATFORM_WIN32_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600779 m_surface_description.pPlatformHandle = m_connection;
780 m_surface_description.pPlatformWindow = m_window;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600781#else // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -0600782 m_platform_handle_xcb.connection = m_connection;
783 m_platform_handle_xcb.root = m_screen->root;
Ian Elliott7e40db92015-08-21 15:09:33 -0600784 m_surface_description.platform = VK_PLATFORM_XCB_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600785 m_surface_description.pPlatformHandle = &m_platform_handle_xcb;
786 m_surface_description.pPlatformWindow = &m_window;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600787#endif // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -0600788
789 // Iterate over each queue to learn whether it supports presenting to WSI:
790 VkBool32 supportsPresent;
791 m_present_queue_node_index = UINT32_MAX;
792 std::vector<vk_testing::Queue *> queues = m_device.graphics_queues();
793 for (int i=0; i < queues.size(); i++)
794 {
795 int family_index = queues[i]->get_family_index();
Ian Elliott7e40db92015-08-21 15:09:33 -0600796 m_fpGetPhysicalDeviceSurfaceSupportKHR(m_device.phy().handle(),
Tony Barbour6a3faf02015-07-23 10:36:18 -0600797 family_index,
Ian Elliott7e40db92015-08-21 15:09:33 -0600798 (VkSurfaceDescriptionKHR *) &m_surface_description,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600799 &supportsPresent);
800 if (supportsPresent) {
801 m_present_queue_node_index = family_index;
802 }
803 }
804
805 assert(m_present_queue_node_index != UINT32_MAX);
806
807
808 // Get the list of VkFormat's that are supported:
Ian Elliott8b139792015-08-07 11:51:12 -0600809 uint32_t formatCount;
Ian Elliott7e40db92015-08-21 15:09:33 -0600810 err = m_fpGetSurfaceFormatsKHR(m_device.handle(),
811 (VkSurfaceDescriptionKHR *) &m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600812 &formatCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600813 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600814 VkSurfaceFormatKHR *surfFormats =
815 (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
816 err = m_fpGetSurfaceFormatsKHR(m_device.handle(),
817 (VkSurfaceDescriptionKHR *) &m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600818 &formatCount, surfFormats);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600819 assert(!err);
820 // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
821 // the surface has no preferred format. Otherwise, at least one
822 // supported format will be returned.
Tony Barbour6a3faf02015-07-23 10:36:18 -0600823 if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED)
824 {
825 m_format = VK_FORMAT_B8G8R8A8_UNORM;
826 }
827 else
828 {
829 assert(formatCount >= 1);
830 m_format = surfFormats[0].format;
831 }
Ian Elliott8b139792015-08-07 11:51:12 -0600832 m_color_space = surfFormats[0].colorSpace;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600833
834 // Check the surface proprties and formats
Ian Elliott7e40db92015-08-21 15:09:33 -0600835 VkSurfacePropertiesKHR surfProperties;
836 err = m_fpGetSurfacePropertiesKHR(m_device.handle(),
837 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600838 &surfProperties);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600839 assert(!err);
840
Ian Elliott8b139792015-08-07 11:51:12 -0600841 uint32_t presentModeCount;
Ian Elliott7e40db92015-08-21 15:09:33 -0600842 err = m_fpGetSurfacePresentModesKHR(m_device.handle(),
843 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600844 &presentModeCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600845 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600846 VkPresentModeKHR *presentModes =
847 (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
Ian Elliott8b139792015-08-07 11:51:12 -0600848 assert(presentModes);
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, presentModes);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600852 assert(!err);
853
Ian Elliott7e40db92015-08-21 15:09:33 -0600854 VkExtent2D swapchainExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600855 // width and height are either both -1, or both not -1.
Ian Elliott8b139792015-08-07 11:51:12 -0600856 if (surfProperties.currentExtent.width == -1)
Tony Barbour6a3faf02015-07-23 10:36:18 -0600857 {
858 // If the surface size is undefined, the size is set to
859 // the size of the images requested.
Ian Elliott7e40db92015-08-21 15:09:33 -0600860 swapchainExtent.width = m_width;
861 swapchainExtent.height = m_height;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600862 }
863 else
864 {
865 // If the surface size is defined, the swap chain size must match
Ian Elliott7e40db92015-08-21 15:09:33 -0600866 swapchainExtent = surfProperties.currentExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600867 }
868
869 // If mailbox mode is available, use it, as is the lowest-latency non-
Ian Elliottae0e8242015-08-10 13:20:49 -0600870 // tearing mode. If not, try IMMEDIATE which will usually be available,
871 // and is fastest (though it tears). If not, fall back to FIFO which is
872 // always available.
Ian Elliott7e40db92015-08-21 15:09:33 -0600873 VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600874 for (size_t i = 0; i < presentModeCount; i++) {
Ian Elliott7e40db92015-08-21 15:09:33 -0600875 if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
876 swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600877 break;
878 }
Ian Elliott7e40db92015-08-21 15:09:33 -0600879 if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) &&
880 (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
881 swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
Ian Elliottae0e8242015-08-10 13:20:49 -0600882 }
Tony Barbour6a3faf02015-07-23 10:36:18 -0600883 }
884
885 // Determine the number of VkImage's to use in the swap chain (we desire to
886 // own only 1 image at a time, besides the images being displayed and
887 // queued for display):
Ian Elliott7e40db92015-08-21 15:09:33 -0600888 uint32_t desiredNumberOfSwapchainImages = surfProperties.minImageCount + 1;
Ian Elliott8b139792015-08-07 11:51:12 -0600889 if ((surfProperties.maxImageCount > 0) &&
Ian Elliott7e40db92015-08-21 15:09:33 -0600890 (desiredNumberOfSwapchainImages > surfProperties.maxImageCount))
Tony Barbour6a3faf02015-07-23 10:36:18 -0600891 {
892 // Application must settle for fewer images than desired:
Ian Elliott7e40db92015-08-21 15:09:33 -0600893 desiredNumberOfSwapchainImages = surfProperties.maxImageCount;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600894 }
895
Ian Elliott7e40db92015-08-21 15:09:33 -0600896 VkSurfaceTransformKHR preTransform;
897 if (surfProperties.supportedTransforms & VK_SURFACE_TRANSFORM_NONE_BIT_KHR) {
898 preTransform = VK_SURFACE_TRANSFORM_NONE_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600899 } else {
Ian Elliott8b139792015-08-07 11:51:12 -0600900 preTransform = surfProperties.currentTransform;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600901 }
Ian Elliott1a3845b2015-07-06 14:33:04 -0600902
Cody Northropdf5b0922015-08-28 16:22:48 -0600903 // We want to blit to the swap chain, ensure the driver supports it. Color is always supported, per WSI spec.
904 assert((surfProperties.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT) != 0);
905
Ian Elliott7e40db92015-08-21 15:09:33 -0600906 VkSwapchainCreateInfoKHR swap_chain = {};
Ian Elliotta257eea2015-09-22 10:20:23 -0600907 swap_chain.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600908 swap_chain.pNext = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600909 swap_chain.pSurfaceDescription = (const VkSurfaceDescriptionKHR *)&m_surface_description;
910 swap_chain.minImageCount = desiredNumberOfSwapchainImages;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600911 swap_chain.imageFormat = m_format;
Ian Elliott8b139792015-08-07 11:51:12 -0600912 swap_chain.imageColorSpace = m_color_space;
Ian Elliott7e40db92015-08-21 15:09:33 -0600913 swap_chain.imageExtent.width = swapchainExtent.width;
914 swap_chain.imageExtent.height = swapchainExtent.height;
Cody Northropdf8f42a2015-08-05 15:38:39 -0600915 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT |
916 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600917 swap_chain.preTransform = preTransform;
Chia-I Wuf8693382015-04-16 22:02:10 +0800918 swap_chain.imageArraySize = 1;
Ian Elliott8b139792015-08-07 11:51:12 -0600919 swap_chain.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
920 swap_chain.queueFamilyCount = 0;
921 swap_chain.pQueueFamilyIndices = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600922 swap_chain.presentMode = swapchainPresentMode;
923 swap_chain.oldSwapchain.handle = 0;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600924 swap_chain.clipped = true;
925
926 uint32_t i;
Chia-I Wuf8693382015-04-16 22:02:10 +0800927
Ian Elliott7e40db92015-08-21 15:09:33 -0600928 err = m_fpCreateSwapchainKHR(m_device.handle(), &swap_chain, &m_swap_chain);
Chia-I Wuf8693382015-04-16 22:02:10 +0800929 assert(!err);
930
Ian Elliott7e40db92015-08-21 15:09:33 -0600931 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
932 &m_swapchainImageCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600933 assert(!err);
934
Ian Elliott7e40db92015-08-21 15:09:33 -0600935 VkImage* swapchainImages = (VkImage*)malloc(m_swapchainImageCount * sizeof(VkImage));
936 assert(swapchainImages);
937 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
938 &m_swapchainImageCount, swapchainImages);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600939 assert(!err);
940
Ian Elliott7e40db92015-08-21 15:09:33 -0600941 m_buffers = (SwapchainBuffers*)malloc(sizeof(SwapchainBuffers)*m_swapchainImageCount);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600942 assert(m_buffers);
943
Ian Elliott7e40db92015-08-21 15:09:33 -0600944 for (i = 0; i < m_swapchainImageCount; i++) {
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600945 VkImageViewCreateInfo color_image_view = {};
946 color_image_view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
947 color_image_view.pNext = NULL;
Courtney Goeltzenleuchter00265c82015-09-11 15:22:06 -0600948 color_image_view.viewType = VK_IMAGE_VIEW_TYPE_2D;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600949 color_image_view.format = m_format;
Courtney Goeltzenleuchterba724512015-09-10 17:58:54 -0600950 color_image_view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600951 color_image_view.subresourceRange.baseMipLevel = 0;
952 color_image_view.subresourceRange.mipLevels = 1;
Courtney Goeltzenleuchter4a261892015-09-10 16:38:41 -0600953 color_image_view.subresourceRange.baseArrayLayer = 0;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600954 color_image_view.subresourceRange.arraySize = 1;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600955
Ian Elliott7e40db92015-08-21 15:09:33 -0600956 m_buffers[i].image = swapchainImages[i];
Tony Barbour6a3faf02015-07-23 10:36:18 -0600957
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600958 color_image_view.image = m_buffers[i].image;
959 err = vkCreateImageView(m_device.handle(),
960 &color_image_view, &m_buffers[i].view);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600961 assert(!err);
Tony Barbourbd094ce2015-10-23 11:00:15 -0600962
963 /* Set image layout to PRESENT_SOURCE_KHR so that before the copy, it can be set to */
964 /* TRANSFER_DESTINATION_OPTIMAL */
965 SetImageLayout(m_buffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT,
966 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SOURCE_KHR);
967
Tony Barbour6a3faf02015-07-23 10:36:18 -0600968 }
Tony Barbour96db8822015-02-25 12:28:39 -0700969}
Tony Barbourbd094ce2015-10-23 11:00:15 -0600970void TestFrameworkVkPresent::SetImageLayout(VkImage image, VkImageAspectFlags aspectMask,
971 VkImageLayout old_image_layout, VkImageLayout new_image_layout)
972{
973 VkResult U_ASSERT_ONLY err;
974
975 VkCmdBufferBeginInfo cmd_buf_info = {};
976 cmd_buf_info.sType = VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO;
977 cmd_buf_info.pNext = NULL;
978 cmd_buf_info.flags = VK_CMD_BUFFER_OPTIMIZE_SMALL_BATCH_BIT |
979 VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT;
980 cmd_buf_info.renderPass = { VK_NULL_HANDLE };
981 cmd_buf_info.subpass = 0;
982 cmd_buf_info.framebuffer = { VK_NULL_HANDLE };
983
984 err = vkBeginCommandBuffer(m_cmdbuf.handle(), &cmd_buf_info);
985 assert(!err);
986
987 VkImageMemoryBarrier image_memory_barrier = {};
988 image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
989 image_memory_barrier.pNext = NULL;
990 image_memory_barrier.outputMask = 0;
991 image_memory_barrier.inputMask = 0;
992 image_memory_barrier.oldLayout = old_image_layout;
993 image_memory_barrier.newLayout = new_image_layout;
994 image_memory_barrier.image = image;
995 image_memory_barrier.subresourceRange.aspectMask = aspectMask;
996 image_memory_barrier.subresourceRange.baseMipLevel = 0;
997 image_memory_barrier.subresourceRange.mipLevels = 1;
998 image_memory_barrier.subresourceRange.baseArrayLayer = 0;
999 image_memory_barrier.subresourceRange.arraySize = 1;
1000
1001 if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL) {
1002 /* Make sure anything that was copying from this image has completed */
1003 image_memory_barrier.inputMask = VK_MEMORY_INPUT_TRANSFER_BIT;
1004 }
1005
1006 if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
1007 /* Make sure any Copy or CPU writes to image are flushed */
1008 image_memory_barrier.outputMask = VK_MEMORY_OUTPUT_HOST_WRITE_BIT | VK_MEMORY_OUTPUT_TRANSFER_BIT;
1009 }
1010
1011 VkImageMemoryBarrier *pmemory_barrier = &image_memory_barrier;
1012
1013 VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1014 VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1015
1016 vkCmdPipelineBarrier(m_cmdbuf.handle(), src_stages, dest_stages, false, 1, (const void * const*)&pmemory_barrier);
1017
1018 err = vkEndCommandBuffer(m_cmdbuf.handle());
1019 assert(!err);
1020
1021 const VkCmdBuffer cmd_bufs[] = { m_cmdbuf.handle() };
1022 VkFence nullFence = { VK_NULL_HANDLE };
1023
1024 err = vkQueueSubmit(m_queue.handle(), 1, cmd_bufs, nullFence);
1025 assert(!err);
1026
1027 err = vkQueueWaitIdle(m_queue.handle());
1028 assert(!err);
1029
1030}
Tony Barbour96db8822015-02-25 12:28:39 -07001031
Jon Ashburn07daee72015-05-21 18:13:33 -06001032void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -07001033{
Ian Elliott7e40db92015-08-21 15:09:33 -06001034 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceSupportKHR);
1035 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfacePropertiesKHR);
1036 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfaceFormatsKHR);
1037 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfacePresentModesKHR);
1038 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1039 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1040 GET_DEVICE_PROC_ADDR(m_device.handle(), DestroySwapchainKHR);
1041 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSwapchainImagesKHR);
1042 GET_DEVICE_PROC_ADDR(m_device.handle(), AcquireNextImageKHR);
1043 GET_DEVICE_PROC_ADDR(m_device.handle(), QueuePresentKHR);
Jon Ashburn07daee72015-05-21 18:13:33 -06001044
Tony Barbour96db8822015-02-25 12:28:39 -07001045 m_images = imagesIn;
1046}
1047
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001048#ifdef _WIN32
1049void TestFrameworkVkPresent::CreateMyWindow()
1050{
1051 WNDCLASSEX win_class;
1052 // const ::testing::TestInfo* const test_info =
1053 // ::testing::UnitTest::GetInstance()->current_test_info();
1054 m_connection = GetModuleHandle(NULL);
1055
1056 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1057 it != m_images.end(); it++) {
1058 if (m_width < it->m_width)
1059 m_width = it->m_width;
1060 if (m_height < it->m_height)
1061 m_height = it->m_height;
1062 }
1063 // Initialize the window class structure:
1064 win_class.cbSize = sizeof(WNDCLASSEX);
1065 win_class.style = CS_HREDRAW | CS_VREDRAW;
1066 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
1067 win_class.cbClsExtra = 0;
1068 win_class.cbWndExtra = 0;
1069 win_class.hInstance = m_connection; // hInstance
1070 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
1071 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
1072 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
1073 win_class.lpszMenuName = NULL;
1074 win_class.lpszClassName = "Test";
1075 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
1076 // Register window class:
1077 if (!RegisterClassEx(&win_class)) {
1078 // It didn't work, so try to give a useful error:
1079 printf("Unexpected error trying to start the application!\n");
1080 fflush(stdout);
1081 exit(1);
1082 }
1083 // Create window with the registered class:
Cody Northrop39582252015-08-05 15:39:31 -06001084 RECT wr = { 0, 0, m_width, m_height };
1085 AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001086 m_window = CreateWindowEx(0,
1087 "Test", // class name
1088 "Test", // app name
1089 WS_OVERLAPPEDWINDOW | // window style
1090 WS_VISIBLE |
1091 WS_SYSMENU,
1092 100,100, // x/y coords
Cody Northrop39582252015-08-05 15:39:31 -06001093 wr.right - wr.left, // width
1094 wr.bottom - wr.top, // height
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001095 NULL, // handle to parent
1096 NULL, // handle to menu
1097 m_connection, // hInstance
1098 NULL); // no extra parameters
1099
1100 if (!m_window) {
1101 // It didn't work, so try to give a useful error:
1102 DWORD error = GetLastError();
1103 char message[120];
1104 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
1105 MessageBox(NULL, message, "Error", MB_OK);
1106 exit(1);
1107 }
Tony-LunarG399dfca2015-05-19 14:08:26 -06001108 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
1109 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001110}
1111#else
Tony Barbour6918cd52015-04-09 12:58:51 -06001112void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -07001113{
Chia-I Wuf8693382015-04-16 22:02:10 +08001114 const xcb_setup_t *setup;
1115 xcb_screen_iterator_t iter;
1116 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -07001117 uint32_t value_mask, value_list[32];
1118
Chia-I Wuf8693382015-04-16 22:02:10 +08001119 m_connection = xcb_connect(NULL, &scr);
1120
1121 setup = xcb_get_setup(m_connection);
1122 iter = xcb_setup_roots_iterator(setup);
1123 while (scr-- > 0)
1124 xcb_screen_next(&iter);
1125
1126 m_screen = iter.data;
1127
1128 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1129 it != m_images.end(); it++) {
1130 if (m_width < it->m_width)
1131 m_width = it->m_width;
1132 if (m_height < it->m_height)
1133 m_height = it->m_height;
1134 }
1135
1136 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -07001137
1138 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +08001139 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -07001140 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
1141 XCB_EVENT_MASK_EXPOSURE |
1142 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
1143
Chia-I Wuf8693382015-04-16 22:02:10 +08001144 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -07001145 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001146 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -07001147 0, 0, m_width, m_height, 0,
1148 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001149 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -07001150 value_mask, value_list);
1151
1152 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +08001153 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -07001154 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +08001155 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001156
Chia-I Wuf8693382015-04-16 22:02:10 +08001157 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
1158 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001159
Chia-I Wuf8693382015-04-16 22:02:10 +08001160 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -07001161 m_window, (*reply).atom, 4, 32, 1,
1162 &(*m_atom_wm_delete_window).atom);
1163 free(reply);
1164
Chia-I Wuf8693382015-04-16 22:02:10 +08001165 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -07001166}
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001167#endif
Tony Barbour96db8822015-02-25 12:28:39 -07001168
Tony Barbour6918cd52015-04-09 12:58:51 -06001169void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -07001170{
Ian Elliott7e40db92015-08-21 15:09:33 -06001171 m_fpDestroySwapchainKHR(m_device.handle(), m_swap_chain);
Tony Barbour9226a822015-10-23 10:58:56 -06001172
1173 for (uint32_t i = 0; i < m_swapchainImageCount; i++) {
1174 vkDestroyImageView(m_device.handle(), m_buffers[i].view);
1175 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001176#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +08001177 xcb_destroy_window(m_connection, m_window);
1178 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001179#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001180}
1181
Tony Barbour6918cd52015-04-09 12:58:51 -06001182void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001183{
1184 if (m_images.size() == 0) return;
1185
Chia-I Wuf8693382015-04-16 22:02:10 +08001186 vk_testing::Environment env;
1187 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -07001188 {
Chia-I Wuf8693382015-04-16 22:02:10 +08001189 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -07001190
Jon Ashburn07daee72015-05-21 18:13:33 -06001191 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001192 vkPresent.CreateMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -06001193 vkPresent.CreateSwapchain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001194 vkPresent.Run();
1195 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -07001196 }
Chia-I Wuf8693382015-04-16 22:02:10 +08001197 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001198}
1199
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001200//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001201// These are the default resources for TBuiltInResources, used for both
1202// - parsing this string for the case where the user didn't supply one
1203// - dumping out a template for user construction of a config file
1204//
1205static const char* DefaultConfig =
1206 "MaxLights 32\n"
1207 "MaxClipPlanes 6\n"
1208 "MaxTextureUnits 32\n"
1209 "MaxTextureCoords 32\n"
1210 "MaxVertexAttribs 64\n"
1211 "MaxVertexUniformComponents 4096\n"
1212 "MaxVaryingFloats 64\n"
1213 "MaxVertexTextureImageUnits 32\n"
1214 "MaxCombinedTextureImageUnits 80\n"
1215 "MaxTextureImageUnits 32\n"
1216 "MaxFragmentUniformComponents 4096\n"
1217 "MaxDrawBuffers 32\n"
1218 "MaxVertexUniformVectors 128\n"
1219 "MaxVaryingVectors 8\n"
1220 "MaxFragmentUniformVectors 16\n"
1221 "MaxVertexOutputVectors 16\n"
1222 "MaxFragmentInputVectors 15\n"
1223 "MinProgramTexelOffset -8\n"
1224 "MaxProgramTexelOffset 7\n"
1225 "MaxClipDistances 8\n"
1226 "MaxComputeWorkGroupCountX 65535\n"
1227 "MaxComputeWorkGroupCountY 65535\n"
1228 "MaxComputeWorkGroupCountZ 65535\n"
1229 "MaxComputeWorkGroupSizeX 1024\n"
1230 "MaxComputeWorkGroupSizeY 1024\n"
1231 "MaxComputeWorkGroupSizeZ 64\n"
1232 "MaxComputeUniformComponents 1024\n"
1233 "MaxComputeTextureImageUnits 16\n"
1234 "MaxComputeImageUniforms 8\n"
1235 "MaxComputeAtomicCounters 8\n"
1236 "MaxComputeAtomicCounterBuffers 1\n"
1237 "MaxVaryingComponents 60\n"
1238 "MaxVertexOutputComponents 64\n"
1239 "MaxGeometryInputComponents 64\n"
1240 "MaxGeometryOutputComponents 128\n"
1241 "MaxFragmentInputComponents 128\n"
1242 "MaxImageUnits 8\n"
1243 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
1244 "MaxCombinedShaderOutputResources 8\n"
1245 "MaxImageSamples 0\n"
1246 "MaxVertexImageUniforms 0\n"
1247 "MaxTessControlImageUniforms 0\n"
1248 "MaxTessEvaluationImageUniforms 0\n"
1249 "MaxGeometryImageUniforms 0\n"
1250 "MaxFragmentImageUniforms 8\n"
1251 "MaxCombinedImageUniforms 8\n"
1252 "MaxGeometryTextureImageUnits 16\n"
1253 "MaxGeometryOutputVertices 256\n"
1254 "MaxGeometryTotalOutputComponents 1024\n"
1255 "MaxGeometryUniformComponents 1024\n"
1256 "MaxGeometryVaryingComponents 64\n"
1257 "MaxTessControlInputComponents 128\n"
1258 "MaxTessControlOutputComponents 128\n"
1259 "MaxTessControlTextureImageUnits 16\n"
1260 "MaxTessControlUniformComponents 1024\n"
1261 "MaxTessControlTotalOutputComponents 4096\n"
1262 "MaxTessEvaluationInputComponents 128\n"
1263 "MaxTessEvaluationOutputComponents 128\n"
1264 "MaxTessEvaluationTextureImageUnits 16\n"
1265 "MaxTessEvaluationUniformComponents 1024\n"
1266 "MaxTessPatchComponents 120\n"
1267 "MaxPatchVertices 32\n"
1268 "MaxTessGenLevel 64\n"
1269 "MaxViewports 16\n"
1270 "MaxVertexAtomicCounters 0\n"
1271 "MaxTessControlAtomicCounters 0\n"
1272 "MaxTessEvaluationAtomicCounters 0\n"
1273 "MaxGeometryAtomicCounters 0\n"
1274 "MaxFragmentAtomicCounters 8\n"
1275 "MaxCombinedAtomicCounters 8\n"
1276 "MaxAtomicCounterBindings 1\n"
1277 "MaxVertexAtomicCounterBuffers 0\n"
1278 "MaxTessControlAtomicCounterBuffers 0\n"
1279 "MaxTessEvaluationAtomicCounterBuffers 0\n"
1280 "MaxGeometryAtomicCounterBuffers 0\n"
1281 "MaxFragmentAtomicCounterBuffers 1\n"
1282 "MaxCombinedAtomicCounterBuffers 1\n"
1283 "MaxAtomicCounterBufferSize 16384\n"
1284 "MaxTransformFeedbackBuffers 4\n"
1285 "MaxTransformFeedbackInterleavedComponents 64\n"
1286 "MaxCullDistances 8\n"
1287 "MaxCombinedClipAndCullDistances 8\n"
1288 "MaxSamples 4\n"
1289
1290 "nonInductiveForLoops 1\n"
1291 "whileLoops 1\n"
1292 "doWhileLoops 1\n"
1293 "generalUniformIndexing 1\n"
1294 "generalAttributeMatrixVectorIndexing 1\n"
1295 "generalVaryingIndexing 1\n"
1296 "generalSamplerIndexing 1\n"
1297 "generalVariableIndexing 1\n"
1298 "generalConstantMatrixVectorIndexing 1\n"
1299 ;
1300
1301//
1302// *.conf => this is a config file that can set limits/resources
1303//
Tony Barbour6918cd52015-04-09 12:58:51 -06001304bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001305{
1306 if (name.size() < 5)
1307 return false;
1308
1309 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
1310 ConfigFile = name;
1311 return true;
1312 }
1313
1314 return false;
1315}
1316
1317//
1318// Parse either a .conf file provided by the user or the default string above.
1319//
Tony Barbour6918cd52015-04-09 12:58:51 -06001320void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001321{
1322 char** configStrings = 0;
1323 char* config = 0;
1324 if (ConfigFile.size() > 0) {
1325 configStrings = ReadFileData(ConfigFile.c_str());
1326 if (configStrings)
1327 config = *configStrings;
1328 else {
1329 printf("Error opening configuration file; will instead use the default configuration\n");
1330 }
1331 }
1332
1333 if (config == 0) {
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001334 config = (char *) alloca(strlen(DefaultConfig) + 1);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001335 strcpy(config, DefaultConfig);
1336 }
1337
1338 const char* delims = " \t\n\r";
1339 const char* token = strtok(config, delims);
1340 while (token) {
1341 const char* valueStr = strtok(0, delims);
1342 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1343 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1344 return;
1345 }
1346 int value = atoi(valueStr);
1347
1348 if (strcmp(token, "MaxLights") == 0)
1349 Resources.maxLights = value;
1350 else if (strcmp(token, "MaxClipPlanes") == 0)
1351 Resources.maxClipPlanes = value;
1352 else if (strcmp(token, "MaxTextureUnits") == 0)
1353 Resources.maxTextureUnits = value;
1354 else if (strcmp(token, "MaxTextureCoords") == 0)
1355 Resources.maxTextureCoords = value;
1356 else if (strcmp(token, "MaxVertexAttribs") == 0)
1357 Resources.maxVertexAttribs = value;
1358 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1359 Resources.maxVertexUniformComponents = value;
1360 else if (strcmp(token, "MaxVaryingFloats") == 0)
1361 Resources.maxVaryingFloats = value;
1362 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1363 Resources.maxVertexTextureImageUnits = value;
1364 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1365 Resources.maxCombinedTextureImageUnits = value;
1366 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1367 Resources.maxTextureImageUnits = value;
1368 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1369 Resources.maxFragmentUniformComponents = value;
1370 else if (strcmp(token, "MaxDrawBuffers") == 0)
1371 Resources.maxDrawBuffers = value;
1372 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1373 Resources.maxVertexUniformVectors = value;
1374 else if (strcmp(token, "MaxVaryingVectors") == 0)
1375 Resources.maxVaryingVectors = value;
1376 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1377 Resources.maxFragmentUniformVectors = value;
1378 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1379 Resources.maxVertexOutputVectors = value;
1380 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1381 Resources.maxFragmentInputVectors = value;
1382 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1383 Resources.minProgramTexelOffset = value;
1384 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1385 Resources.maxProgramTexelOffset = value;
1386 else if (strcmp(token, "MaxClipDistances") == 0)
1387 Resources.maxClipDistances = value;
1388 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1389 Resources.maxComputeWorkGroupCountX = value;
1390 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1391 Resources.maxComputeWorkGroupCountY = value;
1392 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1393 Resources.maxComputeWorkGroupCountZ = value;
1394 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1395 Resources.maxComputeWorkGroupSizeX = value;
1396 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1397 Resources.maxComputeWorkGroupSizeY = value;
1398 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1399 Resources.maxComputeWorkGroupSizeZ = value;
1400 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1401 Resources.maxComputeUniformComponents = value;
1402 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1403 Resources.maxComputeTextureImageUnits = value;
1404 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1405 Resources.maxComputeImageUniforms = value;
1406 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1407 Resources.maxComputeAtomicCounters = value;
1408 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1409 Resources.maxComputeAtomicCounterBuffers = value;
1410 else if (strcmp(token, "MaxVaryingComponents") == 0)
1411 Resources.maxVaryingComponents = value;
1412 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1413 Resources.maxVertexOutputComponents = value;
1414 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1415 Resources.maxGeometryInputComponents = value;
1416 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1417 Resources.maxGeometryOutputComponents = value;
1418 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1419 Resources.maxFragmentInputComponents = value;
1420 else if (strcmp(token, "MaxImageUnits") == 0)
1421 Resources.maxImageUnits = value;
1422 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1423 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1424 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1425 Resources.maxCombinedShaderOutputResources = value;
1426 else if (strcmp(token, "MaxImageSamples") == 0)
1427 Resources.maxImageSamples = value;
1428 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1429 Resources.maxVertexImageUniforms = value;
1430 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1431 Resources.maxTessControlImageUniforms = value;
1432 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1433 Resources.maxTessEvaluationImageUniforms = value;
1434 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1435 Resources.maxGeometryImageUniforms = value;
1436 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1437 Resources.maxFragmentImageUniforms = value;
1438 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1439 Resources.maxCombinedImageUniforms = value;
1440 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1441 Resources.maxGeometryTextureImageUnits = value;
1442 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1443 Resources.maxGeometryOutputVertices = value;
1444 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1445 Resources.maxGeometryTotalOutputComponents = value;
1446 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1447 Resources.maxGeometryUniformComponents = value;
1448 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1449 Resources.maxGeometryVaryingComponents = value;
1450 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1451 Resources.maxTessControlInputComponents = value;
1452 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1453 Resources.maxTessControlOutputComponents = value;
1454 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1455 Resources.maxTessControlTextureImageUnits = value;
1456 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1457 Resources.maxTessControlUniformComponents = value;
1458 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1459 Resources.maxTessControlTotalOutputComponents = value;
1460 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1461 Resources.maxTessEvaluationInputComponents = value;
1462 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1463 Resources.maxTessEvaluationOutputComponents = value;
1464 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1465 Resources.maxTessEvaluationTextureImageUnits = value;
1466 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1467 Resources.maxTessEvaluationUniformComponents = value;
1468 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1469 Resources.maxTessPatchComponents = value;
1470 else if (strcmp(token, "MaxPatchVertices") == 0)
1471 Resources.maxPatchVertices = value;
1472 else if (strcmp(token, "MaxTessGenLevel") == 0)
1473 Resources.maxTessGenLevel = value;
1474 else if (strcmp(token, "MaxViewports") == 0)
1475 Resources.maxViewports = value;
1476 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1477 Resources.maxVertexAtomicCounters = value;
1478 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1479 Resources.maxTessControlAtomicCounters = value;
1480 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1481 Resources.maxTessEvaluationAtomicCounters = value;
1482 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1483 Resources.maxGeometryAtomicCounters = value;
1484 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1485 Resources.maxFragmentAtomicCounters = value;
1486 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1487 Resources.maxCombinedAtomicCounters = value;
1488 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1489 Resources.maxAtomicCounterBindings = value;
1490 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1491 Resources.maxVertexAtomicCounterBuffers = value;
1492 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1493 Resources.maxTessControlAtomicCounterBuffers = value;
1494 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1495 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1496 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1497 Resources.maxGeometryAtomicCounterBuffers = value;
1498 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1499 Resources.maxFragmentAtomicCounterBuffers = value;
1500 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1501 Resources.maxCombinedAtomicCounterBuffers = value;
1502 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1503 Resources.maxAtomicCounterBufferSize = value;
1504 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1505 Resources.maxTransformFeedbackBuffers = value;
1506 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1507 Resources.maxTransformFeedbackInterleavedComponents = value;
1508 else if (strcmp(token, "MaxCullDistances") == 0)
1509 Resources.maxCullDistances = value;
1510 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1511 Resources.maxCombinedClipAndCullDistances = value;
1512 else if (strcmp(token, "MaxSamples") == 0)
1513 Resources.maxSamples = value;
1514
1515 else if (strcmp(token, "nonInductiveForLoops") == 0)
1516 Resources.limits.nonInductiveForLoops = (value != 0);
1517 else if (strcmp(token, "whileLoops") == 0)
1518 Resources.limits.whileLoops = (value != 0);
1519 else if (strcmp(token, "doWhileLoops") == 0)
1520 Resources.limits.doWhileLoops = (value != 0);
1521 else if (strcmp(token, "generalUniformIndexing") == 0)
1522 Resources.limits.generalUniformIndexing = (value != 0);
1523 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1524 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1525 else if (strcmp(token, "generalVaryingIndexing") == 0)
1526 Resources.limits.generalVaryingIndexing = (value != 0);
1527 else if (strcmp(token, "generalSamplerIndexing") == 0)
1528 Resources.limits.generalSamplerIndexing = (value != 0);
1529 else if (strcmp(token, "generalVariableIndexing") == 0)
1530 Resources.limits.generalVariableIndexing = (value != 0);
1531 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1532 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1533 else
1534 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1535
1536 token = strtok(0, delims);
1537 }
1538 if (configStrings)
1539 FreeFileData(configStrings);
1540}
1541
Tony Barbour6918cd52015-04-09 12:58:51 -06001542void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001543{
1544 if (m_compile_options & EOptionRelaxedErrors)
1545 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1546 if (m_compile_options & EOptionIntermediate)
1547 messages = (EShMessages)(messages | EShMsgAST);
1548 if (m_compile_options & EOptionSuppressWarnings)
1549 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1550}
1551
1552//
1553// Malloc a string of sufficient size and read a string into it.
1554//
Tony Barbour6918cd52015-04-09 12:58:51 -06001555char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001556{
1557 FILE *in;
1558 #if defined(_WIN32) && defined(__GNUC__)
1559 in = fopen(fileName, "r");
1560 int errorCode = in ? 0 : 1;
1561 #else
1562 int errorCode = fopen_s(&in, fileName, "r");
1563 #endif
1564
1565 char *fdata;
1566 int count = 0;
1567 const int maxSourceStrings = 5;
1568 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1569
1570 if (errorCode) {
1571 printf("Error: unable to open input file: %s\n", fileName);
1572 return 0;
1573 }
1574
1575 while (fgetc(in) != EOF)
1576 count++;
1577
1578 fseek(in, 0, SEEK_SET);
1579
1580 if (!(fdata = (char*)malloc(count+2))) {
1581 printf("Error allocating memory\n");
1582 return 0;
1583 }
1584 if (fread(fdata,1,count, in)!=count) {
1585 printf("Error reading input file: %s\n", fileName);
1586 return 0;
1587 }
1588 fdata[count] = '\0';
1589 fclose(in);
1590 if (count == 0) {
1591 return_data[0]=(char*)malloc(count+2);
1592 return_data[0][0]='\0';
1593 m_num_shader_strings = 0;
1594 return return_data;
1595 } else
1596 m_num_shader_strings = 1;
1597
1598 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1599 int ptr_len=0,i=0;
1600 while(count>0){
1601 return_data[i]=(char*)malloc(len+2);
1602 memcpy(return_data[i],fdata+ptr_len,len);
1603 return_data[i][len]='\0';
1604 count-=(len);
1605 ptr_len+=(len);
1606 if(count<len){
1607 if(count==0){
1608 m_num_shader_strings=(i+1);
1609 break;
1610 }
1611 len = count;
1612 }
1613 ++i;
1614 }
1615 return return_data;
1616}
1617
Tony Barbour6918cd52015-04-09 12:58:51 -06001618void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001619{
1620 for(int i=0;i<m_num_shader_strings;i++)
1621 free(data[i]);
1622}
1623
1624//
1625// Deduce the language from the filename. Files must end in one of the
1626// following extensions:
1627//
1628// .vert = vertex
1629// .tesc = tessellation control
1630// .tese = tessellation evaluation
1631// .geom = geometry
1632// .frag = fragment
1633// .comp = compute
1634//
Tony Barbour6918cd52015-04-09 12:58:51 -06001635EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001636{
1637 size_t ext = name.rfind('.');
1638 if (ext == std::string::npos) {
1639 return EShLangVertex;
1640 }
1641
1642 std::string suffix = name.substr(ext + 1, std::string::npos);
1643 if (suffix == "vert")
1644 return EShLangVertex;
1645 else if (suffix == "tesc")
1646 return EShLangTessControl;
1647 else if (suffix == "tese")
1648 return EShLangTessEvaluation;
1649 else if (suffix == "geom")
1650 return EShLangGeometry;
1651 else if (suffix == "frag")
1652 return EShLangFragment;
1653 else if (suffix == "comp")
1654 return EShLangCompute;
1655
1656 return EShLangVertex;
1657}
1658
1659//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001660// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001661//
Tony Barbourd1c35722015-04-16 15:59:00 -06001662EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001663{
1664 switch (shader_type) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001665 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001666 return EShLangVertex;
1667
Courtney Goeltzenleuchter96835892015-10-15 17:35:38 -06001668 case VK_SHADER_STAGE_TESSELLATION_CONTROL:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001669 return EShLangTessControl;
1670
Courtney Goeltzenleuchter96835892015-10-15 17:35:38 -06001671 case VK_SHADER_STAGE_TESSELLATION_EVALUATION:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001672 return EShLangTessEvaluation;
1673
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001674 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001675 return EShLangGeometry;
1676
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001677 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001678 return EShLangFragment;
1679
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001680 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001681 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001682
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001683 default:
1684 return EShLangVertex;
1685 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001686}
1687
1688
1689//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001690// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001691// Return value of false means an error was encountered.
1692//
Tony Barbourd1c35722015-04-16 15:59:00 -06001693bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001694 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001695 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001696{
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001697 glslang::TProgram program;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001698 const char *shaderStrings[1];
1699
1700 // TODO: Do we want to load a special config file depending on the
1701 // shader source? Optional name maybe?
1702 // SetConfigFile(fileName);
1703
1704 ProcessConfigFile();
1705
1706 EShMessages messages = EShMsgDefault;
1707 SetMessageOptions(messages);
1708
1709 EShLanguage stage = FindLanguage(shader_type);
1710 glslang::TShader* shader = new glslang::TShader(stage);
1711
1712 shaderStrings[0] = pshader;
1713 shader->setStrings(shaderStrings, 1);
1714
1715 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1716
Cody Northrop195d6622014-11-03 12:54:37 -07001717 if (! (m_compile_options & EOptionSuppressInfolog)) {
1718 puts(shader->getInfoLog());
1719 puts(shader->getInfoDebugLog());
1720 }
1721
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001722 return false; // something didn't work
1723 }
1724
1725 program.addShader(shader);
1726
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001727
1728 //
1729 // Program-level processing...
1730 //
1731
Cody Northrop195d6622014-11-03 12:54:37 -07001732 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001733
Cody Northrop195d6622014-11-03 12:54:37 -07001734 if (! (m_compile_options & EOptionSuppressInfolog)) {
1735 puts(shader->getInfoLog());
1736 puts(shader->getInfoDebugLog());
1737 }
1738
1739 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001740 }
1741
1742 if (m_compile_options & EOptionDumpReflection) {
1743 program.buildReflection();
1744 program.dumpReflection();
1745 }
1746
Cody Northrop5a95b472015-06-03 13:01:54 -06001747 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1748
1749 //
1750 // Test the different modes of SPIR-V modification
1751 //
1752 if (this->m_canonicalize_spv) {
1753 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1754 }
1755
1756 if (this->m_strip_spv) {
1757 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1758 }
1759
1760 if (this->m_do_everything_spv) {
1761 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1762 }
1763
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001764 delete shader;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001765
1766 return true;
1767}
1768
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001769
1770
Tony Barbour6918cd52015-04-09 12:58:51 -06001771VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001772 m_width( 0 ),
1773 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001774 m_data( NULL ),
1775 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001776{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001777}
1778
Tony Barbour6918cd52015-04-09 12:58:51 -06001779VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001780{
1781
1782}
1783
Tony Barbour6918cd52015-04-09 12:58:51 -06001784VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001785{
1786 m_title = copyin.m_title;
1787 m_width = copyin.m_width;
1788 m_height = copyin.m_height;
1789 m_data_size = copyin.m_data_size;
1790 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1791}
1792
Tony Barbour6918cd52015-04-09 12:58:51 -06001793ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001794{
Tony Barbour6918cd52015-04-09 12:58:51 -06001795 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1796 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001797 return output;
1798}
1799
Tony Barbour6918cd52015-04-09 12:58:51 -06001800VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001801{
1802 m_title = rhs.m_title;
1803 m_width = rhs.m_width;
1804 m_height = rhs.m_height;
1805 m_data_size = rhs.m_data_size;
1806 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001807 return *this;
1808}
1809
Tony Barbour6918cd52015-04-09 12:58:51 -06001810int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001811{
1812 if( this->m_data != rhs.m_data) return 0;
1813 return 1;
1814}
1815
1816// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001817int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001818{
1819 if( this->m_data_size < rhs.m_data_size ) return 1;
1820 return 0;
1821}
1822