blob: e98d9a4e040e0c136c0cf2136c1eb81d87413421 [file] [log] [blame]
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001//
Courtney Goeltzenleuchterfcbe16f2015-10-29 13:50:34 -06002// Copyright (C) 2015 Valve Corporation
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06003//
4// Permission is hereby granted, free of charge, to any person obtaining a
5// copy of this software and associated documentation files (the "Software"),
6// to deal in the Software without restriction, including without limitation
7// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8// and/or sell copies of the Software, and to permit persons to whom the
9// Software is furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included
12// in all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060021//
22// Author: Chia-I Wu <olv@lunarg.com>
23// Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
24// Author: Tony Barbour <tony@LunarG.com>
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -060025
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060026#include "vktestframework.h"
27#include "vkrenderframework.h"
Jon Ashburn94207e92015-12-04 17:03:59 -070028//TODO FIXME remove this once glslang doesn't define this
29#undef BadValue
Cody Northrop5a95b472015-06-03 13:01:54 -060030#include "SPIRV/GlslangToSpv.h"
31#include "SPIRV/SPVRemapper.h"
Tony Barbour4ab45422014-12-10 17:00:20 -070032#include <limits.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060033#include <math.h>
Chia-I Wuec664fa2014-12-02 11:54:24 +080034#include <wand/MagickWand.h>
Jon Ashburn94207e92015-12-04 17:03:59 -070035
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060036
Tony Barbour3d69c9e2015-05-20 16:53:31 -060037#if defined(PATH_MAX) && !defined(MAX_PATH)
38#define MAX_PATH PATH_MAX
39#endif
40
Tony Barbour6a3faf02015-07-23 10:36:18 -060041#ifdef _WIN32
42#define ERR_EXIT(err_msg, err_class) \
43 do { \
44 MessageBox(NULL, err_msg, err_class, MB_OK); \
45 exit(1); \
46 } while (0)
47#else // _WIN32
48
49#define ERR_EXIT(err_msg, err_class) \
50 do { \
51 printf(err_msg); \
52 fflush(stdout); \
53 exit(1); \
54 } while (0)
55#endif // _WIN32
56
57#define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \
58{ \
59 m_fp##entrypoint = (PFN_vk##entrypoint) vkGetInstanceProcAddr(inst, "vk"#entrypoint); \
60 if (m_fp##entrypoint == NULL) { \
61 ERR_EXIT("vkGetInstanceProcAddr failed to find vk"#entrypoint, \
62 "vkGetInstanceProcAddr Failure"); \
63 } \
64}
65
66#define GET_DEVICE_PROC_ADDR(dev, entrypoint) \
67{ \
68 m_fp##entrypoint = (PFN_vk##entrypoint) vkGetDeviceProcAddr(dev, "vk"#entrypoint); \
69 if (m_fp##entrypoint == NULL) { \
70 ERR_EXIT("vkGetDeviceProcAddr failed to find vk"#entrypoint, \
71 "vkGetDeviceProcAddr Failure"); \
72 } \
73}
74
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060075// Command-line options
76enum TOptions {
77 EOptionNone = 0x000,
78 EOptionIntermediate = 0x001,
79 EOptionSuppressInfolog = 0x002,
80 EOptionMemoryLeakMode = 0x004,
81 EOptionRelaxedErrors = 0x008,
82 EOptionGiveWarnings = 0x010,
83 EOptionLinkProgram = 0x020,
84 EOptionMultiThreaded = 0x040,
85 EOptionDumpConfig = 0x080,
86 EOptionDumpReflection = 0x100,
87 EOptionSuppressWarnings = 0x200,
88 EOptionDumpVersions = 0x400,
Cody Northrop3bfd27c2015-03-17 15:55:58 -060089 EOptionSpv = 0x800,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060090 EOptionDefaultDesktop = 0x1000,
91};
92
Ian Elliott7e40db92015-08-21 15:09:33 -060093typedef struct _SwapchainBuffers {
Tony Barbour6a3faf02015-07-23 10:36:18 -060094 VkImage image;
Chia-I Wu3432a0c2015-10-27 18:04:07 +080095 VkCommandBuffer cmd;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -060096 VkImageView view;
Ian Elliott7e40db92015-08-21 15:09:33 -060097} SwapchainBuffers;
Tony Barbour6a3faf02015-07-23 10:36:18 -060098
Chia-I Wuf8693382015-04-16 22:02:10 +080099class TestFrameworkVkPresent
100{
101public:
102 TestFrameworkVkPresent(vk_testing::Device &device);
103
104 void Run();
Jon Ashburn07daee72015-05-21 18:13:33 -0600105 void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst);
Chia-I Wuf8693382015-04-16 22:02:10 +0800106 void CreateMyWindow();
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700107 VkFormat GetPresentFormat();
Tony Barboure1837292015-12-07 13:46:11 -0700108 void DestroyMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -0600109 void CreateSwapchain();
Tony Barbourbd094ce2015-10-23 11:00:15 -0600110 void SetImageLayout(VkImage image, VkImageAspectFlags aspectMask,
111 VkImageLayout old_image_layout, VkImageLayout new_image_layout);
Chia-I Wuf8693382015-04-16 22:02:10 +0800112 void TearDown();
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600113#ifdef _WIN32
114 static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
115#endif
116
Chia-I Wuf8693382015-04-16 22:02:10 +0800117
118protected:
119 vk_testing::Device &m_device;
120 vk_testing::Queue &m_queue;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800121 vk_testing::CommandPool m_cmdpool;
122 vk_testing::CommandBuffer m_cmdbuf;
Chia-I Wuf8693382015-04-16 22:02:10 +0800123
124private:
Ian Elliottc11750d2015-10-30 13:24:12 -0600125 VkInstance m_instance;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600126#ifdef _WIN32
127 HINSTANCE m_connection; // hInstance - Windows Instance
128 HWND m_window; // hWnd - window handle
129
130#else
Chia-I Wuf8693382015-04-16 22:02:10 +0800131 xcb_connection_t *m_connection;
132 xcb_screen_t *m_screen;
133 xcb_window_t m_window;
134 xcb_intern_atom_reply_t *m_atom_wm_delete_window;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600135#endif
Ian Elliottc11750d2015-10-30 13:24:12 -0600136 VkSurfaceKHR m_surface;
Courtney Goeltzenleuchterd6079ec2015-04-22 10:09:35 -0600137 std::list<VkTestImageRecord> m_images;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600138 uint32_t m_present_queue_node_index;
Chia-I Wuf8693382015-04-16 22:02:10 +0800139
Ian Elliott7e40db92015-08-21 15:09:33 -0600140 PFN_vkGetPhysicalDeviceSurfaceSupportKHR m_fpGetPhysicalDeviceSurfaceSupportKHR;
Ian Elliottc11750d2015-10-30 13:24:12 -0600141 PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR m_fpGetPhysicalDeviceSurfaceCapabilitiesKHR;
142 PFN_vkGetPhysicalDeviceSurfaceFormatsKHR m_fpGetPhysicalDeviceSurfaceFormatsKHR;
143 PFN_vkGetPhysicalDeviceSurfacePresentModesKHR m_fpGetPhysicalDeviceSurfacePresentModesKHR;
Ian Elliott7e40db92015-08-21 15:09:33 -0600144 PFN_vkCreateSwapchainKHR m_fpCreateSwapchainKHR;
145 PFN_vkDestroySwapchainKHR m_fpDestroySwapchainKHR;
146 PFN_vkGetSwapchainImagesKHR m_fpGetSwapchainImagesKHR;
147 PFN_vkAcquireNextImageKHR m_fpAcquireNextImageKHR;
148 PFN_vkQueuePresentKHR m_fpQueuePresentKHR;
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700149 PFN_vkDestroySurfaceKHR m_fpDestroySurfaceKHR;
Ian Elliott7e40db92015-08-21 15:09:33 -0600150 uint32_t m_swapchainImageCount;
151 VkSwapchainKHR m_swap_chain;
152 SwapchainBuffers *m_buffers;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600153 VkFormat m_format;
Ian Elliott7e40db92015-08-21 15:09:33 -0600154 VkColorSpaceKHR m_color_space;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600155
156 uint32_t m_current_buffer;
Chia-I Wuf8693382015-04-16 22:02:10 +0800157
158 bool m_quit;
159 bool m_pause;
160
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600161 int m_width;
162 int m_height;
Chia-I Wuf8693382015-04-16 22:02:10 +0800163
164 std::list<VkTestImageRecord>::iterator m_display_image;
165
166 void Display();
Tony Barbourfeb61962015-09-21 15:17:33 -0600167#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800168 void HandleEvent(xcb_generic_event_t *event);
Tony Barbourfeb61962015-09-21 15:17:33 -0600169#endif
Chia-I Wuf8693382015-04-16 22:02:10 +0800170};
171
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600172#ifndef _WIN32
173
174#include <errno.h>
175
176int fopen_s(
177 FILE** pFile,
178 const char* filename,
179 const char* mode
180)
181{
182 if (!pFile || !filename || !mode) {
183 return EINVAL;
184 }
185
186 FILE* f = fopen(filename, mode);
187 if (! f) {
188 if (errno != 0) {
189 return errno;
190 } else {
191 return ENOENT;
192 }
193 }
194 *pFile = f;
195
196 return 0;
197}
198
199#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600200
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600201
202
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600203// Set up environment for GLSL compiler
204// Must be done once per process
205void TestEnvironment::SetUp()
206{
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600207 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600208 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800209
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600210 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600211}
212
213void TestEnvironment::TearDown()
214{
215 glslang::FinalizeProcess();
216}
217
Tony Barbour6918cd52015-04-09 12:58:51 -0600218VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600219 m_compile_options( 0 ),
220 m_num_shader_strings( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600221{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600222
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600223}
224
Tony Barbour6918cd52015-04-09 12:58:51 -0600225VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600226{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600227
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600228}
229
230// Define all the static elements
Cody Northropa3673cf2015-06-09 13:00:45 -0600231bool VkTestFramework::m_show_images = false;
232bool VkTestFramework::m_save_images = false;
233bool VkTestFramework::m_compare_images = false;
234bool VkTestFramework::m_use_glsl = false;
235bool VkTestFramework::m_canonicalize_spv = false;
236bool VkTestFramework::m_strip_spv = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600237bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour6918cd52015-04-09 12:58:51 -0600238int VkTestFramework::m_width = 0;
239int VkTestFramework::m_height = 0;
240std::list<VkTestImageRecord> VkTestFramework::m_images;
241std::list<VkTestImageRecord>::iterator VkTestFramework::m_display_image;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600242int m_display_image_idx = 0;
243
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600244bool VkTestFramework::optionMatch(const char* option, char* optionLine)
245{
246 if (strncmp(option, optionLine, strlen(option)) == 0)
247 return true;
248 else
249 return false;
250}
251
Tony Barbour6918cd52015-04-09 12:58:51 -0600252void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600253{
254 int i, n;
255
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600256 for (i=1, n=1; i< *argc; i++) {
257 if (optionMatch("--show-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600258 m_show_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600259 else if (optionMatch("--save-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600260 m_save_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600261 else if (optionMatch("--no-SPV", argv[i]))
262 m_use_glsl = true;
263 else if (optionMatch("--strip-SPV", argv[i]))
264 m_strip_spv = true;
265 else if (optionMatch("--canonicalize-SPV", argv[i]))
266 m_canonicalize_spv = true;
267 else if (optionMatch("--compare-images", argv[i]))
Tony Barbour247bf372014-10-30 14:29:04 -0600268 m_compare_images = true;
Tony Barbour247bf372014-10-30 14:29:04 -0600269
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600270 else if (optionMatch("--help", argv[i]) ||
271 optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700272 printf("\nOther options:\n");
273 printf("\t--show-images\n"
274 "\t\tDisplay test images in viewer after tests complete.\n");
275 printf("\t--save-images\n"
276 "\t\tSave tests images as ppm files in current working directory.\n"
277 "\t\tUsed to generate golden images for compare-images.\n");
278 printf("\t--compare-images\n"
279 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barboura98d3932014-12-11 09:52:49 -0700280 "\t\tAlso saves the generated test image in current working\n"
281 "\t\t\tdirectory but only if the image is different from the golden\n"
282 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
283 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700284 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600285 printf("\t--no-SPV\n"
286 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600287 printf("\t--strip-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600288 "\t\tStrip SPIR-V debug information (line numbers, names, etc).\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600289 printf("\t--canonicalize-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600290 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600291 exit(0);
292 } else {
293 printf("\nUnrecognized option: %s\n", argv[i]);
294 printf("\nUse --help or -h for option list.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700295 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700296 }
297
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600298 /*
299 * Since the above "consume" inputs, update argv
300 * so that it contains the trimmed list of args for glutInit
301 */
302
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600303 argv[n] = argv[i];
304 n++;
305 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600306}
307
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700308VkFormat VkTestFramework::GetFormat(VkInstance instance, vk_testing::Device *device)
309{
310 VkFormatProperties format_props;
311 if (!m_show_images)
312 {
313 vkGetPhysicalDeviceFormatProperties(device->phy().handle(), VK_FORMAT_B8G8R8A8_UNORM, &format_props);
314 if (format_props.linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ||
315 format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)
316 {
317 return VK_FORMAT_B8G8R8A8_UNORM;
318 }
319 vkGetPhysicalDeviceFormatProperties(device->phy().handle(), VK_FORMAT_R8G8B8A8_UNORM, &format_props);
320 if (format_props.linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ||
321 format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)
322 {
323 return VK_FORMAT_R8G8B8A8_UNORM;
324 }
325 printf("Error - device does not support VK_FORMAT_B8G8R8A8_UNORM nor VK_FORMAT_R8G8B8A8_UNORM - exiting\n");
326 exit(0);
327 }
328 else
329 {
330 /* To find which formats are presentable, you have to provide a surface to vkGetPhysicalDeviceSurfaceFormatsKHR */
331 /* To create a surface, you need a window. Use the present object to create a window, use that to create a */
332 /* KHR surface, and then find out what formats are presentable */
333 VkFormat presentFormat;
334 std::list<VkTestImageRecord> list;
335 VkTestImageRecord placeholder;
336 /* Use a dummy image record with non-zero area so the window will create on Windows */
337 placeholder.m_width = placeholder.m_height = 20;
338 list.push_back(placeholder);
339 TestFrameworkVkPresent vkPresent(*device);
340 vkPresent.InitPresentFramework(list, instance);
341 vkPresent.CreateMyWindow();
342 presentFormat = vkPresent.GetPresentFormat();
Tony Barboure1837292015-12-07 13:46:11 -0700343 vkPresent.DestroyMyWindow();
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700344 return presentFormat;
345 }
346}
347
Tony Barbour6918cd52015-04-09 12:58:51 -0600348void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600349{
350 string filename;
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600351 uint32_t x, y;
Tony Barbour6918cd52015-04-09 12:58:51 -0600352 VkImageObj displayImage(image->device());
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600353 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbour84d448c2015-04-02 14:02:33 -0600354
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800355 displayImage.init(image->extent().width, image->extent().height, image->format(), VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_LINEAR, reqs);
Tony Barbour84d448c2015-04-02 14:02:33 -0600356 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600357
358 filename.append(basename);
359 filename.append(".ppm");
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600360
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600361 const VkImageSubresource sr = {
Courtney Goeltzenleuchter908e7672015-10-21 17:00:51 -0600362 VK_IMAGE_ASPECT_COLOR_BIT, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600363 };
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600364 VkSubresourceLayout sr_layout;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600365
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600366 vkGetImageSubresourceLayout(image->device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600367
Tony Barbour84d448c2015-04-02 14:02:33 -0600368 char *ptr;
Chia-I Wu681d7a02015-07-03 13:44:34 +0800369 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600370 ptr += sr_layout.offset;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600371 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600372 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
373
374 file << "P6\n";
Tony Barbourfeb61962015-09-21 15:17:33 -0600375 file << displayImage.width() << " ";
Tony Barbour84d448c2015-04-02 14:02:33 -0600376 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600377 file << 255 << "\n";
378
Tony Barbour84d448c2015-04-02 14:02:33 -0600379 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700380 const int *row = (const int *) ptr;
381 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600382
Tony Barbourd1c35722015-04-16 15:59:00 -0600383 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700384 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600385 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700386 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
387 file.write((char *) &swapped, 3);
388 row++;
389 }
390 }
Tony Barbourd1c35722015-04-16 15:59:00 -0600391 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700392 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600393 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700394 file.write((char *) row, 3);
395 row++;
396 }
397 }
398 else {
399 printf("Unrecognized image format - will not write image files");
400 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600401 }
402
403 ptr += sr_layout.rowPitch;
404 }
405
406 file.close();
Chia-I Wu681d7a02015-07-03 13:44:34 +0800407 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600408}
409
Tony Barbour6918cd52015-04-09 12:58:51 -0600410void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour247bf372014-10-30 14:29:04 -0600411{
412
413 MagickWand *magick_wand_1;
414 MagickWand *magick_wand_2;
415 MagickWand *compare_wand;
416 MagickBooleanType status;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600417 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600418 double differenz;
419
Tony Barbour4ab45422014-12-10 17:00:20 -0700420 if (getenv("RENDERTEST_GOLDEN_DIR"))
421 {
422 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
423 }
424
Tony Barbour247bf372014-10-30 14:29:04 -0600425 MagickWandGenesis();
426 magick_wand_1=NewMagickWand();
427 sprintf(testimage,"%s.ppm",basename);
428 status=MagickReadImage(magick_wand_1,testimage);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600429 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour247bf372014-10-30 14:29:04 -0600430
431
432 MagickWandGenesis();
433 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700434 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600435 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600436 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour247bf372014-10-30 14:29:04 -0600437
Tony Barbour247bf372014-10-30 14:29:04 -0600438 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
439 if (differenz != 0.0)
440 {
441 char difference[256];
442
443 sprintf(difference,"%s-diff.ppm",basename);
444 status = MagickWriteImage(compare_wand, difference);
445 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
446 }
447 DestroyMagickWand(compare_wand);
448
449 DestroyMagickWand(magick_wand_1);
450 DestroyMagickWand(magick_wand_2);
451 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700452
453 if (differenz == 0.0)
454 {
455 /*
456 * If test image and golden image match, we do not need to
457 * keep around the test image.
458 */
459 remove(testimage);
460 }
Tony Barbour247bf372014-10-30 14:29:04 -0600461}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600462
Tony Barbour6918cd52015-04-09 12:58:51 -0600463void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600464{
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600465 VkSubresourceLayout sr_layout;
466 char *ptr;
467 VkTestImageRecord record;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600468 VkImageObj displayImage(image->device());
469 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
470
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800471 displayImage.init(image->extent().width, image->extent().height, image->format(), VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_LINEAR, reqs);
Cody Northropc9a69912015-06-18 17:05:15 -0600472
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600473 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600474
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600475 const VkImageSubresource sr = {
Courtney Goeltzenleuchter908e7672015-10-21 17:00:51 -0600476 VK_IMAGE_ASPECT_COLOR_BIT, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600477 };
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600478
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600479 vkGetImageSubresourceLayout(displayImage.device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600480
Chia-I Wu681d7a02015-07-03 13:44:34 +0800481 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600482 ptr += sr_layout.offset;
483
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600484 record.m_title.append(comment);
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600485 record.m_width = displayImage.width();
486 record.m_height = displayImage.height();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600487 // TODO: Need to make this more robust to handle different image formats
Tony-LunarG399dfca2015-05-19 14:08:26 -0600488 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600489 record.m_data = malloc(record.m_data_size);
490 memcpy(record.m_data, ptr, record.m_data_size);
491 m_images.push_back(record);
492 m_display_image = --m_images.end();
493
Chia-I Wu681d7a02015-07-03 13:44:34 +0800494 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600495}
496
Tony Barbour6918cd52015-04-09 12:58:51 -0600497void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600498{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600499 for (int32_t i = 0; i < images.size(); i++) {
500 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600501 }
502}
503
Tony Barbour6918cd52015-04-09 12:58:51 -0600504void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600505{
506 const ::testing::TestInfo* const test_info =
507 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600508 ostringstream filestream;
509 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600510
Tony Barbour247bf372014-10-30 14:29:04 -0600511 m_width = 40;
512
513 if (strcmp(test_info->name(), m_testName.c_str())) {
514 filestream << test_info->name();
515 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700516 m_frameNum = 2;
517 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600518 }
519 else {
520 filestream << test_info->name() << "-" << m_frameNum;
521 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700522 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600523 }
524
Tony Barbour247bf372014-10-30 14:29:04 -0600525 // ToDo - scrub string for bad characters
526
527 if (m_save_images || m_compare_images) {
528 WritePPM(filename.c_str(), image);
529 if (m_compare_images) {
530 Compare(filename.c_str(), image);
531 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600532 }
533
534 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600535 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600536 }
537}
538
Chia-I Wuf8693382015-04-16 22:02:10 +0800539TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
540 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700541 m_queue(*m_device.graphics_queues()[0]),
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800542 m_cmdpool(m_device, vk_testing::CommandPool::create_info(m_device.graphics_queue_node_index_)),
543 m_cmdbuf(m_device, vk_testing::CommandBuffer::create_info(m_cmdpool.handle()))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600544{
Tony Barbour96db8822015-02-25 12:28:39 -0700545 m_quit = false;
546 m_pause = false;
547 m_width = 0;
548 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600549}
550
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700551VkFormat TestFrameworkVkPresent::GetPresentFormat()
552{
553 uint32_t formatCount;
554 VkResult U_ASSERT_ONLY res;
555 VkSurfaceKHR surface;
556 VkFormat returnFormat;
557
558#ifdef _WIN32
Ian Elliotta8914ac2015-12-11 14:05:35 -0700559 VkWin32SurfaceCreateInfoKHR createInfo;
560 createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
561 createInfo.pNext = NULL;
562 createInfo.flags = 0;
Jon Ashburn88215af2015-12-24 17:08:01 -0700563 createInfo.hinstance = m_connection;
564 createInfo.hwnd = m_window;
Ian Elliotta8914ac2015-12-11 14:05:35 -0700565
566 res = vkCreateWin32SurfaceKHR(m_instance, &createInfo, NULL, &surface);
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700567#else // _WIN32
Ian Elliotta8914ac2015-12-11 14:05:35 -0700568 VkXcbSurfaceCreateInfoKHR createInfo;
569 createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
570 createInfo.pNext = NULL;
571 createInfo.flags = 0;
572 createInfo.connection = m_connection;
573 createInfo.window = m_window;
574
575 res = vkCreateXcbSurfaceKHR(m_instance, &createInfo, NULL, &surface);
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700576#endif // _WIN32
577 assert(res == VK_SUCCESS);
578
579 m_fpGetPhysicalDeviceSurfaceFormatsKHR(
580 m_device.phy().handle(),
581 surface,
582 &formatCount, NULL);
583 VkSurfaceFormatKHR *surfFormats =
584 (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
585 m_fpGetPhysicalDeviceSurfaceFormatsKHR(
586 m_device.phy().handle(),
587 surface,
588 &formatCount, surfFormats);
589
590 m_fpDestroySurfaceKHR(m_instance, surface, NULL);
591
592 returnFormat = surfFormats[0].format;
593 free(surfFormats);
594 return returnFormat;
595}
596
Tony Barbour6918cd52015-04-09 12:58:51 -0600597void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600598{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600599 VkResult U_ASSERT_ONLY err;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600600 vk_testing::Buffer buf;
601 void *dest_ptr;
602
Tony Barbour6a3faf02015-07-23 10:36:18 -0600603 VkSemaphore presentCompleteSemaphore;
604 VkSemaphoreCreateInfo presentCompleteSemaphoreCreateInfo = {};
605 presentCompleteSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
606 presentCompleteSemaphoreCreateInfo.pNext = NULL;
607 presentCompleteSemaphoreCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
608
609
610 err = vkCreateSemaphore(m_device.handle(),
611 &presentCompleteSemaphoreCreateInfo,
Chia-I Wuf7458c52015-10-26 21:10:41 +0800612 NULL, &presentCompleteSemaphore);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600613 assert(!err);
614
615 // Get the index of the next available swapchain image:
Ian Elliott7e40db92015-08-21 15:09:33 -0600616 err = m_fpAcquireNextImageKHR(m_device.handle(), m_swap_chain,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600617 UINT64_MAX,
618 presentCompleteSemaphore,
Ian Elliottc11750d2015-10-30 13:24:12 -0600619 VK_NULL_HANDLE,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600620 &m_current_buffer);
Ian Elliott7e40db92015-08-21 15:09:33 -0600621 // TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
Tony Barbour6a3faf02015-07-23 10:36:18 -0600622 // return codes
623 assert(!err);
624
Tony-LunarG399dfca2015-05-19 14:08:26 -0600625 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Cody Northrop7fb43862015-06-22 14:56:14 -0600626 buf.init_as_src(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800627 dest_ptr = buf.memory().map();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600628 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800629 buf.memory().unmap();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600630
631 m_cmdbuf.begin();
Tony Barbourbd094ce2015-10-23 11:00:15 -0600632 VkImageMemoryBarrier memoryBarrier = {};
633 memoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
634 memoryBarrier.pNext = NULL;
Tony Barbourd800bbd2015-11-05 10:54:44 -0700635 memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
Chia-I Wua4594202015-10-27 19:54:37 +0800636 memoryBarrier.dstAccessMask = 0;
Ian Elliott1dcd1092015-11-17 17:29:40 -0700637 memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800638 memoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600639 memoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800640 memoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600641 memoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
642 memoryBarrier.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800643 memoryBarrier.subresourceRange.levelCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600644 memoryBarrier.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800645 memoryBarrier.subresourceRange.layerCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600646 memoryBarrier.image = m_buffers[m_current_buffer].image;
647 VkImageMemoryBarrier *pmemory_barrier = &memoryBarrier;
Chia-I Wu89d0f942015-10-31 00:31:16 +0800648 vkCmdPipelineBarrier(m_cmdbuf.handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
Chia-I Wu53534662015-10-26 17:08:33 +0800649 0, 1, (const void * const*)&pmemory_barrier);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600650
651 VkBufferImageCopy region = {};
Tony Barbourd800bbd2015-11-05 10:54:44 -0700652 region.bufferRowLength = m_display_image->m_width;
653 region.bufferImageHeight = m_display_image->m_height;
654 region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
655 region.imageSubresource.layerCount = 1;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600656 region.imageExtent.height = m_display_image->m_height;
657 region.imageExtent.width = m_display_image->m_width;
658 region.imageExtent.depth = 1;
659
Chia-I Wube2b9172015-07-03 11:49:42 +0800660 vkCmdCopyBufferToImage(m_cmdbuf.handle(),
Chia-I Wu681d7a02015-07-03 13:44:34 +0800661 buf.handle(),
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800662 m_buffers[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600663 1, &region);
Tony Barbourbd094ce2015-10-23 11:00:15 -0600664
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800665 memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
Ian Elliott1dcd1092015-11-17 17:29:40 -0700666 memoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
Chia-I Wu89d0f942015-10-31 00:31:16 +0800667 vkCmdPipelineBarrier(m_cmdbuf.handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
Chia-I Wu53534662015-10-26 17:08:33 +0800668 0, 1, (const void * const*)&pmemory_barrier);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600669 m_cmdbuf.end();
670
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800671 VkCommandBuffer cmdBufs[1];
Chia-I Wube2b9172015-07-03 11:49:42 +0800672 cmdBufs[0] = m_cmdbuf.handle();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600673
Chia-I Wua690b412015-10-29 22:01:53 +0800674 // Wait for the present complete semaphore to be signaled to ensure
675 // that the image won't be rendered to until the presentation
676 // engine has fully released ownership to the application, and it is
677 // okay to render to the image.
Tony Barbour67e99152015-07-10 14:10:27 -0600678 VkFence nullFence = { VK_NULL_HANDLE };
Jon Ashburn7f9716c2015-12-30 16:42:50 -0700679 VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600680 VkSubmitInfo submit_info;
Chia-I Wuf9be13c2015-10-26 20:37:06 +0800681 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
682 submit_info.pNext = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +0800683 submit_info.waitSemaphoreCount = 1;
Jon Ashburn7f9716c2015-12-30 16:42:50 -0700684 submit_info.pWaitSemaphores = &presentCompleteSemaphore;
685 submit_info.pWaitDstStageMask = &pipe_stage_flags;
Chia-I Wud50a7d72015-10-26 20:48:51 +0800686 submit_info.commandBufferCount = 1;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600687 submit_info.pCommandBuffers = cmdBufs;
Chia-I Wud50a7d72015-10-26 20:48:51 +0800688 submit_info.signalSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600689 submit_info.pSignalSemaphores = NULL;
690
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -0600691 vkQueueSubmit(m_queue.handle(), 1, &submit_info, nullFence);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600692 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700693
Chia-I Wuf7458c52015-10-26 21:10:41 +0800694 vkDestroySemaphore(m_device.handle(), presentCompleteSemaphore, NULL);
Chia-I Wua690b412015-10-29 22:01:53 +0800695
Ian Elliott7e40db92015-08-21 15:09:33 -0600696 VkPresentInfoKHR present = {};
697 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600698 present.pNext = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600699 present.swapchainCount = 1;
Ian Elliottc11750d2015-10-30 13:24:12 -0600700 present.pSwapchains = & m_swap_chain;
701 present.pImageIndices = &m_current_buffer;
Tony Barbour96db8822015-02-25 12:28:39 -0700702
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600703#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800704 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700705 XCB_PROP_MODE_REPLACE,
706 m_window,
707 XCB_ATOM_WM_NAME,
708 XCB_ATOM_STRING,
709 8,
710 m_display_image->m_title.size(),
711 m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600712#endif
Jon Ashburn07daee72015-05-21 18:13:33 -0600713
Ian Elliott7e40db92015-08-21 15:09:33 -0600714 err = m_fpQueuePresentKHR(m_queue.handle(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700715 assert(!err);
716
717 m_queue.wait();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600718 m_current_buffer = (m_current_buffer + 1) % 2;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600719}
720
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600721#ifdef _WIN32
Tony-LunarG399dfca2015-05-19 14:08:26 -0600722# define PREVIOUSLY_DOWN 1<<29
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600723// MS-Windows event handling function:
724LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
725 UINT uMsg,
726 WPARAM wParam,
727 LPARAM lParam)
728{
729
730 switch(uMsg)
731 {
732 case WM_CLOSE:
733 PostQuitMessage(0);
734 break;
735
736 case WM_PAINT:
737 {
738 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
739 if (me) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600740 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600741 me->Display();
742 }
743 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600744 break;
745
746 case WM_KEYDOWN:
747 {
748 if (lParam & (PREVIOUSLY_DOWN)){
749 break;
750 }
751 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
752 // the window, we put the this pointer into the window's user data so we could get it back now
753 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
754 switch (wParam)
755 {
756 case VK_ESCAPE: me->m_quit = true;
757 break;
758
759 case VK_LEFT: // left arrow key
760 if (me->m_display_image == me->m_images.begin()) {
761 me->m_display_image = --me->m_images.end();
762 }
763 else {
764 --me->m_display_image;
765 }
766 break;
767
768 case VK_RIGHT: // right arrow key
769 ++me->m_display_image;
770 if (me->m_display_image == me->m_images.end()) {
771 me->m_display_image = me->m_images.begin();
772 }
773 break;
774
775 default:
776 break;
777 }
778 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
779 me->Display();
780 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600781 }
782 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
783}
784
785void TestFrameworkVkPresent::Run()
786{
787 MSG msg; // message
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600788
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600789 /* main message loop*/
Tony-LunarG399dfca2015-05-19 14:08:26 -0600790 while(! m_quit) {
791 GetMessage(&msg, m_window, 0, 0);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600792 if (msg.message == WM_QUIT) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600793 m_quit = true; //if found, quit app
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600794 } else {
795 /* Translate and dispatch to event queue*/
796 TranslateMessage(&msg);
797 DispatchMessage(&msg);
798 }
799 }
800}
801
802#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600803void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600804{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600805 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700806 switch (event_code) {
807 case XCB_EXPOSE:
808 Display(); // TODO: handle resize
809 break;
810 case XCB_CLIENT_MESSAGE:
811 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
812 (m_atom_wm_delete_window)->atom) {
813 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600814 }
815 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700816 case XCB_KEY_RELEASE:
817 {
818 const xcb_key_release_event_t *key =
819 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600820
Tony Barbour96db8822015-02-25 12:28:39 -0700821 switch (key->detail) {
822 case 0x9: // Escape
823 m_quit = true;
824 break;
825 case 0x71: // left arrow key
826 if (m_display_image == m_images.begin()) {
827 m_display_image = --m_images.end();
828 } else {
829 --m_display_image;
830 }
831 break;
832 case 0x72: // right arrow key
833 ++m_display_image;
834 if (m_display_image == m_images.end()) {
835 m_display_image = m_images.begin();
836 }
837 break;
838 case 0x41:
839 m_pause = !m_pause;
840 break;
841 }
842 Display();
843 }
844 break;
845 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600846 break;
847 }
Tony Barbour96db8822015-02-25 12:28:39 -0700848}
849
Tony Barbour6918cd52015-04-09 12:58:51 -0600850void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700851{
Chia-I Wuf8693382015-04-16 22:02:10 +0800852 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700853
854 while (! m_quit) {
855 xcb_generic_event_t *event;
856
857 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800858 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700859 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800860 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700861 }
862 if (event) {
863 HandleEvent(event);
864 free(event);
865 }
866 }
867}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600868#endif // _WIN32
Tony Barbour96db8822015-02-25 12:28:39 -0700869
Ian Elliott7e40db92015-08-21 15:09:33 -0600870void TestFrameworkVkPresent::CreateSwapchain()
Tony Barbour96db8822015-02-25 12:28:39 -0700871{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600872 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700873
Tony-LunarG399dfca2015-05-19 14:08:26 -0600874 m_display_image = m_images.begin();
875 m_current_buffer = 0;
876
Ian Elliottc11750d2015-10-30 13:24:12 -0600877 // Create the WSI surface:
Ian Elliott1a3845b2015-07-06 14:33:04 -0600878#ifdef _WIN32
Ian Elliotta8914ac2015-12-11 14:05:35 -0700879 VkWin32SurfaceCreateInfoKHR createInfo;
880 createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
881 createInfo.pNext = NULL;
882 createInfo.flags = 0;
Jon Ashburn88215af2015-12-24 17:08:01 -0700883 createInfo.hinstance = m_connection;
884 createInfo.hwnd = m_window;
Ian Elliotta8914ac2015-12-11 14:05:35 -0700885
886 err = vkCreateWin32SurfaceKHR(m_instance, &createInfo, NULL, &m_surface);
Ian Elliott1a3845b2015-07-06 14:33:04 -0600887#else // _WIN32
Ian Elliotta8914ac2015-12-11 14:05:35 -0700888 VkXcbSurfaceCreateInfoKHR createInfo;
889 createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
890 createInfo.pNext = NULL;
891 createInfo.flags = 0;
892 createInfo.connection = m_connection;
893 createInfo.window = m_window;
894
895 err = vkCreateXcbSurfaceKHR(m_instance, &createInfo, NULL, &m_surface);
Ian Elliott1a3845b2015-07-06 14:33:04 -0600896#endif // _WIN32
Ian Elliottc11750d2015-10-30 13:24:12 -0600897 assert(!err);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600898
899 // Iterate over each queue to learn whether it supports presenting to WSI:
900 VkBool32 supportsPresent;
901 m_present_queue_node_index = UINT32_MAX;
902 std::vector<vk_testing::Queue *> queues = m_device.graphics_queues();
903 for (int i=0; i < queues.size(); i++)
904 {
905 int family_index = queues[i]->get_family_index();
Ian Elliott7e40db92015-08-21 15:09:33 -0600906 m_fpGetPhysicalDeviceSurfaceSupportKHR(m_device.phy().handle(),
Tony Barbour6a3faf02015-07-23 10:36:18 -0600907 family_index,
Ian Elliottc11750d2015-10-30 13:24:12 -0600908 m_surface,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600909 &supportsPresent);
910 if (supportsPresent) {
911 m_present_queue_node_index = family_index;
912 }
913 }
914
915 assert(m_present_queue_node_index != UINT32_MAX);
916
917
918 // Get the list of VkFormat's that are supported:
Ian Elliott8b139792015-08-07 11:51:12 -0600919 uint32_t formatCount;
Ian Elliottc11750d2015-10-30 13:24:12 -0600920 err = m_fpGetPhysicalDeviceSurfaceFormatsKHR(m_device.phy().handle(),
921 m_surface,
Ian Elliott8b139792015-08-07 11:51:12 -0600922 &formatCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600923 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600924 VkSurfaceFormatKHR *surfFormats =
925 (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
Ian Elliottc11750d2015-10-30 13:24:12 -0600926 err = m_fpGetPhysicalDeviceSurfaceFormatsKHR(m_device.phy().handle(),
927 m_surface,
Ian Elliott8b139792015-08-07 11:51:12 -0600928 &formatCount, surfFormats);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600929 assert(!err);
930 // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
931 // the surface has no preferred format. Otherwise, at least one
932 // supported format will be returned.
Tony Barbour6a3faf02015-07-23 10:36:18 -0600933 if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED)
934 {
935 m_format = VK_FORMAT_B8G8R8A8_UNORM;
936 }
937 else
938 {
939 assert(formatCount >= 1);
940 m_format = surfFormats[0].format;
941 }
Ian Elliott8b139792015-08-07 11:51:12 -0600942 m_color_space = surfFormats[0].colorSpace;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600943
Ian Elliottc11750d2015-10-30 13:24:12 -0600944 // Check the surface capabilities and formats
945 VkSurfaceCapabilitiesKHR surfCapabilities;
946 err = m_fpGetPhysicalDeviceSurfaceCapabilitiesKHR(m_device.phy().handle(),
947 m_surface,
948 &surfCapabilities);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600949 assert(!err);
950
Ian Elliott8b139792015-08-07 11:51:12 -0600951 uint32_t presentModeCount;
Ian Elliottc11750d2015-10-30 13:24:12 -0600952 err = m_fpGetPhysicalDeviceSurfacePresentModesKHR(m_device.phy().handle(),
953 m_surface,
Ian Elliott8b139792015-08-07 11:51:12 -0600954 &presentModeCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600955 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600956 VkPresentModeKHR *presentModes =
957 (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
Ian Elliott8b139792015-08-07 11:51:12 -0600958 assert(presentModes);
Ian Elliottc11750d2015-10-30 13:24:12 -0600959 err = m_fpGetPhysicalDeviceSurfacePresentModesKHR(m_device.phy().handle(),
960 m_surface,
Ian Elliott8b139792015-08-07 11:51:12 -0600961 &presentModeCount, presentModes);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600962 assert(!err);
963
Ian Elliott7e40db92015-08-21 15:09:33 -0600964 VkExtent2D swapchainExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600965 // width and height are either both -1, or both not -1.
Ian Elliottc11750d2015-10-30 13:24:12 -0600966 if (surfCapabilities.currentExtent.width == -1)
Tony Barbour6a3faf02015-07-23 10:36:18 -0600967 {
968 // If the surface size is undefined, the size is set to
969 // the size of the images requested.
Ian Elliott7e40db92015-08-21 15:09:33 -0600970 swapchainExtent.width = m_width;
971 swapchainExtent.height = m_height;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600972 }
973 else
974 {
975 // If the surface size is defined, the swap chain size must match
Ian Elliottc11750d2015-10-30 13:24:12 -0600976 swapchainExtent = surfCapabilities.currentExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600977 }
978
979 // If mailbox mode is available, use it, as is the lowest-latency non-
Ian Elliottae0e8242015-08-10 13:20:49 -0600980 // tearing mode. If not, try IMMEDIATE which will usually be available,
981 // and is fastest (though it tears). If not, fall back to FIFO which is
982 // always available.
Ian Elliott7e40db92015-08-21 15:09:33 -0600983 VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600984 for (size_t i = 0; i < presentModeCount; i++) {
Ian Elliott7e40db92015-08-21 15:09:33 -0600985 if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
986 swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600987 break;
988 }
Ian Elliott7e40db92015-08-21 15:09:33 -0600989 if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) &&
990 (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
991 swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
Ian Elliottae0e8242015-08-10 13:20:49 -0600992 }
Tony Barbour6a3faf02015-07-23 10:36:18 -0600993 }
994
995 // Determine the number of VkImage's to use in the swap chain (we desire to
996 // own only 1 image at a time, besides the images being displayed and
997 // queued for display):
Ian Elliottc11750d2015-10-30 13:24:12 -0600998 uint32_t desiredNumberOfSwapchainImages = surfCapabilities.minImageCount + 1;
999 if ((surfCapabilities.maxImageCount > 0) &&
1000 (desiredNumberOfSwapchainImages > surfCapabilities.maxImageCount))
Tony Barbour6a3faf02015-07-23 10:36:18 -06001001 {
1002 // Application must settle for fewer images than desired:
Ian Elliottc11750d2015-10-30 13:24:12 -06001003 desiredNumberOfSwapchainImages = surfCapabilities.maxImageCount;
Tony Barbour6a3faf02015-07-23 10:36:18 -06001004 }
1005
Ian Elliottc11750d2015-10-30 13:24:12 -06001006 VkSurfaceTransformFlagsKHR preTransform;
Ian Elliotta8914ac2015-12-11 14:05:35 -07001007 if (surfCapabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) {
1008 preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -06001009 } else {
Ian Elliottc11750d2015-10-30 13:24:12 -06001010 preTransform = surfCapabilities.currentTransform;
Tony Barbour6a3faf02015-07-23 10:36:18 -06001011 }
Ian Elliott1a3845b2015-07-06 14:33:04 -06001012
Cody Northropdf5b0922015-08-28 16:22:48 -06001013 // We want to blit to the swap chain, ensure the driver supports it. Color is always supported, per WSI spec.
Ian Elliottc11750d2015-10-30 13:24:12 -06001014 assert((surfCapabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) != 0);
Cody Northropdf5b0922015-08-28 16:22:48 -06001015
Ian Elliott7e40db92015-08-21 15:09:33 -06001016 VkSwapchainCreateInfoKHR swap_chain = {};
Ian Elliotta257eea2015-09-22 10:20:23 -06001017 swap_chain.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
Ian Elliott1a3845b2015-07-06 14:33:04 -06001018 swap_chain.pNext = NULL;
Ian Elliottc11750d2015-10-30 13:24:12 -06001019 swap_chain.surface = m_surface;
Ian Elliott7e40db92015-08-21 15:09:33 -06001020 swap_chain.minImageCount = desiredNumberOfSwapchainImages;
Tony Barbour6a3faf02015-07-23 10:36:18 -06001021 swap_chain.imageFormat = m_format;
Ian Elliott8b139792015-08-07 11:51:12 -06001022 swap_chain.imageColorSpace = m_color_space;
Ian Elliott7e40db92015-08-21 15:09:33 -06001023 swap_chain.imageExtent.width = swapchainExtent.width;
1024 swap_chain.imageExtent.height = swapchainExtent.height;
Ian Elliottc11750d2015-10-30 13:24:12 -06001025 swap_chain.imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1026 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1027 swap_chain.preTransform = (VkSurfaceTransformFlagBitsKHR) preTransform;
1028 swap_chain.imageArrayLayers = 1;
1029 swap_chain.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
1030 swap_chain.queueFamilyIndexCount = 0;
Ian Elliott8b139792015-08-07 11:51:12 -06001031 swap_chain.pQueueFamilyIndices = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -06001032 swap_chain.presentMode = swapchainPresentMode;
Chia-I Wue2fc5522015-10-26 20:04:44 +08001033 swap_chain.oldSwapchain = VK_NULL_HANDLE;
Tony Barbour6a3faf02015-07-23 10:36:18 -06001034 swap_chain.clipped = true;
1035
1036 uint32_t i;
Chia-I Wuf8693382015-04-16 22:02:10 +08001037
Ian Elliottc11750d2015-10-30 13:24:12 -06001038 err = m_fpCreateSwapchainKHR(m_device.handle(), &swap_chain, NULL, &m_swap_chain);
Chia-I Wuf8693382015-04-16 22:02:10 +08001039 assert(!err);
1040
Ian Elliott7e40db92015-08-21 15:09:33 -06001041 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
1042 &m_swapchainImageCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -06001043 assert(!err);
1044
Ian Elliott7e40db92015-08-21 15:09:33 -06001045 VkImage* swapchainImages = (VkImage*)malloc(m_swapchainImageCount * sizeof(VkImage));
1046 assert(swapchainImages);
1047 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
1048 &m_swapchainImageCount, swapchainImages);
Tony Barbour6a3faf02015-07-23 10:36:18 -06001049 assert(!err);
1050
Ian Elliott7e40db92015-08-21 15:09:33 -06001051 m_buffers = (SwapchainBuffers*)malloc(sizeof(SwapchainBuffers)*m_swapchainImageCount);
Tony Barbour6a3faf02015-07-23 10:36:18 -06001052 assert(m_buffers);
1053
Ian Elliott7e40db92015-08-21 15:09:33 -06001054 for (i = 0; i < m_swapchainImageCount; i++) {
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -06001055 VkImageViewCreateInfo color_image_view = {};
1056 color_image_view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
1057 color_image_view.pNext = NULL;
1058 color_image_view.format = m_format;
Tony Barbourd800bbd2015-11-05 10:54:44 -07001059 color_image_view.components.r = VK_COMPONENT_SWIZZLE_R;
1060 color_image_view.components.g = VK_COMPONENT_SWIZZLE_G;
1061 color_image_view.components.b = VK_COMPONENT_SWIZZLE_B;
1062 color_image_view.components.a = VK_COMPONENT_SWIZZLE_A;
Courtney Goeltzenleuchterba724512015-09-10 17:58:54 -06001063 color_image_view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -06001064 color_image_view.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001065 color_image_view.subresourceRange.levelCount = 1;
Courtney Goeltzenleuchter4a261892015-09-10 16:38:41 -06001066 color_image_view.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001067 color_image_view.subresourceRange.layerCount = 1;
Tony Barbourd800bbd2015-11-05 10:54:44 -07001068 color_image_view.viewType = VK_IMAGE_VIEW_TYPE_2D;
1069 color_image_view.flags = 0;
Tony Barbour6a3faf02015-07-23 10:36:18 -06001070
Ian Elliott7e40db92015-08-21 15:09:33 -06001071 m_buffers[i].image = swapchainImages[i];
Tony Barbour6a3faf02015-07-23 10:36:18 -06001072
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -06001073 color_image_view.image = m_buffers[i].image;
1074 err = vkCreateImageView(m_device.handle(),
Chia-I Wuf7458c52015-10-26 21:10:41 +08001075 &color_image_view, NULL, &m_buffers[i].view);
Tony Barbour6a3faf02015-07-23 10:36:18 -06001076 assert(!err);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001077
1078 /* Set image layout to PRESENT_SOURCE_KHR so that before the copy, it can be set to */
1079 /* TRANSFER_DESTINATION_OPTIMAL */
1080 SetImageLayout(m_buffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT,
Ian Elliott1dcd1092015-11-17 17:29:40 -07001081 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001082
Tony Barbour6a3faf02015-07-23 10:36:18 -06001083 }
Tony Barbour96db8822015-02-25 12:28:39 -07001084}
Tony Barbourbd094ce2015-10-23 11:00:15 -06001085void TestFrameworkVkPresent::SetImageLayout(VkImage image, VkImageAspectFlags aspectMask,
1086 VkImageLayout old_image_layout, VkImageLayout new_image_layout)
1087{
1088 VkResult U_ASSERT_ONLY err;
1089
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001090 VkCommandBufferBeginInfo cmd_buf_info = {};
1091 cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001092 cmd_buf_info.pNext = NULL;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001093 cmd_buf_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001094 cmd_buf_info.renderPass = { VK_NULL_HANDLE };
1095 cmd_buf_info.subpass = 0;
1096 cmd_buf_info.framebuffer = { VK_NULL_HANDLE };
Chia-I Wub8d47ae2015-11-11 10:18:12 +08001097 cmd_buf_info.occlusionQueryEnable = VK_FALSE;
1098 cmd_buf_info.queryFlags = 0;
1099 cmd_buf_info.pipelineStatistics = 0;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001100
1101 err = vkBeginCommandBuffer(m_cmdbuf.handle(), &cmd_buf_info);
1102 assert(!err);
1103
1104 VkImageMemoryBarrier image_memory_barrier = {};
1105 image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
1106 image_memory_barrier.pNext = NULL;
Chia-I Wua4594202015-10-27 19:54:37 +08001107 image_memory_barrier.srcAccessMask = 0;
1108 image_memory_barrier.dstAccessMask = 0;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001109 image_memory_barrier.oldLayout = old_image_layout;
1110 image_memory_barrier.newLayout = new_image_layout;
1111 image_memory_barrier.image = image;
1112 image_memory_barrier.subresourceRange.aspectMask = aspectMask;
1113 image_memory_barrier.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001114 image_memory_barrier.subresourceRange.levelCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001115 image_memory_barrier.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001116 image_memory_barrier.subresourceRange.layerCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001117
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001118 if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
Tony Barbourbd094ce2015-10-23 11:00:15 -06001119 /* Make sure anything that was copying from this image has completed */
Chia-I Wua4594202015-10-27 19:54:37 +08001120 image_memory_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001121 }
1122
1123 if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
1124 /* Make sure any Copy or CPU writes to image are flushed */
Chia-I Wua4594202015-10-27 19:54:37 +08001125 image_memory_barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001126 }
1127
1128 VkImageMemoryBarrier *pmemory_barrier = &image_memory_barrier;
1129
1130 VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1131 VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1132
Chia-I Wu53534662015-10-26 17:08:33 +08001133 vkCmdPipelineBarrier(m_cmdbuf.handle(), src_stages, dest_stages, 0, 1, (const void * const*)&pmemory_barrier);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001134
1135 err = vkEndCommandBuffer(m_cmdbuf.handle());
1136 assert(!err);
1137
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001138 const VkCommandBuffer cmd_bufs[] = { m_cmdbuf.handle() };
Tony Barbourbd094ce2015-10-23 11:00:15 -06001139 VkFence nullFence = { VK_NULL_HANDLE };
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001140 VkSubmitInfo submit_info;
Chia-I Wuf9be13c2015-10-26 20:37:06 +08001141 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1142 submit_info.pNext = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001143 submit_info.waitSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001144 submit_info.pWaitSemaphores = NULL;
Jon Ashburn7f9716c2015-12-30 16:42:50 -07001145 submit_info.pWaitDstStageMask = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001146 submit_info.commandBufferCount = 1;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001147 submit_info.pCommandBuffers = cmd_bufs;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001148 submit_info.signalSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001149 submit_info.pSignalSemaphores = NULL;
1150
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -06001151 err = vkQueueSubmit(m_queue.handle(), 1, &submit_info, nullFence);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001152 assert(!err);
1153
1154 err = vkQueueWaitIdle(m_queue.handle());
1155 assert(!err);
1156
1157}
Tony Barbour96db8822015-02-25 12:28:39 -07001158
Jon Ashburn07daee72015-05-21 18:13:33 -06001159void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -07001160{
Ian Elliottc11750d2015-10-30 13:24:12 -06001161 m_instance = inst;
Ian Elliott7e40db92015-08-21 15:09:33 -06001162 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceSupportKHR);
Ian Elliottc11750d2015-10-30 13:24:12 -06001163 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceCapabilitiesKHR);
1164 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceFormatsKHR);
1165 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfacePresentModesKHR);
Tony Barbour2d6d54e2015-12-03 16:05:11 -07001166 GET_INSTANCE_PROC_ADDR(inst, DestroySurfaceKHR);
Ian Elliott7e40db92015-08-21 15:09:33 -06001167 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1168 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1169 GET_DEVICE_PROC_ADDR(m_device.handle(), DestroySwapchainKHR);
1170 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSwapchainImagesKHR);
1171 GET_DEVICE_PROC_ADDR(m_device.handle(), AcquireNextImageKHR);
1172 GET_DEVICE_PROC_ADDR(m_device.handle(), QueuePresentKHR);
Jon Ashburn07daee72015-05-21 18:13:33 -06001173
Tony Barbour96db8822015-02-25 12:28:39 -07001174 m_images = imagesIn;
1175}
1176
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001177#ifdef _WIN32
1178void TestFrameworkVkPresent::CreateMyWindow()
1179{
1180 WNDCLASSEX win_class;
1181 // const ::testing::TestInfo* const test_info =
1182 // ::testing::UnitTest::GetInstance()->current_test_info();
1183 m_connection = GetModuleHandle(NULL);
1184
1185 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1186 it != m_images.end(); it++) {
1187 if (m_width < it->m_width)
1188 m_width = it->m_width;
1189 if (m_height < it->m_height)
1190 m_height = it->m_height;
1191 }
1192 // Initialize the window class structure:
1193 win_class.cbSize = sizeof(WNDCLASSEX);
1194 win_class.style = CS_HREDRAW | CS_VREDRAW;
1195 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
1196 win_class.cbClsExtra = 0;
1197 win_class.cbWndExtra = 0;
1198 win_class.hInstance = m_connection; // hInstance
1199 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
1200 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
1201 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
1202 win_class.lpszMenuName = NULL;
1203 win_class.lpszClassName = "Test";
1204 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
1205 // Register window class:
1206 if (!RegisterClassEx(&win_class)) {
1207 // It didn't work, so try to give a useful error:
1208 printf("Unexpected error trying to start the application!\n");
1209 fflush(stdout);
1210 exit(1);
1211 }
1212 // Create window with the registered class:
Cody Northrop39582252015-08-05 15:39:31 -06001213 RECT wr = { 0, 0, m_width, m_height };
1214 AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001215 m_window = CreateWindowEx(0,
1216 "Test", // class name
1217 "Test", // app name
1218 WS_OVERLAPPEDWINDOW | // window style
1219 WS_VISIBLE |
1220 WS_SYSMENU,
1221 100,100, // x/y coords
Cody Northrop39582252015-08-05 15:39:31 -06001222 wr.right - wr.left, // width
1223 wr.bottom - wr.top, // height
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001224 NULL, // handle to parent
1225 NULL, // handle to menu
1226 m_connection, // hInstance
1227 NULL); // no extra parameters
1228
1229 if (!m_window) {
1230 // It didn't work, so try to give a useful error:
1231 DWORD error = GetLastError();
1232 char message[120];
1233 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
1234 MessageBox(NULL, message, "Error", MB_OK);
1235 exit(1);
1236 }
Tony-LunarG399dfca2015-05-19 14:08:26 -06001237 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
1238 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001239}
1240#else
Tony Barbour6918cd52015-04-09 12:58:51 -06001241void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -07001242{
Chia-I Wuf8693382015-04-16 22:02:10 +08001243 const xcb_setup_t *setup;
1244 xcb_screen_iterator_t iter;
1245 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -07001246 uint32_t value_mask, value_list[32];
1247
Chia-I Wuf8693382015-04-16 22:02:10 +08001248 m_connection = xcb_connect(NULL, &scr);
1249
1250 setup = xcb_get_setup(m_connection);
1251 iter = xcb_setup_roots_iterator(setup);
1252 while (scr-- > 0)
1253 xcb_screen_next(&iter);
1254
1255 m_screen = iter.data;
1256
1257 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1258 it != m_images.end(); it++) {
1259 if (m_width < it->m_width)
1260 m_width = it->m_width;
1261 if (m_height < it->m_height)
1262 m_height = it->m_height;
1263 }
1264
1265 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -07001266
1267 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +08001268 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -07001269 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
1270 XCB_EVENT_MASK_EXPOSURE |
1271 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
1272
Chia-I Wuf8693382015-04-16 22:02:10 +08001273 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -07001274 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001275 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -07001276 0, 0, m_width, m_height, 0,
1277 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001278 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -07001279 value_mask, value_list);
1280
1281 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +08001282 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -07001283 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +08001284 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001285
Chia-I Wuf8693382015-04-16 22:02:10 +08001286 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
1287 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001288
Chia-I Wuf8693382015-04-16 22:02:10 +08001289 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -07001290 m_window, (*reply).atom, 4, 32, 1,
1291 &(*m_atom_wm_delete_window).atom);
1292 free(reply);
1293
Chia-I Wuf8693382015-04-16 22:02:10 +08001294 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -07001295}
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001296#endif
Tony Barbour96db8822015-02-25 12:28:39 -07001297
Tony Barbour6918cd52015-04-09 12:58:51 -06001298void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -07001299{
Ian Elliottc11750d2015-10-30 13:24:12 -06001300 m_fpDestroySwapchainKHR(m_device.handle(), m_swap_chain, NULL);
Tony Barbour9226a822015-10-23 10:58:56 -06001301
1302 for (uint32_t i = 0; i < m_swapchainImageCount; i++) {
Chia-I Wuf7458c52015-10-26 21:10:41 +08001303 vkDestroyImageView(m_device.handle(), m_buffers[i].view, NULL);
Tony Barbour9226a822015-10-23 10:58:56 -06001304 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001305#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +08001306 xcb_destroy_window(m_connection, m_window);
1307 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001308#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001309}
1310
Tony Barboure1837292015-12-07 13:46:11 -07001311void TestFrameworkVkPresent::DestroyMyWindow()
Tony Barbour2d6d54e2015-12-03 16:05:11 -07001312{
1313#ifndef _WIN32
1314 xcb_destroy_window(m_connection, m_window);
1315 xcb_disconnect(m_connection);
1316#else
1317 DestroyWindow(m_window);
1318#endif
1319}
1320
Tony Barbour6918cd52015-04-09 12:58:51 -06001321void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001322{
1323 if (m_images.size() == 0) return;
1324
Chia-I Wuf8693382015-04-16 22:02:10 +08001325 vk_testing::Environment env;
1326 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -07001327 {
Chia-I Wuf8693382015-04-16 22:02:10 +08001328 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -07001329
Jon Ashburn07daee72015-05-21 18:13:33 -06001330 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001331 vkPresent.CreateMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -06001332 vkPresent.CreateSwapchain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001333 vkPresent.Run();
1334 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -07001335 }
Chia-I Wuf8693382015-04-16 22:02:10 +08001336 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001337}
1338
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001339//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001340// These are the default resources for TBuiltInResources, used for both
1341// - parsing this string for the case where the user didn't supply one
1342// - dumping out a template for user construction of a config file
1343//
1344static const char* DefaultConfig =
1345 "MaxLights 32\n"
1346 "MaxClipPlanes 6\n"
1347 "MaxTextureUnits 32\n"
1348 "MaxTextureCoords 32\n"
1349 "MaxVertexAttribs 64\n"
1350 "MaxVertexUniformComponents 4096\n"
1351 "MaxVaryingFloats 64\n"
1352 "MaxVertexTextureImageUnits 32\n"
1353 "MaxCombinedTextureImageUnits 80\n"
1354 "MaxTextureImageUnits 32\n"
1355 "MaxFragmentUniformComponents 4096\n"
1356 "MaxDrawBuffers 32\n"
1357 "MaxVertexUniformVectors 128\n"
1358 "MaxVaryingVectors 8\n"
1359 "MaxFragmentUniformVectors 16\n"
1360 "MaxVertexOutputVectors 16\n"
1361 "MaxFragmentInputVectors 15\n"
1362 "MinProgramTexelOffset -8\n"
1363 "MaxProgramTexelOffset 7\n"
1364 "MaxClipDistances 8\n"
1365 "MaxComputeWorkGroupCountX 65535\n"
1366 "MaxComputeWorkGroupCountY 65535\n"
1367 "MaxComputeWorkGroupCountZ 65535\n"
1368 "MaxComputeWorkGroupSizeX 1024\n"
1369 "MaxComputeWorkGroupSizeY 1024\n"
1370 "MaxComputeWorkGroupSizeZ 64\n"
1371 "MaxComputeUniformComponents 1024\n"
1372 "MaxComputeTextureImageUnits 16\n"
1373 "MaxComputeImageUniforms 8\n"
1374 "MaxComputeAtomicCounters 8\n"
1375 "MaxComputeAtomicCounterBuffers 1\n"
1376 "MaxVaryingComponents 60\n"
1377 "MaxVertexOutputComponents 64\n"
1378 "MaxGeometryInputComponents 64\n"
1379 "MaxGeometryOutputComponents 128\n"
1380 "MaxFragmentInputComponents 128\n"
1381 "MaxImageUnits 8\n"
1382 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
1383 "MaxCombinedShaderOutputResources 8\n"
1384 "MaxImageSamples 0\n"
1385 "MaxVertexImageUniforms 0\n"
1386 "MaxTessControlImageUniforms 0\n"
1387 "MaxTessEvaluationImageUniforms 0\n"
1388 "MaxGeometryImageUniforms 0\n"
1389 "MaxFragmentImageUniforms 8\n"
1390 "MaxCombinedImageUniforms 8\n"
1391 "MaxGeometryTextureImageUnits 16\n"
1392 "MaxGeometryOutputVertices 256\n"
1393 "MaxGeometryTotalOutputComponents 1024\n"
1394 "MaxGeometryUniformComponents 1024\n"
1395 "MaxGeometryVaryingComponents 64\n"
1396 "MaxTessControlInputComponents 128\n"
1397 "MaxTessControlOutputComponents 128\n"
1398 "MaxTessControlTextureImageUnits 16\n"
1399 "MaxTessControlUniformComponents 1024\n"
1400 "MaxTessControlTotalOutputComponents 4096\n"
1401 "MaxTessEvaluationInputComponents 128\n"
1402 "MaxTessEvaluationOutputComponents 128\n"
1403 "MaxTessEvaluationTextureImageUnits 16\n"
1404 "MaxTessEvaluationUniformComponents 1024\n"
1405 "MaxTessPatchComponents 120\n"
1406 "MaxPatchVertices 32\n"
1407 "MaxTessGenLevel 64\n"
1408 "MaxViewports 16\n"
1409 "MaxVertexAtomicCounters 0\n"
1410 "MaxTessControlAtomicCounters 0\n"
1411 "MaxTessEvaluationAtomicCounters 0\n"
1412 "MaxGeometryAtomicCounters 0\n"
1413 "MaxFragmentAtomicCounters 8\n"
1414 "MaxCombinedAtomicCounters 8\n"
1415 "MaxAtomicCounterBindings 1\n"
1416 "MaxVertexAtomicCounterBuffers 0\n"
1417 "MaxTessControlAtomicCounterBuffers 0\n"
1418 "MaxTessEvaluationAtomicCounterBuffers 0\n"
1419 "MaxGeometryAtomicCounterBuffers 0\n"
1420 "MaxFragmentAtomicCounterBuffers 1\n"
1421 "MaxCombinedAtomicCounterBuffers 1\n"
1422 "MaxAtomicCounterBufferSize 16384\n"
1423 "MaxTransformFeedbackBuffers 4\n"
1424 "MaxTransformFeedbackInterleavedComponents 64\n"
1425 "MaxCullDistances 8\n"
1426 "MaxCombinedClipAndCullDistances 8\n"
1427 "MaxSamples 4\n"
1428
1429 "nonInductiveForLoops 1\n"
1430 "whileLoops 1\n"
1431 "doWhileLoops 1\n"
1432 "generalUniformIndexing 1\n"
1433 "generalAttributeMatrixVectorIndexing 1\n"
1434 "generalVaryingIndexing 1\n"
1435 "generalSamplerIndexing 1\n"
1436 "generalVariableIndexing 1\n"
1437 "generalConstantMatrixVectorIndexing 1\n"
1438 ;
1439
1440//
1441// *.conf => this is a config file that can set limits/resources
1442//
Tony Barbour6918cd52015-04-09 12:58:51 -06001443bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001444{
1445 if (name.size() < 5)
1446 return false;
1447
1448 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
1449 ConfigFile = name;
1450 return true;
1451 }
1452
1453 return false;
1454}
1455
1456//
1457// Parse either a .conf file provided by the user or the default string above.
1458//
Tony Barbour6918cd52015-04-09 12:58:51 -06001459void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001460{
1461 char** configStrings = 0;
1462 char* config = 0;
1463 if (ConfigFile.size() > 0) {
1464 configStrings = ReadFileData(ConfigFile.c_str());
1465 if (configStrings)
1466 config = *configStrings;
1467 else {
1468 printf("Error opening configuration file; will instead use the default configuration\n");
1469 }
1470 }
1471
1472 if (config == 0) {
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001473 config = (char *) alloca(strlen(DefaultConfig) + 1);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001474 strcpy(config, DefaultConfig);
1475 }
1476
1477 const char* delims = " \t\n\r";
1478 const char* token = strtok(config, delims);
1479 while (token) {
1480 const char* valueStr = strtok(0, delims);
1481 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1482 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1483 return;
1484 }
1485 int value = atoi(valueStr);
1486
1487 if (strcmp(token, "MaxLights") == 0)
1488 Resources.maxLights = value;
1489 else if (strcmp(token, "MaxClipPlanes") == 0)
1490 Resources.maxClipPlanes = value;
1491 else if (strcmp(token, "MaxTextureUnits") == 0)
1492 Resources.maxTextureUnits = value;
1493 else if (strcmp(token, "MaxTextureCoords") == 0)
1494 Resources.maxTextureCoords = value;
1495 else if (strcmp(token, "MaxVertexAttribs") == 0)
1496 Resources.maxVertexAttribs = value;
1497 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1498 Resources.maxVertexUniformComponents = value;
1499 else if (strcmp(token, "MaxVaryingFloats") == 0)
1500 Resources.maxVaryingFloats = value;
1501 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1502 Resources.maxVertexTextureImageUnits = value;
1503 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1504 Resources.maxCombinedTextureImageUnits = value;
1505 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1506 Resources.maxTextureImageUnits = value;
1507 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1508 Resources.maxFragmentUniformComponents = value;
1509 else if (strcmp(token, "MaxDrawBuffers") == 0)
1510 Resources.maxDrawBuffers = value;
1511 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1512 Resources.maxVertexUniformVectors = value;
1513 else if (strcmp(token, "MaxVaryingVectors") == 0)
1514 Resources.maxVaryingVectors = value;
1515 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1516 Resources.maxFragmentUniformVectors = value;
1517 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1518 Resources.maxVertexOutputVectors = value;
1519 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1520 Resources.maxFragmentInputVectors = value;
1521 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1522 Resources.minProgramTexelOffset = value;
1523 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1524 Resources.maxProgramTexelOffset = value;
1525 else if (strcmp(token, "MaxClipDistances") == 0)
1526 Resources.maxClipDistances = value;
1527 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1528 Resources.maxComputeWorkGroupCountX = value;
1529 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1530 Resources.maxComputeWorkGroupCountY = value;
1531 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1532 Resources.maxComputeWorkGroupCountZ = value;
1533 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1534 Resources.maxComputeWorkGroupSizeX = value;
1535 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1536 Resources.maxComputeWorkGroupSizeY = value;
1537 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1538 Resources.maxComputeWorkGroupSizeZ = value;
1539 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1540 Resources.maxComputeUniformComponents = value;
1541 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1542 Resources.maxComputeTextureImageUnits = value;
1543 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1544 Resources.maxComputeImageUniforms = value;
1545 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1546 Resources.maxComputeAtomicCounters = value;
1547 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1548 Resources.maxComputeAtomicCounterBuffers = value;
1549 else if (strcmp(token, "MaxVaryingComponents") == 0)
1550 Resources.maxVaryingComponents = value;
1551 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1552 Resources.maxVertexOutputComponents = value;
1553 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1554 Resources.maxGeometryInputComponents = value;
1555 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1556 Resources.maxGeometryOutputComponents = value;
1557 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1558 Resources.maxFragmentInputComponents = value;
1559 else if (strcmp(token, "MaxImageUnits") == 0)
1560 Resources.maxImageUnits = value;
1561 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1562 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1563 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1564 Resources.maxCombinedShaderOutputResources = value;
1565 else if (strcmp(token, "MaxImageSamples") == 0)
1566 Resources.maxImageSamples = value;
1567 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1568 Resources.maxVertexImageUniforms = value;
1569 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1570 Resources.maxTessControlImageUniforms = value;
1571 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1572 Resources.maxTessEvaluationImageUniforms = value;
1573 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1574 Resources.maxGeometryImageUniforms = value;
1575 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1576 Resources.maxFragmentImageUniforms = value;
1577 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1578 Resources.maxCombinedImageUniforms = value;
1579 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1580 Resources.maxGeometryTextureImageUnits = value;
1581 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1582 Resources.maxGeometryOutputVertices = value;
1583 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1584 Resources.maxGeometryTotalOutputComponents = value;
1585 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1586 Resources.maxGeometryUniformComponents = value;
1587 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1588 Resources.maxGeometryVaryingComponents = value;
1589 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1590 Resources.maxTessControlInputComponents = value;
1591 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1592 Resources.maxTessControlOutputComponents = value;
1593 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1594 Resources.maxTessControlTextureImageUnits = value;
1595 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1596 Resources.maxTessControlUniformComponents = value;
1597 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1598 Resources.maxTessControlTotalOutputComponents = value;
1599 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1600 Resources.maxTessEvaluationInputComponents = value;
1601 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1602 Resources.maxTessEvaluationOutputComponents = value;
1603 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1604 Resources.maxTessEvaluationTextureImageUnits = value;
1605 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1606 Resources.maxTessEvaluationUniformComponents = value;
1607 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1608 Resources.maxTessPatchComponents = value;
1609 else if (strcmp(token, "MaxPatchVertices") == 0)
1610 Resources.maxPatchVertices = value;
1611 else if (strcmp(token, "MaxTessGenLevel") == 0)
1612 Resources.maxTessGenLevel = value;
1613 else if (strcmp(token, "MaxViewports") == 0)
1614 Resources.maxViewports = value;
1615 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1616 Resources.maxVertexAtomicCounters = value;
1617 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1618 Resources.maxTessControlAtomicCounters = value;
1619 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1620 Resources.maxTessEvaluationAtomicCounters = value;
1621 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1622 Resources.maxGeometryAtomicCounters = value;
1623 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1624 Resources.maxFragmentAtomicCounters = value;
1625 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1626 Resources.maxCombinedAtomicCounters = value;
1627 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1628 Resources.maxAtomicCounterBindings = value;
1629 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1630 Resources.maxVertexAtomicCounterBuffers = value;
1631 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1632 Resources.maxTessControlAtomicCounterBuffers = value;
1633 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1634 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1635 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1636 Resources.maxGeometryAtomicCounterBuffers = value;
1637 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1638 Resources.maxFragmentAtomicCounterBuffers = value;
1639 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1640 Resources.maxCombinedAtomicCounterBuffers = value;
1641 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1642 Resources.maxAtomicCounterBufferSize = value;
1643 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1644 Resources.maxTransformFeedbackBuffers = value;
1645 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1646 Resources.maxTransformFeedbackInterleavedComponents = value;
1647 else if (strcmp(token, "MaxCullDistances") == 0)
1648 Resources.maxCullDistances = value;
1649 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1650 Resources.maxCombinedClipAndCullDistances = value;
1651 else if (strcmp(token, "MaxSamples") == 0)
1652 Resources.maxSamples = value;
1653
1654 else if (strcmp(token, "nonInductiveForLoops") == 0)
1655 Resources.limits.nonInductiveForLoops = (value != 0);
1656 else if (strcmp(token, "whileLoops") == 0)
1657 Resources.limits.whileLoops = (value != 0);
1658 else if (strcmp(token, "doWhileLoops") == 0)
1659 Resources.limits.doWhileLoops = (value != 0);
1660 else if (strcmp(token, "generalUniformIndexing") == 0)
1661 Resources.limits.generalUniformIndexing = (value != 0);
1662 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1663 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1664 else if (strcmp(token, "generalVaryingIndexing") == 0)
1665 Resources.limits.generalVaryingIndexing = (value != 0);
1666 else if (strcmp(token, "generalSamplerIndexing") == 0)
1667 Resources.limits.generalSamplerIndexing = (value != 0);
1668 else if (strcmp(token, "generalVariableIndexing") == 0)
1669 Resources.limits.generalVariableIndexing = (value != 0);
1670 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1671 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1672 else
1673 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1674
1675 token = strtok(0, delims);
1676 }
1677 if (configStrings)
1678 FreeFileData(configStrings);
1679}
1680
Tony Barbour6918cd52015-04-09 12:58:51 -06001681void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001682{
1683 if (m_compile_options & EOptionRelaxedErrors)
1684 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1685 if (m_compile_options & EOptionIntermediate)
1686 messages = (EShMessages)(messages | EShMsgAST);
1687 if (m_compile_options & EOptionSuppressWarnings)
1688 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1689}
1690
1691//
1692// Malloc a string of sufficient size and read a string into it.
1693//
Tony Barbour6918cd52015-04-09 12:58:51 -06001694char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001695{
1696 FILE *in;
1697 #if defined(_WIN32) && defined(__GNUC__)
1698 in = fopen(fileName, "r");
1699 int errorCode = in ? 0 : 1;
1700 #else
1701 int errorCode = fopen_s(&in, fileName, "r");
1702 #endif
1703
1704 char *fdata;
1705 int count = 0;
1706 const int maxSourceStrings = 5;
1707 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1708
1709 if (errorCode) {
1710 printf("Error: unable to open input file: %s\n", fileName);
1711 return 0;
1712 }
1713
1714 while (fgetc(in) != EOF)
1715 count++;
1716
1717 fseek(in, 0, SEEK_SET);
1718
1719 if (!(fdata = (char*)malloc(count+2))) {
1720 printf("Error allocating memory\n");
1721 return 0;
1722 }
1723 if (fread(fdata,1,count, in)!=count) {
1724 printf("Error reading input file: %s\n", fileName);
1725 return 0;
1726 }
1727 fdata[count] = '\0';
1728 fclose(in);
1729 if (count == 0) {
1730 return_data[0]=(char*)malloc(count+2);
1731 return_data[0][0]='\0';
1732 m_num_shader_strings = 0;
1733 return return_data;
1734 } else
1735 m_num_shader_strings = 1;
1736
1737 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1738 int ptr_len=0,i=0;
1739 while(count>0){
1740 return_data[i]=(char*)malloc(len+2);
1741 memcpy(return_data[i],fdata+ptr_len,len);
1742 return_data[i][len]='\0';
1743 count-=(len);
1744 ptr_len+=(len);
1745 if(count<len){
1746 if(count==0){
1747 m_num_shader_strings=(i+1);
1748 break;
1749 }
1750 len = count;
1751 }
1752 ++i;
1753 }
1754 return return_data;
1755}
1756
Tony Barbour6918cd52015-04-09 12:58:51 -06001757void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001758{
1759 for(int i=0;i<m_num_shader_strings;i++)
1760 free(data[i]);
1761}
1762
1763//
1764// Deduce the language from the filename. Files must end in one of the
1765// following extensions:
1766//
1767// .vert = vertex
1768// .tesc = tessellation control
1769// .tese = tessellation evaluation
1770// .geom = geometry
1771// .frag = fragment
1772// .comp = compute
1773//
Tony Barbour6918cd52015-04-09 12:58:51 -06001774EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001775{
1776 size_t ext = name.rfind('.');
1777 if (ext == std::string::npos) {
1778 return EShLangVertex;
1779 }
1780
1781 std::string suffix = name.substr(ext + 1, std::string::npos);
1782 if (suffix == "vert")
1783 return EShLangVertex;
1784 else if (suffix == "tesc")
1785 return EShLangTessControl;
1786 else if (suffix == "tese")
1787 return EShLangTessEvaluation;
1788 else if (suffix == "geom")
1789 return EShLangGeometry;
1790 else if (suffix == "frag")
1791 return EShLangFragment;
1792 else if (suffix == "comp")
1793 return EShLangCompute;
1794
1795 return EShLangVertex;
1796}
1797
1798//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001799// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001800//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001801EShLanguage VkTestFramework::FindLanguage(const VkShaderStageFlagBits shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001802{
1803 switch (shader_type) {
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001804 case VK_SHADER_STAGE_VERTEX_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001805 return EShLangVertex;
1806
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001807 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001808 return EShLangTessControl;
1809
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001810 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001811 return EShLangTessEvaluation;
1812
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001813 case VK_SHADER_STAGE_GEOMETRY_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001814 return EShLangGeometry;
1815
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001816 case VK_SHADER_STAGE_FRAGMENT_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001817 return EShLangFragment;
1818
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001819 case VK_SHADER_STAGE_COMPUTE_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001820 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001821
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001822 default:
1823 return EShLangVertex;
1824 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001825}
1826
1827
1828//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001829// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001830// Return value of false means an error was encountered.
1831//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001832bool VkTestFramework::GLSLtoSPV(const VkShaderStageFlagBits shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001833 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001834 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001835{
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001836 glslang::TProgram program;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001837 const char *shaderStrings[1];
1838
1839 // TODO: Do we want to load a special config file depending on the
1840 // shader source? Optional name maybe?
1841 // SetConfigFile(fileName);
1842
1843 ProcessConfigFile();
1844
1845 EShMessages messages = EShMsgDefault;
1846 SetMessageOptions(messages);
1847
1848 EShLanguage stage = FindLanguage(shader_type);
1849 glslang::TShader* shader = new glslang::TShader(stage);
1850
1851 shaderStrings[0] = pshader;
1852 shader->setStrings(shaderStrings, 1);
1853
1854 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1855
Cody Northrop195d6622014-11-03 12:54:37 -07001856 if (! (m_compile_options & EOptionSuppressInfolog)) {
1857 puts(shader->getInfoLog());
1858 puts(shader->getInfoDebugLog());
1859 }
1860
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001861 return false; // something didn't work
1862 }
1863
1864 program.addShader(shader);
1865
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001866
1867 //
1868 // Program-level processing...
1869 //
1870
Cody Northrop195d6622014-11-03 12:54:37 -07001871 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001872
Cody Northrop195d6622014-11-03 12:54:37 -07001873 if (! (m_compile_options & EOptionSuppressInfolog)) {
1874 puts(shader->getInfoLog());
1875 puts(shader->getInfoDebugLog());
1876 }
1877
1878 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001879 }
1880
1881 if (m_compile_options & EOptionDumpReflection) {
1882 program.buildReflection();
1883 program.dumpReflection();
1884 }
1885
Cody Northrop5a95b472015-06-03 13:01:54 -06001886 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1887
1888 //
1889 // Test the different modes of SPIR-V modification
1890 //
1891 if (this->m_canonicalize_spv) {
1892 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1893 }
1894
1895 if (this->m_strip_spv) {
1896 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1897 }
1898
1899 if (this->m_do_everything_spv) {
1900 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1901 }
1902
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001903 delete shader;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001904
1905 return true;
1906}
1907
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001908
1909
Tony Barbour6918cd52015-04-09 12:58:51 -06001910VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001911 m_width( 0 ),
1912 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001913 m_data( NULL ),
1914 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001915{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001916}
1917
Tony Barbour6918cd52015-04-09 12:58:51 -06001918VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001919{
1920
1921}
1922
Tony Barbour6918cd52015-04-09 12:58:51 -06001923VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001924{
1925 m_title = copyin.m_title;
1926 m_width = copyin.m_width;
1927 m_height = copyin.m_height;
1928 m_data_size = copyin.m_data_size;
1929 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1930}
1931
Tony Barbour6918cd52015-04-09 12:58:51 -06001932ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001933{
Tony Barbour6918cd52015-04-09 12:58:51 -06001934 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1935 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001936 return output;
1937}
1938
Tony Barbour6918cd52015-04-09 12:58:51 -06001939VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001940{
1941 m_title = rhs.m_title;
1942 m_width = rhs.m_width;
1943 m_height = rhs.m_height;
1944 m_data_size = rhs.m_data_size;
1945 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001946 return *this;
1947}
1948
Tony Barbour6918cd52015-04-09 12:58:51 -06001949int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001950{
1951 if( this->m_data != rhs.m_data) return 0;
1952 return 1;
1953}
1954
1955// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001956int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001957{
1958 if( this->m_data_size < rhs.m_data_size ) return 1;
1959 return 0;
1960}
1961