blob: c07d48f38f8038639c3fbf790056783742eea627 [file] [log] [blame]
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001// VK tests
Courtney Goeltzenleuchterd0d7ccc2014-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 Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060023#include "vktestframework.h"
24#include "vkrenderframework.h"
Cody Northropeb9130e2015-06-03 13:01:54 -060025#include "SPIRV/GlslangToSpv.h"
26#include "SPIRV/SPVRemapper.h"
Tony Barbour772c5ef2014-12-10 17:00:20 -070027#include <limits.h>
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -060028#include <math.h>
Chia-I Wu3d9ebb22014-12-02 11:54:24 +080029#include <wand/MagickWand.h>
Tony Barboura26fb7d2015-09-21 15:17:33 -060030#ifndef _WIN32
Chia-I Wu5b66aa52015-04-16 22:02:10 +080031#include <xcb/xcb.h>
Tony Barboura26fb7d2015-09-21 15:17:33 -060032#endif
Ian Elliott338dedb2015-08-21 15:09:33 -060033#include "vk_ext_khr_swapchain.h"
34#include "vk_ext_khr_device_swapchain.h"
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -060035
Tony Barbour25e3b832015-05-20 16:53:31 -060036#if defined(PATH_MAX) && !defined(MAX_PATH)
37#define MAX_PATH PATH_MAX
38#endif
39
Tony Barbourb3744222015-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 Goeltzenleuchter94192032014-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 Northropacfb0492015-03-17 15:55:58 -060088 EOptionSpv = 0x800,
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -060089 EOptionDefaultDesktop = 0x1000,
90};
91
Ian Elliott338dedb2015-08-21 15:09:33 -060092typedef struct _SwapchainBuffers {
Tony Barbourb3744222015-07-23 10:36:18 -060093 VkImage image;
94 VkCmdBuffer cmd;
Courtney Goeltzenleuchter1856d6f2015-09-01 17:30:39 -060095 VkImageView view;
Ian Elliott338dedb2015-08-21 15:09:33 -060096} SwapchainBuffers;
Tony Barbourb3744222015-07-23 10:36:18 -060097
Chia-I Wu5b66aa52015-04-16 22:02:10 +080098class TestFrameworkVkPresent
99{
100public:
101 TestFrameworkVkPresent(vk_testing::Device &device);
102
103 void Run();
Jon Ashburncedc15f2015-05-21 18:13:33 -0600104 void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800105 void CreateMyWindow();
Ian Elliott338dedb2015-08-21 15:09:33 -0600106 void CreateSwapchain();
Tony Barbour24366562015-10-23 11:00:15 -0600107 void SetImageLayout(VkImage image, VkImageAspectFlags aspectMask,
108 VkImageLayout old_image_layout, VkImageLayout new_image_layout);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800109 void TearDown();
Tony Barbour25e3b832015-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 Wu5b66aa52015-04-16 22:02:10 +0800114
115protected:
116 vk_testing::Device &m_device;
117 vk_testing::Queue &m_queue;
Dana Jansens6e2dda12015-07-30 13:04:16 -0700118 vk_testing::CmdPool m_cmdpool;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800119 vk_testing::CmdBuffer m_cmdbuf;
120
121private:
Tony Barbour25e3b832015-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 Wu5b66aa52015-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 Elliott338dedb2015-08-21 15:09:33 -0600131 VkPlatformHandleXcbKHR m_platform_handle_xcb;
Tony Barbour25e3b832015-05-20 16:53:31 -0600132#endif
Courtney Goeltzenleuchterec69b9c2015-04-22 10:09:35 -0600133 std::list<VkTestImageRecord> m_images;
Tony Barbourb3744222015-07-23 10:36:18 -0600134 uint32_t m_present_queue_node_index;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800135
Ian Elliott338dedb2015-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 Barbourb3744222015-07-23 10:36:18 -0600149 VkFormat m_format;
Ian Elliott338dedb2015-08-21 15:09:33 -0600150 VkColorSpaceKHR m_color_space;
Tony Barbourb3744222015-07-23 10:36:18 -0600151
152 uint32_t m_current_buffer;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800153
154 bool m_quit;
155 bool m_pause;
156
Tony Barbour8bef8ee2015-05-22 09:44:58 -0600157 int m_width;
158 int m_height;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800159
160 std::list<VkTestImageRecord>::iterator m_display_image;
161
162 void Display();
Tony Barboura26fb7d2015-09-21 15:17:33 -0600163#ifndef _WIN32
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800164 void HandleEvent(xcb_generic_event_t *event);
Tony Barboura26fb7d2015-09-21 15:17:33 -0600165#endif
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800166};
167
Courtney Goeltzenleuchter94192032014-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600196
Tony Barbour25e3b832015-05-20 16:53:31 -0600197
198
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600199// Set up environment for GLSL compiler
200// Must be done once per process
201void TestEnvironment::SetUp()
202{
Cody Northropacfb0492015-03-17 15:55:58 -0600203 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600204 glslang::InitializeProcess();
Chia-I Wu1c9869e2014-12-28 14:27:28 +0800205
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600206 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600207}
208
209void TestEnvironment::TearDown()
210{
211 glslang::FinalizeProcess();
212}
213
Tony Barbour01999182015-04-09 12:58:51 -0600214VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600215 m_compile_options( 0 ),
216 m_num_shader_strings( 0 )
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600217{
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600218
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600219}
220
Tony Barbour01999182015-04-09 12:58:51 -0600221VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600222{
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600223
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600224}
225
226// Define all the static elements
Cody Northropa392a292015-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 Northropeb9130e2015-06-03 13:01:54 -0600233bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour01999182015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600238int m_display_image_idx = 0;
239
Cody Northrop1cfbd172015-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 Barbour01999182015-04-09 12:58:51 -0600248void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600249{
250 int i, n;
251
Cody Northrop1cfbd172015-06-03 16:49:20 -0600252 for (i=1, n=1; i< *argc; i++) {
253 if (optionMatch("--show-images", argv[i]))
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600254 m_show_images = true;
Cody Northrop1cfbd172015-06-03 16:49:20 -0600255 else if (optionMatch("--save-images", argv[i]))
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600256 m_save_images = true;
Cody Northrop1cfbd172015-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 Barbour32f368c2014-10-30 14:29:04 -0600264 m_compare_images = true;
Tony Barbour32f368c2014-10-30 14:29:04 -0600265
Cody Northrop1cfbd172015-06-03 16:49:20 -0600266 else if (optionMatch("--help", argv[i]) ||
267 optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchterb7f26e02014-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 Barbour0e4235d2014-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 Goeltzenleuchterb7f26e02014-12-02 13:13:10 -0700280 "\t\tSignal test failure if different.\n");
Cody Northropacfb0492015-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 Northrop1cfbd172015-06-03 16:49:20 -0600283 printf("\t--strip-SPV\n"
Cody Northrop1e056dd2015-07-13 12:48:41 -0600284 "\t\tStrip SPIR-V debug information (line numbers, names, etc).\n");
Cody Northrop1cfbd172015-06-03 16:49:20 -0600285 printf("\t--canonicalize-SPV\n"
Cody Northrop1e056dd2015-07-13 12:48:41 -0600286 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
Cody Northrop1cfbd172015-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 Barbour772c5ef2014-12-10 17:00:20 -0700291 exit(0);
Courtney Goeltzenleuchterb7f26e02014-12-02 13:13:10 -0700292 }
293
Cody Northrop1cfbd172015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600299 argv[n] = argv[i];
300 n++;
301 }
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600302}
303
Tony Barbour01999182015-04-09 12:58:51 -0600304void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600305{
306 string filename;
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600307 VkResult err;
Tony Barbour8bef8ee2015-05-22 09:44:58 -0600308 uint32_t x, y;
Tony Barbour01999182015-04-09 12:58:51 -0600309 VkImageObj displayImage(image->device());
Tony Barbour94310562015-04-22 15:10:33 -0600310 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbouredc49d92015-04-02 14:02:33 -0600311
Tony Barboura7ec3ba2015-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 Barbouredc49d92015-04-02 14:02:33 -0600313 displayImage.CopyImage(*image);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600314
315 filename.append(basename);
316 filename.append(".ppm");
Tony Barbour25e3b832015-05-20 16:53:31 -0600317
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600318 const VkImageSubresource sr = {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600319 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600320 };
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600321 VkSubresourceLayout sr_layout;
Tony Barbour25e3b832015-05-20 16:53:31 -0600322
Tony Barbour426b9052015-06-24 16:06:58 -0600323 err = vkGetImageSubresourceLayout(image->device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600324 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600325
Tony Barbouredc49d92015-04-02 14:02:33 -0600326 char *ptr;
Chia-I Wuf4aed6c2015-07-03 13:44:34 +0800327 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600328 ptr += sr_layout.offset;
Tony Barbour25e3b832015-05-20 16:53:31 -0600329 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600330 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
331
332 file << "P6\n";
Tony Barboura26fb7d2015-09-21 15:17:33 -0600333 file << displayImage.width() << " ";
Tony Barbouredc49d92015-04-02 14:02:33 -0600334 file << displayImage.height() << "\n";
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600335 file << 255 << "\n";
336
Tony Barbouredc49d92015-04-02 14:02:33 -0600337 for (y = 0; y < displayImage.height(); y++) {
Tony Barboure2668672015-02-25 11:25:11 -0700338 const int *row = (const int *) ptr;
339 int swapped;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600340
Tony Barbour8205d902015-04-16 15:59:00 -0600341 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboure2668672015-02-25 11:25:11 -0700342 {
Tony Barbouredc49d92015-04-02 14:02:33 -0600343 for (x = 0; x < displayImage.width(); x++) {
Tony Barboure2668672015-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 Barbour8205d902015-04-16 15:59:00 -0600349 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboure2668672015-02-25 11:25:11 -0700350 {
Tony Barbouredc49d92015-04-02 14:02:33 -0600351 for (x = 0; x < displayImage.width(); x++) {
Tony Barboure2668672015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600359 }
360
361 ptr += sr_layout.rowPitch;
362 }
363
364 file.close();
Chia-I Wuf4aed6c2015-07-03 13:44:34 +0800365 displayImage.UnmapMemory();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600366}
367
Tony Barbour01999182015-04-09 12:58:51 -0600368void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour32f368c2014-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 Barbour25e3b832015-05-20 16:53:31 -0600375 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour32f368c2014-10-30 14:29:04 -0600376 double differenz;
377
Tony Barbour772c5ef2014-12-10 17:00:20 -0700378 if (getenv("RENDERTEST_GOLDEN_DIR"))
379 {
380 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
381 }
382
Tony Barbour32f368c2014-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 Barbour8bef8ee2015-05-22 09:44:58 -0600387 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour32f368c2014-10-30 14:29:04 -0600388
389
390 MagickWandGenesis();
391 magick_wand_2=NewMagickWand();
Tony Barbour772c5ef2014-12-10 17:00:20 -0700392 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour32f368c2014-10-30 14:29:04 -0600393 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour8bef8ee2015-05-22 09:44:58 -0600394 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour32f368c2014-10-30 14:29:04 -0600395
Tony Barbour32f368c2014-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 Goeltzenleuchterdfa97b82014-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 Barbour32f368c2014-10-30 14:29:04 -0600419}
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600420
Tony Barbour01999182015-04-09 12:58:51 -0600421void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600422{
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600423 VkResult err;
Courtney Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600424 VkSubresourceLayout sr_layout;
425 char *ptr;
426 VkTestImageRecord record;
Courtney Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600427 VkImageObj displayImage(image->device());
428 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
429
Cody Northrop025cbb12015-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 Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600432 displayImage.CopyImage(*image);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600433
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600434 const VkImageSubresource sr = {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600435 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600436 };
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600437
Tony Barbour426b9052015-06-24 16:06:58 -0600438 err = vkGetImageSubresourceLayout(displayImage.device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600439 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600440
Chia-I Wuf4aed6c2015-07-03 13:44:34 +0800441 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600442 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600443
444 ptr += sr_layout.offset;
445
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600446 record.m_title.append(comment);
Courtney Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600447 record.m_width = displayImage.width();
448 record.m_height = displayImage.height();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600449 // TODO: Need to make this more robust to handle different image formats
Tony-LunarGf05ba082015-05-19 14:08:26 -0600450 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchterd0d7ccc2014-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 Wuf4aed6c2015-07-03 13:44:34 +0800456 displayImage.UnmapMemory();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600457}
458
Tony Barbour01999182015-04-09 12:58:51 -0600459void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour32f368c2014-10-30 14:29:04 -0600460{
Courtney Goeltzenleuchtercd5ed1e2015-04-02 14:17:44 -0600461 for (int32_t i = 0; i < images.size(); i++) {
462 RecordImage(images[i]);
Tony Barbour32f368c2014-10-30 14:29:04 -0600463 }
464}
465
Tony Barbour01999182015-04-09 12:58:51 -0600466void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600467{
468 const ::testing::TestInfo* const test_info =
469 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour32f368c2014-10-30 14:29:04 -0600470 ostringstream filestream;
471 string filename;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600472
Tony Barbour32f368c2014-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 Barboura48b0812014-11-18 17:02:36 -0700478 m_frameNum = 2;
479 filename = filestream.str();
Tony Barbour32f368c2014-10-30 14:29:04 -0600480 }
481 else {
482 filestream << test_info->name() << "-" << m_frameNum;
483 m_frameNum++;
Tony Barboura48b0812014-11-18 17:02:36 -0700484 filename = filestream.str();
Tony Barbour32f368c2014-10-30 14:29:04 -0600485 }
486
Tony Barbour32f368c2014-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600494 }
495
496 if (m_show_images) {
Courtney Goeltzenleuchtere5409342014-10-08 14:26:40 -0600497 Show(test_info->name(), image);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600498 }
499}
500
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800501TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
502 m_device(device),
Courtney Goeltzenleuchterdd745fd2015-03-05 16:47:18 -0700503 m_queue(*m_device.graphics_queues()[0]),
Dana Jansens6e2dda12015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600506{
Tony Barbouref20d322015-02-25 12:28:39 -0700507 m_quit = false;
508 m_pause = false;
509 m_width = 0;
510 m_height = 0;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600511}
512
Tony Barbour01999182015-04-09 12:58:51 -0600513void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600514{
Tony Barbour22a30862015-04-22 09:02:32 -0600515 VkResult U_ASSERT_ONLY err;
Tony-LunarGf05ba082015-05-19 14:08:26 -0600516 vk_testing::Buffer buf;
517 void *dest_ptr;
518
Tony Barbourb3744222015-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 Elliott338dedb2015-08-21 15:09:33 -0600532 err = m_fpAcquireNextImageKHR(m_device.handle(), m_swap_chain,
Tony Barbourb3744222015-07-23 10:36:18 -0600533 UINT64_MAX,
534 presentCompleteSemaphore,
535 &m_current_buffer);
Ian Elliott338dedb2015-08-21 15:09:33 -0600536 // TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
Tony Barbourb3744222015-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 Barboure483fc02015-10-23 10:58:56 -0600545 vkDestroySemaphore(m_device.handle(), presentCompleteSemaphore);
Tony-LunarGf05ba082015-05-19 14:08:26 -0600546
547 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Cody Northropd0e7d222015-06-22 14:56:14 -0600548 buf.init_as_src(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
Chia-I Wuf4aed6c2015-07-03 13:44:34 +0800549 dest_ptr = buf.memory().map();
Tony-LunarGf05ba082015-05-19 14:08:26 -0600550 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
Chia-I Wuf4aed6c2015-07-03 13:44:34 +0800551 buf.memory().unmap();
Tony-LunarGf05ba082015-05-19 14:08:26 -0600552
553 m_cmdbuf.begin();
Tony Barbour24366562015-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-LunarGf05ba082015-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 Wu78c2a352015-07-03 11:49:42 +0800578 vkCmdCopyBufferToImage(m_cmdbuf.handle(),
Chia-I Wuf4aed6c2015-07-03 13:44:34 +0800579 buf.handle(),
Tony Barbourb3744222015-07-23 10:36:18 -0600580 m_buffers[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
Tony-LunarGf05ba082015-05-19 14:08:26 -0600581 1, &region);
Tony Barbour24366562015-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-LunarGf05ba082015-05-19 14:08:26 -0600587 m_cmdbuf.end();
588
589 VkCmdBuffer cmdBufs[1];
Chia-I Wu78c2a352015-07-03 11:49:42 +0800590 cmdBufs[0] = m_cmdbuf.handle();
Tony-LunarGf05ba082015-05-19 14:08:26 -0600591
Tony Barboure84a8d62015-07-10 14:10:27 -0600592 VkFence nullFence = { VK_NULL_HANDLE };
593 vkQueueSubmit(m_queue.handle(), 1, cmdBufs, nullFence);
Tony-LunarGf05ba082015-05-19 14:08:26 -0600594 m_queue.wait();
Tony Barbouref20d322015-02-25 12:28:39 -0700595
Ian Elliott338dedb2015-08-21 15:09:33 -0600596 VkPresentInfoKHR present = {};
597 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
Tony Barbourb3744222015-07-23 10:36:18 -0600598 present.pNext = NULL;
Ian Elliott338dedb2015-08-21 15:09:33 -0600599 present.swapchainCount = 1;
600 present.swapchains = & m_swap_chain;
Tony Barbourb3744222015-07-23 10:36:18 -0600601 present.imageIndices = &m_current_buffer;
Tony Barbouref20d322015-02-25 12:28:39 -0700602
Tony Barbour25e3b832015-05-20 16:53:31 -0600603#ifndef _WIN32
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800604 xcb_change_property (m_connection,
Tony Barbouref20d322015-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 Barbour25e3b832015-05-20 16:53:31 -0600612#endif
Jon Ashburncedc15f2015-05-21 18:13:33 -0600613
Ian Elliott338dedb2015-08-21 15:09:33 -0600614 err = m_fpQueuePresentKHR(m_queue.handle(), &present);
Tony Barbouref20d322015-02-25 12:28:39 -0700615 assert(!err);
616
617 m_queue.wait();
Tony-LunarGf05ba082015-05-19 14:08:26 -0600618 m_current_buffer = (m_current_buffer + 1) % 2;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600619}
620
Tony Barbour25e3b832015-05-20 16:53:31 -0600621#ifdef _WIN32
Tony-LunarGf05ba082015-05-19 14:08:26 -0600622# define PREVIOUSLY_DOWN 1<<29
Tony Barbour25e3b832015-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-LunarGf05ba082015-05-19 14:08:26 -0600640 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour25e3b832015-05-20 16:53:31 -0600641 me->Display();
642 }
643 }
Tony-LunarGf05ba082015-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 Barbour25e3b832015-05-20 16:53:31 -0600681 }
682 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
683}
684
685void TestFrameworkVkPresent::Run()
686{
687 MSG msg; // message
Tony Barbour25e3b832015-05-20 16:53:31 -0600688
Tony Barbour25e3b832015-05-20 16:53:31 -0600689 /* main message loop*/
Tony-LunarGf05ba082015-05-19 14:08:26 -0600690 while(! m_quit) {
691 GetMessage(&msg, m_window, 0, 0);
Tony Barbour25e3b832015-05-20 16:53:31 -0600692 if (msg.message == WM_QUIT) {
Tony-LunarGf05ba082015-05-19 14:08:26 -0600693 m_quit = true; //if found, quit app
Tony Barbour25e3b832015-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 Barbour01999182015-04-09 12:58:51 -0600703void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600704{
Tony Barbour3a5cda02015-04-02 15:48:24 -0600705 uint8_t event_code = event->response_type & 0x7f;
Tony Barbouref20d322015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600714 }
715 break;
Tony Barbouref20d322015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600720
Tony Barbouref20d322015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600746 break;
747 }
Tony Barbouref20d322015-02-25 12:28:39 -0700748}
749
Tony Barbour01999182015-04-09 12:58:51 -0600750void TestFrameworkVkPresent::Run()
Tony Barbouref20d322015-02-25 12:28:39 -0700751{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800752 xcb_flush(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700753
754 while (! m_quit) {
755 xcb_generic_event_t *event;
756
757 if (m_pause) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800758 event = xcb_wait_for_event(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700759 } else {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800760 event = xcb_poll_for_event(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700761 }
762 if (event) {
763 HandleEvent(event);
764 free(event);
765 }
766 }
767}
Tony Barbour25e3b832015-05-20 16:53:31 -0600768#endif // _WIN32
Tony Barbouref20d322015-02-25 12:28:39 -0700769
Ian Elliott338dedb2015-08-21 15:09:33 -0600770void TestFrameworkVkPresent::CreateSwapchain()
Tony Barbouref20d322015-02-25 12:28:39 -0700771{
Tony Barbour22a30862015-04-22 09:02:32 -0600772 VkResult U_ASSERT_ONLY err;
Tony Barbouref20d322015-02-25 12:28:39 -0700773
Tony-LunarGf05ba082015-05-19 14:08:26 -0600774 m_display_image = m_images.begin();
775 m_current_buffer = 0;
776
Tony Barbourb3744222015-07-23 10:36:18 -0600777 // Construct the WSI surface description:
Ian Elliott338dedb2015-08-21 15:09:33 -0600778 m_surface_description.sType = VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_KHR;
Tony Barbourb3744222015-07-23 10:36:18 -0600779 m_surface_description.pNext = NULL;
Ian Elliott331f4e82015-07-06 14:33:04 -0600780#ifdef _WIN32
Ian Elliott338dedb2015-08-21 15:09:33 -0600781 m_surface_description.platform = VK_PLATFORM_WIN32_KHR;
Tony Barbourb3744222015-07-23 10:36:18 -0600782 m_surface_description.pPlatformHandle = m_connection;
783 m_surface_description.pPlatformWindow = m_window;
Ian Elliott331f4e82015-07-06 14:33:04 -0600784#else // _WIN32
Tony Barbourb3744222015-07-23 10:36:18 -0600785 m_platform_handle_xcb.connection = m_connection;
786 m_platform_handle_xcb.root = m_screen->root;
Ian Elliott338dedb2015-08-21 15:09:33 -0600787 m_surface_description.platform = VK_PLATFORM_XCB_KHR;
Tony Barbourb3744222015-07-23 10:36:18 -0600788 m_surface_description.pPlatformHandle = &m_platform_handle_xcb;
789 m_surface_description.pPlatformWindow = &m_window;
Ian Elliott331f4e82015-07-06 14:33:04 -0600790#endif // _WIN32
Tony Barbourb3744222015-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 Elliott338dedb2015-08-21 15:09:33 -0600799 m_fpGetPhysicalDeviceSurfaceSupportKHR(m_device.phy().handle(),
Tony Barbourb3744222015-07-23 10:36:18 -0600800 family_index,
Ian Elliott338dedb2015-08-21 15:09:33 -0600801 (VkSurfaceDescriptionKHR *) &m_surface_description,
Tony Barbourb3744222015-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 Elliottdad13202015-08-07 11:51:12 -0600812 uint32_t formatCount;
Ian Elliott338dedb2015-08-21 15:09:33 -0600813 err = m_fpGetSurfaceFormatsKHR(m_device.handle(),
814 (VkSurfaceDescriptionKHR *) &m_surface_description,
Ian Elliottdad13202015-08-07 11:51:12 -0600815 &formatCount, NULL);
Tony Barbourb3744222015-07-23 10:36:18 -0600816 assert(!err);
Ian Elliott338dedb2015-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 Elliottdad13202015-08-07 11:51:12 -0600821 &formatCount, surfFormats);
Tony Barbourb3744222015-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 Barbourb3744222015-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 Elliottdad13202015-08-07 11:51:12 -0600835 m_color_space = surfFormats[0].colorSpace;
Tony Barbourb3744222015-07-23 10:36:18 -0600836
837 // Check the surface proprties and formats
Ian Elliott338dedb2015-08-21 15:09:33 -0600838 VkSurfacePropertiesKHR surfProperties;
839 err = m_fpGetSurfacePropertiesKHR(m_device.handle(),
840 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliottdad13202015-08-07 11:51:12 -0600841 &surfProperties);
Tony Barbourb3744222015-07-23 10:36:18 -0600842 assert(!err);
843
Ian Elliottdad13202015-08-07 11:51:12 -0600844 uint32_t presentModeCount;
Ian Elliott338dedb2015-08-21 15:09:33 -0600845 err = m_fpGetSurfacePresentModesKHR(m_device.handle(),
846 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliottdad13202015-08-07 11:51:12 -0600847 &presentModeCount, NULL);
Tony Barbourb3744222015-07-23 10:36:18 -0600848 assert(!err);
Ian Elliott338dedb2015-08-21 15:09:33 -0600849 VkPresentModeKHR *presentModes =
850 (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
Ian Elliottdad13202015-08-07 11:51:12 -0600851 assert(presentModes);
Ian Elliott338dedb2015-08-21 15:09:33 -0600852 err = m_fpGetSurfacePresentModesKHR(m_device.handle(),
853 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliottdad13202015-08-07 11:51:12 -0600854 &presentModeCount, presentModes);
Tony Barbourb3744222015-07-23 10:36:18 -0600855 assert(!err);
856
Ian Elliott338dedb2015-08-21 15:09:33 -0600857 VkExtent2D swapchainExtent;
Tony Barbourb3744222015-07-23 10:36:18 -0600858 // width and height are either both -1, or both not -1.
Ian Elliottdad13202015-08-07 11:51:12 -0600859 if (surfProperties.currentExtent.width == -1)
Tony Barbourb3744222015-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 Elliott338dedb2015-08-21 15:09:33 -0600863 swapchainExtent.width = m_width;
864 swapchainExtent.height = m_height;
Tony Barbourb3744222015-07-23 10:36:18 -0600865 }
866 else
867 {
868 // If the surface size is defined, the swap chain size must match
Ian Elliott338dedb2015-08-21 15:09:33 -0600869 swapchainExtent = surfProperties.currentExtent;
Tony Barbourb3744222015-07-23 10:36:18 -0600870 }
871
872 // If mailbox mode is available, use it, as is the lowest-latency non-
Ian Elliotta96de0f2015-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 Elliott338dedb2015-08-21 15:09:33 -0600876 VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
Tony Barbourb3744222015-07-23 10:36:18 -0600877 for (size_t i = 0; i < presentModeCount; i++) {
Ian Elliott338dedb2015-08-21 15:09:33 -0600878 if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
879 swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
Tony Barbourb3744222015-07-23 10:36:18 -0600880 break;
881 }
Ian Elliott338dedb2015-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 Elliotta96de0f2015-08-10 13:20:49 -0600885 }
Tony Barbourb3744222015-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 Elliott338dedb2015-08-21 15:09:33 -0600891 uint32_t desiredNumberOfSwapchainImages = surfProperties.minImageCount + 1;
Ian Elliottdad13202015-08-07 11:51:12 -0600892 if ((surfProperties.maxImageCount > 0) &&
Ian Elliott338dedb2015-08-21 15:09:33 -0600893 (desiredNumberOfSwapchainImages > surfProperties.maxImageCount))
Tony Barbourb3744222015-07-23 10:36:18 -0600894 {
895 // Application must settle for fewer images than desired:
Ian Elliott338dedb2015-08-21 15:09:33 -0600896 desiredNumberOfSwapchainImages = surfProperties.maxImageCount;
Tony Barbourb3744222015-07-23 10:36:18 -0600897 }
898
Ian Elliott338dedb2015-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 Barbourb3744222015-07-23 10:36:18 -0600902 } else {
Ian Elliottdad13202015-08-07 11:51:12 -0600903 preTransform = surfProperties.currentTransform;
Tony Barbourb3744222015-07-23 10:36:18 -0600904 }
Ian Elliott331f4e82015-07-06 14:33:04 -0600905
Cody Northrop3b0a3ef2015-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 Elliott338dedb2015-08-21 15:09:33 -0600909 VkSwapchainCreateInfoKHR swap_chain = {};
Ian Elliott434d2222015-09-22 10:20:23 -0600910 swap_chain.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
Ian Elliott331f4e82015-07-06 14:33:04 -0600911 swap_chain.pNext = NULL;
Ian Elliott338dedb2015-08-21 15:09:33 -0600912 swap_chain.pSurfaceDescription = (const VkSurfaceDescriptionKHR *)&m_surface_description;
913 swap_chain.minImageCount = desiredNumberOfSwapchainImages;
Tony Barbourb3744222015-07-23 10:36:18 -0600914 swap_chain.imageFormat = m_format;
Ian Elliottdad13202015-08-07 11:51:12 -0600915 swap_chain.imageColorSpace = m_color_space;
Ian Elliott338dedb2015-08-21 15:09:33 -0600916 swap_chain.imageExtent.width = swapchainExtent.width;
917 swap_chain.imageExtent.height = swapchainExtent.height;
Cody Northrop7f815382015-08-05 15:38:39 -0600918 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT |
919 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
Tony Barbourb3744222015-07-23 10:36:18 -0600920 swap_chain.preTransform = preTransform;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800921 swap_chain.imageArraySize = 1;
Ian Elliottdad13202015-08-07 11:51:12 -0600922 swap_chain.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
923 swap_chain.queueFamilyCount = 0;
924 swap_chain.pQueueFamilyIndices = NULL;
Ian Elliott338dedb2015-08-21 15:09:33 -0600925 swap_chain.presentMode = swapchainPresentMode;
926 swap_chain.oldSwapchain.handle = 0;
Tony Barbourb3744222015-07-23 10:36:18 -0600927 swap_chain.clipped = true;
928
929 uint32_t i;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800930
Ian Elliott338dedb2015-08-21 15:09:33 -0600931 err = m_fpCreateSwapchainKHR(m_device.handle(), &swap_chain, &m_swap_chain);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800932 assert(!err);
933
Ian Elliott338dedb2015-08-21 15:09:33 -0600934 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
935 &m_swapchainImageCount, NULL);
Tony Barbourb3744222015-07-23 10:36:18 -0600936 assert(!err);
937
Ian Elliott338dedb2015-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 Barbourb3744222015-07-23 10:36:18 -0600942 assert(!err);
943
Ian Elliott338dedb2015-08-21 15:09:33 -0600944 m_buffers = (SwapchainBuffers*)malloc(sizeof(SwapchainBuffers)*m_swapchainImageCount);
Tony Barbourb3744222015-07-23 10:36:18 -0600945 assert(m_buffers);
946
Ian Elliott338dedb2015-08-21 15:09:33 -0600947 for (i = 0; i < m_swapchainImageCount; i++) {
Courtney Goeltzenleuchter1856d6f2015-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 Goeltzenleuchter065983e2015-09-11 15:22:06 -0600951 color_image_view.viewType = VK_IMAGE_VIEW_TYPE_2D;
Courtney Goeltzenleuchter1856d6f2015-09-01 17:30:39 -0600952 color_image_view.format = m_format;
Courtney Goeltzenleuchteraeffeae2015-09-10 17:58:54 -0600953 color_image_view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
Courtney Goeltzenleuchter1856d6f2015-09-01 17:30:39 -0600954 color_image_view.subresourceRange.baseMipLevel = 0;
955 color_image_view.subresourceRange.mipLevels = 1;
Courtney Goeltzenleuchter3dee8082015-09-10 16:38:41 -0600956 color_image_view.subresourceRange.baseArrayLayer = 0;
Courtney Goeltzenleuchter1856d6f2015-09-01 17:30:39 -0600957 color_image_view.subresourceRange.arraySize = 1;
Tony Barbourb3744222015-07-23 10:36:18 -0600958
Ian Elliott338dedb2015-08-21 15:09:33 -0600959 m_buffers[i].image = swapchainImages[i];
Tony Barbourb3744222015-07-23 10:36:18 -0600960
Courtney Goeltzenleuchter1856d6f2015-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 Barbourb3744222015-07-23 10:36:18 -0600964 assert(!err);
Tony Barbour24366562015-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 Barbourb3744222015-07-23 10:36:18 -0600971 }
Tony Barbouref20d322015-02-25 12:28:39 -0700972}
Tony Barbour24366562015-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 Barbouref20d322015-02-25 12:28:39 -07001034
Jon Ashburncedc15f2015-05-21 18:13:33 -06001035void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbouref20d322015-02-25 12:28:39 -07001036{
Ian Elliott338dedb2015-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 Ashburncedc15f2015-05-21 18:13:33 -06001047
Tony Barbouref20d322015-02-25 12:28:39 -07001048 m_images = imagesIn;
1049}
1050
Tony Barbour25e3b832015-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 Northropb746ee72015-08-05 15:39:31 -06001087 RECT wr = { 0, 0, m_width, m_height };
1088 AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
Tony Barbour25e3b832015-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 Northropb746ee72015-08-05 15:39:31 -06001096 wr.right - wr.left, // width
1097 wr.bottom - wr.top, // height
Tony Barbour25e3b832015-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-LunarGf05ba082015-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 Barbour25e3b832015-05-20 16:53:31 -06001113}
1114#else
Tony Barbour01999182015-04-09 12:58:51 -06001115void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbouref20d322015-02-25 12:28:39 -07001116{
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001117 const xcb_setup_t *setup;
1118 xcb_screen_iterator_t iter;
1119 int scr;
Tony Barbouref20d322015-02-25 12:28:39 -07001120 uint32_t value_mask, value_list[32];
1121
Chia-I Wu5b66aa52015-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 Barbouref20d322015-02-25 12:28:39 -07001140
1141 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001142 value_list[0] = m_screen->black_pixel;
Tony Barbouref20d322015-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 Wu5b66aa52015-04-16 22:02:10 +08001147 xcb_create_window(m_connection,
Tony Barbouref20d322015-02-25 12:28:39 -07001148 XCB_COPY_FROM_PARENT,
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001149 m_window, m_screen->root,
Tony Barbouref20d322015-02-25 12:28:39 -07001150 0, 0, m_width, m_height, 0,
1151 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001152 m_screen->root_visual,
Tony Barbouref20d322015-02-25 12:28:39 -07001153 value_mask, value_list);
1154
1155 /* Magic code that will send notification when window is destroyed */
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001156 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbouref20d322015-02-25 12:28:39 -07001157 "WM_PROTOCOLS");
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001158 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbouref20d322015-02-25 12:28:39 -07001159
Chia-I Wu5b66aa52015-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 Barbouref20d322015-02-25 12:28:39 -07001162
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001163 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbouref20d322015-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 Wu5b66aa52015-04-16 22:02:10 +08001168 xcb_map_window(m_connection, m_window);
Tony Barbouref20d322015-02-25 12:28:39 -07001169}
Tony Barbour25e3b832015-05-20 16:53:31 -06001170#endif
Tony Barbouref20d322015-02-25 12:28:39 -07001171
Tony Barbour01999182015-04-09 12:58:51 -06001172void TestFrameworkVkPresent::TearDown()
Tony Barbouref20d322015-02-25 12:28:39 -07001173{
Ian Elliott338dedb2015-08-21 15:09:33 -06001174 m_fpDestroySwapchainKHR(m_device.handle(), m_swap_chain);
Tony Barboure483fc02015-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 Barbour25e3b832015-05-20 16:53:31 -06001179#ifndef _WIN32
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001180 xcb_destroy_window(m_connection, m_window);
1181 xcb_disconnect(m_connection);
Tony Barbour25e3b832015-05-20 16:53:31 -06001182#endif
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001183}
1184
Tony Barbour01999182015-04-09 12:58:51 -06001185void VkTestFramework::Finish()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001186{
1187 if (m_images.size() == 0) return;
1188
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001189 vk_testing::Environment env;
1190 env.SetUp();
Tony Barbouref20d322015-02-25 12:28:39 -07001191 {
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001192 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbouref20d322015-02-25 12:28:39 -07001193
Jon Ashburncedc15f2015-05-21 18:13:33 -06001194 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001195 vkPresent.CreateMyWindow();
Ian Elliott338dedb2015-08-21 15:09:33 -06001196 vkPresent.CreateSwapchain();
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001197 vkPresent.Run();
1198 vkPresent.TearDown();
Tony Barbouref20d322015-02-25 12:28:39 -07001199 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001200 env.TearDown();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001201}
1202
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001203//
Courtney Goeltzenleuchter94192032014-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 Barbour01999182015-04-09 12:58:51 -06001307bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter94192032014-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 Barbour01999182015-04-09 12:58:51 -06001323void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter94192032014-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 Goeltzenleuchter358c76e2015-09-24 17:05:05 -06001337 config = (char *) alloca(strlen(DefaultConfig) + 1);
Courtney Goeltzenleuchter94192032014-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 Barbour01999182015-04-09 12:58:51 -06001545void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter94192032014-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 Barbour01999182015-04-09 12:58:51 -06001558char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter94192032014-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 Barbour01999182015-04-09 12:58:51 -06001621void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter94192032014-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 Barbour01999182015-04-09 12:58:51 -06001638EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter94192032014-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 Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001663// Convert VK shader type to compiler's
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001664//
Tony Barbour8205d902015-04-16 15:59:00 -06001665EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001666{
1667 switch (shader_type) {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001668 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001669 return EShLangVertex;
1670
Courtney Goeltzenleuchterc6fd2262015-10-15 17:35:38 -06001671 case VK_SHADER_STAGE_TESSELLATION_CONTROL:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001672 return EShLangTessControl;
1673
Courtney Goeltzenleuchterc6fd2262015-10-15 17:35:38 -06001674 case VK_SHADER_STAGE_TESSELLATION_EVALUATION:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001675 return EShLangTessEvaluation;
1676
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001677 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001678 return EShLangGeometry;
1679
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001680 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001681 return EShLangFragment;
1682
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001683 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001684 return EShLangCompute;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001685
Chia-I Wubbdeacc2014-12-15 23:50:11 +08001686 default:
1687 return EShLangVertex;
1688 }
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001689}
1690
1691
1692//
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001693// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001694// Return value of false means an error was encountered.
1695//
Tony Barbour8205d902015-04-16 15:59:00 -06001696bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001697 const char *pshader,
Cody Northropeb9130e2015-06-03 13:01:54 -06001698 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001699{
Courtney Goeltzenleuchter358c76e2015-09-24 17:05:05 -06001700 glslang::TProgram program;
Courtney Goeltzenleuchter94192032014-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 Northropad306f02014-11-03 12:54:37 -07001720 if (! (m_compile_options & EOptionSuppressInfolog)) {
1721 puts(shader->getInfoLog());
1722 puts(shader->getInfoDebugLog());
1723 }
1724
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001725 return false; // something didn't work
1726 }
1727
1728 program.addShader(shader);
1729
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001730
1731 //
1732 // Program-level processing...
1733 //
1734
Cody Northropad306f02014-11-03 12:54:37 -07001735 if (! program.link(messages)) {
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001736
Cody Northropad306f02014-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 Goeltzenleuchter94192032014-10-03 09:53:32 -06001743 }
1744
1745 if (m_compile_options & EOptionDumpReflection) {
1746 program.buildReflection();
1747 program.dumpReflection();
1748 }
1749
Cody Northropeb9130e2015-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 Goeltzenleuchter358c76e2015-09-24 17:05:05 -06001767 delete shader;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001768
1769 return true;
1770}
1771
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001772
1773
Tony Barbour01999182015-04-09 12:58:51 -06001774VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001775 m_width( 0 ),
1776 m_height( 0 ),
Chia-I Wub2c2dea2014-12-15 23:29:34 +08001777 m_data( NULL ),
1778 m_data_size( 0 )
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001779{
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001780}
1781
Tony Barbour01999182015-04-09 12:58:51 -06001782VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001783{
1784
1785}
1786
Tony Barbour01999182015-04-09 12:58:51 -06001787VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchterd0d7ccc2014-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 Barbour01999182015-04-09 12:58:51 -06001796ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001797{
Tony Barbour01999182015-04-09 12:58:51 -06001798 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1799 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001800 return output;
1801}
1802
Tony Barbour01999182015-04-09 12:58:51 -06001803VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchterd0d7ccc2014-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001810 return *this;
1811}
1812
Tony Barbour01999182015-04-09 12:58:51 -06001813int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchterd0d7ccc2014-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 Barbour01999182015-04-09 12:58:51 -06001820int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001821{
1822 if( this->m_data_size < rhs.m_data_size ) return 1;
1823 return 0;
1824}
1825