blob: 315dd35ec111eb8eec3e815313527e3186c445d6 [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 Barbour90ceffb2016-01-05 09:59:05 -0700635 memoryBarrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
636 memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
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;
Tony Barbour90ceffb2016-01-05 09:59:05 -0700648 vkCmdPipelineBarrier(m_cmdbuf.handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_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;
Tony Barbour90ceffb2016-01-05 09:59:05 -0700667 memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
668 memoryBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
669 vkCmdPipelineBarrier(m_cmdbuf.handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
Chia-I Wu53534662015-10-26 17:08:33 +0800670 0, 1, (const void * const*)&pmemory_barrier);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600671 m_cmdbuf.end();
672
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800673 VkCommandBuffer cmdBufs[1];
Chia-I Wube2b9172015-07-03 11:49:42 +0800674 cmdBufs[0] = m_cmdbuf.handle();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600675
Chia-I Wua690b412015-10-29 22:01:53 +0800676 // Wait for the present complete semaphore to be signaled to ensure
677 // that the image won't be rendered to until the presentation
678 // engine has fully released ownership to the application, and it is
679 // okay to render to the image.
Tony Barbour67e99152015-07-10 14:10:27 -0600680 VkFence nullFence = { VK_NULL_HANDLE };
Jon Ashburn8c0c1432015-12-31 12:32:16 -0700681 VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600682 VkSubmitInfo submit_info;
Chia-I Wuf9be13c2015-10-26 20:37:06 +0800683 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
684 submit_info.pNext = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +0800685 submit_info.waitSemaphoreCount = 1;
Jon Ashburn7f9716c2015-12-30 16:42:50 -0700686 submit_info.pWaitSemaphores = &presentCompleteSemaphore;
687 submit_info.pWaitDstStageMask = &pipe_stage_flags;
Chia-I Wud50a7d72015-10-26 20:48:51 +0800688 submit_info.commandBufferCount = 1;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600689 submit_info.pCommandBuffers = cmdBufs;
Chia-I Wud50a7d72015-10-26 20:48:51 +0800690 submit_info.signalSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600691 submit_info.pSignalSemaphores = NULL;
692
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -0600693 vkQueueSubmit(m_queue.handle(), 1, &submit_info, nullFence);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600694 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700695
Chia-I Wuf7458c52015-10-26 21:10:41 +0800696 vkDestroySemaphore(m_device.handle(), presentCompleteSemaphore, NULL);
Chia-I Wua690b412015-10-29 22:01:53 +0800697
Ian Elliott7e40db92015-08-21 15:09:33 -0600698 VkPresentInfoKHR present = {};
699 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600700 present.pNext = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600701 present.swapchainCount = 1;
Ian Elliottc11750d2015-10-30 13:24:12 -0600702 present.pSwapchains = & m_swap_chain;
703 present.pImageIndices = &m_current_buffer;
Tony Barbour96db8822015-02-25 12:28:39 -0700704
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600705#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800706 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700707 XCB_PROP_MODE_REPLACE,
708 m_window,
709 XCB_ATOM_WM_NAME,
710 XCB_ATOM_STRING,
711 8,
712 m_display_image->m_title.size(),
713 m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600714#endif
Jon Ashburn07daee72015-05-21 18:13:33 -0600715
Ian Elliott7e40db92015-08-21 15:09:33 -0600716 err = m_fpQueuePresentKHR(m_queue.handle(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700717 assert(!err);
718
719 m_queue.wait();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600720 m_current_buffer = (m_current_buffer + 1) % 2;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600721}
722
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600723#ifdef _WIN32
Tony-LunarG399dfca2015-05-19 14:08:26 -0600724# define PREVIOUSLY_DOWN 1<<29
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600725// MS-Windows event handling function:
726LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
727 UINT uMsg,
728 WPARAM wParam,
729 LPARAM lParam)
730{
731
732 switch(uMsg)
733 {
734 case WM_CLOSE:
735 PostQuitMessage(0);
736 break;
737
738 case WM_PAINT:
739 {
740 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
741 if (me) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600742 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600743 me->Display();
744 }
745 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600746 break;
747
748 case WM_KEYDOWN:
749 {
750 if (lParam & (PREVIOUSLY_DOWN)){
751 break;
752 }
753 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
754 // the window, we put the this pointer into the window's user data so we could get it back now
755 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
756 switch (wParam)
757 {
758 case VK_ESCAPE: me->m_quit = true;
759 break;
760
761 case VK_LEFT: // left arrow key
762 if (me->m_display_image == me->m_images.begin()) {
763 me->m_display_image = --me->m_images.end();
764 }
765 else {
766 --me->m_display_image;
767 }
768 break;
769
770 case VK_RIGHT: // right arrow key
771 ++me->m_display_image;
772 if (me->m_display_image == me->m_images.end()) {
773 me->m_display_image = me->m_images.begin();
774 }
775 break;
776
777 default:
778 break;
779 }
780 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
781 me->Display();
782 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600783 }
784 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
785}
786
787void TestFrameworkVkPresent::Run()
788{
789 MSG msg; // message
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600790
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600791 /* main message loop*/
Tony-LunarG399dfca2015-05-19 14:08:26 -0600792 while(! m_quit) {
793 GetMessage(&msg, m_window, 0, 0);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600794 if (msg.message == WM_QUIT) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600795 m_quit = true; //if found, quit app
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600796 } else {
797 /* Translate and dispatch to event queue*/
798 TranslateMessage(&msg);
799 DispatchMessage(&msg);
800 }
801 }
802}
803
804#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600805void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600806{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600807 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700808 switch (event_code) {
809 case XCB_EXPOSE:
810 Display(); // TODO: handle resize
811 break;
812 case XCB_CLIENT_MESSAGE:
813 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
814 (m_atom_wm_delete_window)->atom) {
815 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600816 }
817 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700818 case XCB_KEY_RELEASE:
819 {
820 const xcb_key_release_event_t *key =
821 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600822
Tony Barbour96db8822015-02-25 12:28:39 -0700823 switch (key->detail) {
824 case 0x9: // Escape
825 m_quit = true;
826 break;
827 case 0x71: // left arrow key
828 if (m_display_image == m_images.begin()) {
829 m_display_image = --m_images.end();
830 } else {
831 --m_display_image;
832 }
833 break;
834 case 0x72: // right arrow key
835 ++m_display_image;
836 if (m_display_image == m_images.end()) {
837 m_display_image = m_images.begin();
838 }
839 break;
840 case 0x41:
841 m_pause = !m_pause;
842 break;
843 }
844 Display();
845 }
846 break;
847 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600848 break;
849 }
Tony Barbour96db8822015-02-25 12:28:39 -0700850}
851
Tony Barbour6918cd52015-04-09 12:58:51 -0600852void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700853{
Chia-I Wuf8693382015-04-16 22:02:10 +0800854 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700855
856 while (! m_quit) {
857 xcb_generic_event_t *event;
858
859 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800860 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700861 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800862 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700863 }
864 if (event) {
865 HandleEvent(event);
866 free(event);
867 }
868 }
869}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600870#endif // _WIN32
Tony Barbour96db8822015-02-25 12:28:39 -0700871
Ian Elliott7e40db92015-08-21 15:09:33 -0600872void TestFrameworkVkPresent::CreateSwapchain()
Tony Barbour96db8822015-02-25 12:28:39 -0700873{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600874 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700875
Tony-LunarG399dfca2015-05-19 14:08:26 -0600876 m_display_image = m_images.begin();
877 m_current_buffer = 0;
878
Ian Elliottc11750d2015-10-30 13:24:12 -0600879 // Create the WSI surface:
Ian Elliott1a3845b2015-07-06 14:33:04 -0600880#ifdef _WIN32
Ian Elliotta8914ac2015-12-11 14:05:35 -0700881 VkWin32SurfaceCreateInfoKHR createInfo;
882 createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
883 createInfo.pNext = NULL;
884 createInfo.flags = 0;
Jon Ashburn88215af2015-12-24 17:08:01 -0700885 createInfo.hinstance = m_connection;
886 createInfo.hwnd = m_window;
Ian Elliotta8914ac2015-12-11 14:05:35 -0700887
888 err = vkCreateWin32SurfaceKHR(m_instance, &createInfo, NULL, &m_surface);
Ian Elliott1a3845b2015-07-06 14:33:04 -0600889#else // _WIN32
Ian Elliotta8914ac2015-12-11 14:05:35 -0700890 VkXcbSurfaceCreateInfoKHR createInfo;
891 createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
892 createInfo.pNext = NULL;
893 createInfo.flags = 0;
894 createInfo.connection = m_connection;
895 createInfo.window = m_window;
896
897 err = vkCreateXcbSurfaceKHR(m_instance, &createInfo, NULL, &m_surface);
Ian Elliott1a3845b2015-07-06 14:33:04 -0600898#endif // _WIN32
Ian Elliottc11750d2015-10-30 13:24:12 -0600899 assert(!err);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600900
901 // Iterate over each queue to learn whether it supports presenting to WSI:
902 VkBool32 supportsPresent;
903 m_present_queue_node_index = UINT32_MAX;
904 std::vector<vk_testing::Queue *> queues = m_device.graphics_queues();
905 for (int i=0; i < queues.size(); i++)
906 {
907 int family_index = queues[i]->get_family_index();
Ian Elliott7e40db92015-08-21 15:09:33 -0600908 m_fpGetPhysicalDeviceSurfaceSupportKHR(m_device.phy().handle(),
Tony Barbour6a3faf02015-07-23 10:36:18 -0600909 family_index,
Ian Elliottc11750d2015-10-30 13:24:12 -0600910 m_surface,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600911 &supportsPresent);
912 if (supportsPresent) {
913 m_present_queue_node_index = family_index;
914 }
915 }
916
917 assert(m_present_queue_node_index != UINT32_MAX);
918
919
920 // Get the list of VkFormat's that are supported:
Ian Elliott8b139792015-08-07 11:51:12 -0600921 uint32_t formatCount;
Ian Elliottc11750d2015-10-30 13:24:12 -0600922 err = m_fpGetPhysicalDeviceSurfaceFormatsKHR(m_device.phy().handle(),
923 m_surface,
Ian Elliott8b139792015-08-07 11:51:12 -0600924 &formatCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600925 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600926 VkSurfaceFormatKHR *surfFormats =
927 (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
Ian Elliottc11750d2015-10-30 13:24:12 -0600928 err = m_fpGetPhysicalDeviceSurfaceFormatsKHR(m_device.phy().handle(),
929 m_surface,
Ian Elliott8b139792015-08-07 11:51:12 -0600930 &formatCount, surfFormats);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600931 assert(!err);
932 // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
933 // the surface has no preferred format. Otherwise, at least one
934 // supported format will be returned.
Tony Barbour6a3faf02015-07-23 10:36:18 -0600935 if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED)
936 {
937 m_format = VK_FORMAT_B8G8R8A8_UNORM;
938 }
939 else
940 {
941 assert(formatCount >= 1);
942 m_format = surfFormats[0].format;
943 }
Ian Elliott8b139792015-08-07 11:51:12 -0600944 m_color_space = surfFormats[0].colorSpace;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600945
Ian Elliottc11750d2015-10-30 13:24:12 -0600946 // Check the surface capabilities and formats
947 VkSurfaceCapabilitiesKHR surfCapabilities;
948 err = m_fpGetPhysicalDeviceSurfaceCapabilitiesKHR(m_device.phy().handle(),
949 m_surface,
950 &surfCapabilities);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600951 assert(!err);
952
Ian Elliott8b139792015-08-07 11:51:12 -0600953 uint32_t presentModeCount;
Ian Elliottc11750d2015-10-30 13:24:12 -0600954 err = m_fpGetPhysicalDeviceSurfacePresentModesKHR(m_device.phy().handle(),
955 m_surface,
Ian Elliott8b139792015-08-07 11:51:12 -0600956 &presentModeCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600957 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600958 VkPresentModeKHR *presentModes =
959 (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
Ian Elliott8b139792015-08-07 11:51:12 -0600960 assert(presentModes);
Ian Elliottc11750d2015-10-30 13:24:12 -0600961 err = m_fpGetPhysicalDeviceSurfacePresentModesKHR(m_device.phy().handle(),
962 m_surface,
Ian Elliott8b139792015-08-07 11:51:12 -0600963 &presentModeCount, presentModes);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600964 assert(!err);
965
Ian Elliott7e40db92015-08-21 15:09:33 -0600966 VkExtent2D swapchainExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600967 // width and height are either both -1, or both not -1.
Ian Elliottc11750d2015-10-30 13:24:12 -0600968 if (surfCapabilities.currentExtent.width == -1)
Tony Barbour6a3faf02015-07-23 10:36:18 -0600969 {
970 // If the surface size is undefined, the size is set to
971 // the size of the images requested.
Ian Elliott7e40db92015-08-21 15:09:33 -0600972 swapchainExtent.width = m_width;
973 swapchainExtent.height = m_height;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600974 }
975 else
976 {
977 // If the surface size is defined, the swap chain size must match
Ian Elliottc11750d2015-10-30 13:24:12 -0600978 swapchainExtent = surfCapabilities.currentExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600979 }
980
981 // If mailbox mode is available, use it, as is the lowest-latency non-
Ian Elliottae0e8242015-08-10 13:20:49 -0600982 // tearing mode. If not, try IMMEDIATE which will usually be available,
983 // and is fastest (though it tears). If not, fall back to FIFO which is
984 // always available.
Ian Elliott7e40db92015-08-21 15:09:33 -0600985 VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600986 for (size_t i = 0; i < presentModeCount; i++) {
Ian Elliott7e40db92015-08-21 15:09:33 -0600987 if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
988 swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600989 break;
990 }
Ian Elliott7e40db92015-08-21 15:09:33 -0600991 if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) &&
992 (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
993 swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
Ian Elliottae0e8242015-08-10 13:20:49 -0600994 }
Tony Barbour6a3faf02015-07-23 10:36:18 -0600995 }
996
997 // Determine the number of VkImage's to use in the swap chain (we desire to
998 // own only 1 image at a time, besides the images being displayed and
999 // queued for display):
Ian Elliottc11750d2015-10-30 13:24:12 -06001000 uint32_t desiredNumberOfSwapchainImages = surfCapabilities.minImageCount + 1;
1001 if ((surfCapabilities.maxImageCount > 0) &&
1002 (desiredNumberOfSwapchainImages > surfCapabilities.maxImageCount))
Tony Barbour6a3faf02015-07-23 10:36:18 -06001003 {
1004 // Application must settle for fewer images than desired:
Ian Elliottc11750d2015-10-30 13:24:12 -06001005 desiredNumberOfSwapchainImages = surfCapabilities.maxImageCount;
Tony Barbour6a3faf02015-07-23 10:36:18 -06001006 }
1007
Ian Elliottc11750d2015-10-30 13:24:12 -06001008 VkSurfaceTransformFlagsKHR preTransform;
Ian Elliotta8914ac2015-12-11 14:05:35 -07001009 if (surfCapabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) {
1010 preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -06001011 } else {
Ian Elliottc11750d2015-10-30 13:24:12 -06001012 preTransform = surfCapabilities.currentTransform;
Tony Barbour6a3faf02015-07-23 10:36:18 -06001013 }
Ian Elliott1a3845b2015-07-06 14:33:04 -06001014
Cody Northropdf5b0922015-08-28 16:22:48 -06001015 // 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 -06001016 assert((surfCapabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) != 0);
Cody Northropdf5b0922015-08-28 16:22:48 -06001017
Ian Elliott7e40db92015-08-21 15:09:33 -06001018 VkSwapchainCreateInfoKHR swap_chain = {};
Ian Elliotta257eea2015-09-22 10:20:23 -06001019 swap_chain.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
Ian Elliott1a3845b2015-07-06 14:33:04 -06001020 swap_chain.pNext = NULL;
Ian Elliottc11750d2015-10-30 13:24:12 -06001021 swap_chain.surface = m_surface;
Ian Elliott7e40db92015-08-21 15:09:33 -06001022 swap_chain.minImageCount = desiredNumberOfSwapchainImages;
Tony Barbour6a3faf02015-07-23 10:36:18 -06001023 swap_chain.imageFormat = m_format;
Ian Elliott8b139792015-08-07 11:51:12 -06001024 swap_chain.imageColorSpace = m_color_space;
Ian Elliott7e40db92015-08-21 15:09:33 -06001025 swap_chain.imageExtent.width = swapchainExtent.width;
1026 swap_chain.imageExtent.height = swapchainExtent.height;
Ian Elliottc11750d2015-10-30 13:24:12 -06001027 swap_chain.imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1028 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1029 swap_chain.preTransform = (VkSurfaceTransformFlagBitsKHR) preTransform;
1030 swap_chain.imageArrayLayers = 1;
1031 swap_chain.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
1032 swap_chain.queueFamilyIndexCount = 0;
Ian Elliott8b139792015-08-07 11:51:12 -06001033 swap_chain.pQueueFamilyIndices = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -06001034 swap_chain.presentMode = swapchainPresentMode;
Chia-I Wue2fc5522015-10-26 20:04:44 +08001035 swap_chain.oldSwapchain = VK_NULL_HANDLE;
Tony Barbour6a3faf02015-07-23 10:36:18 -06001036 swap_chain.clipped = true;
1037
1038 uint32_t i;
Chia-I Wuf8693382015-04-16 22:02:10 +08001039
Ian Elliottc11750d2015-10-30 13:24:12 -06001040 err = m_fpCreateSwapchainKHR(m_device.handle(), &swap_chain, NULL, &m_swap_chain);
Chia-I Wuf8693382015-04-16 22:02:10 +08001041 assert(!err);
1042
Ian Elliott7e40db92015-08-21 15:09:33 -06001043 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
1044 &m_swapchainImageCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -06001045 assert(!err);
1046
Ian Elliott7e40db92015-08-21 15:09:33 -06001047 VkImage* swapchainImages = (VkImage*)malloc(m_swapchainImageCount * sizeof(VkImage));
1048 assert(swapchainImages);
1049 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
1050 &m_swapchainImageCount, swapchainImages);
Tony Barbour6a3faf02015-07-23 10:36:18 -06001051 assert(!err);
1052
Ian Elliott7e40db92015-08-21 15:09:33 -06001053 m_buffers = (SwapchainBuffers*)malloc(sizeof(SwapchainBuffers)*m_swapchainImageCount);
Tony Barbour6a3faf02015-07-23 10:36:18 -06001054 assert(m_buffers);
1055
Ian Elliott7e40db92015-08-21 15:09:33 -06001056 for (i = 0; i < m_swapchainImageCount; i++) {
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -06001057 VkImageViewCreateInfo color_image_view = {};
1058 color_image_view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
1059 color_image_view.pNext = NULL;
1060 color_image_view.format = m_format;
Tony Barbourd800bbd2015-11-05 10:54:44 -07001061 color_image_view.components.r = VK_COMPONENT_SWIZZLE_R;
1062 color_image_view.components.g = VK_COMPONENT_SWIZZLE_G;
1063 color_image_view.components.b = VK_COMPONENT_SWIZZLE_B;
1064 color_image_view.components.a = VK_COMPONENT_SWIZZLE_A;
Courtney Goeltzenleuchterba724512015-09-10 17:58:54 -06001065 color_image_view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -06001066 color_image_view.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001067 color_image_view.subresourceRange.levelCount = 1;
Courtney Goeltzenleuchter4a261892015-09-10 16:38:41 -06001068 color_image_view.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001069 color_image_view.subresourceRange.layerCount = 1;
Tony Barbourd800bbd2015-11-05 10:54:44 -07001070 color_image_view.viewType = VK_IMAGE_VIEW_TYPE_2D;
1071 color_image_view.flags = 0;
Tony Barbour6a3faf02015-07-23 10:36:18 -06001072
Ian Elliott7e40db92015-08-21 15:09:33 -06001073 m_buffers[i].image = swapchainImages[i];
Tony Barbour6a3faf02015-07-23 10:36:18 -06001074
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -06001075 color_image_view.image = m_buffers[i].image;
1076 err = vkCreateImageView(m_device.handle(),
Chia-I Wuf7458c52015-10-26 21:10:41 +08001077 &color_image_view, NULL, &m_buffers[i].view);
Tony Barbour6a3faf02015-07-23 10:36:18 -06001078 assert(!err);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001079
1080 /* Set image layout to PRESENT_SOURCE_KHR so that before the copy, it can be set to */
1081 /* TRANSFER_DESTINATION_OPTIMAL */
1082 SetImageLayout(m_buffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT,
Ian Elliott1dcd1092015-11-17 17:29:40 -07001083 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001084
Tony Barbour6a3faf02015-07-23 10:36:18 -06001085 }
Tony Barbour96db8822015-02-25 12:28:39 -07001086}
Tony Barbourbd094ce2015-10-23 11:00:15 -06001087void TestFrameworkVkPresent::SetImageLayout(VkImage image, VkImageAspectFlags aspectMask,
1088 VkImageLayout old_image_layout, VkImageLayout new_image_layout)
1089{
1090 VkResult U_ASSERT_ONLY err;
1091
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001092 VkCommandBufferBeginInfo cmd_buf_info = {};
1093 cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001094 cmd_buf_info.pNext = NULL;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001095 cmd_buf_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001096 cmd_buf_info.renderPass = { VK_NULL_HANDLE };
1097 cmd_buf_info.subpass = 0;
1098 cmd_buf_info.framebuffer = { VK_NULL_HANDLE };
Chia-I Wub8d47ae2015-11-11 10:18:12 +08001099 cmd_buf_info.occlusionQueryEnable = VK_FALSE;
1100 cmd_buf_info.queryFlags = 0;
1101 cmd_buf_info.pipelineStatistics = 0;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001102
1103 err = vkBeginCommandBuffer(m_cmdbuf.handle(), &cmd_buf_info);
1104 assert(!err);
1105
1106 VkImageMemoryBarrier image_memory_barrier = {};
1107 image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
1108 image_memory_barrier.pNext = NULL;
Chia-I Wua4594202015-10-27 19:54:37 +08001109 image_memory_barrier.srcAccessMask = 0;
1110 image_memory_barrier.dstAccessMask = 0;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001111 image_memory_barrier.oldLayout = old_image_layout;
1112 image_memory_barrier.newLayout = new_image_layout;
1113 image_memory_barrier.image = image;
1114 image_memory_barrier.subresourceRange.aspectMask = aspectMask;
1115 image_memory_barrier.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001116 image_memory_barrier.subresourceRange.levelCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001117 image_memory_barrier.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001118 image_memory_barrier.subresourceRange.layerCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001119
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001120 if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
Tony Barbourbd094ce2015-10-23 11:00:15 -06001121 /* Make sure anything that was copying from this image has completed */
Chia-I Wua4594202015-10-27 19:54:37 +08001122 image_memory_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001123 }
1124
1125 if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
1126 /* Make sure any Copy or CPU writes to image are flushed */
Chia-I Wua4594202015-10-27 19:54:37 +08001127 image_memory_barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001128 }
1129
1130 VkImageMemoryBarrier *pmemory_barrier = &image_memory_barrier;
1131
1132 VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1133 VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1134
Chia-I Wu53534662015-10-26 17:08:33 +08001135 vkCmdPipelineBarrier(m_cmdbuf.handle(), src_stages, dest_stages, 0, 1, (const void * const*)&pmemory_barrier);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001136
1137 err = vkEndCommandBuffer(m_cmdbuf.handle());
1138 assert(!err);
1139
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001140 const VkCommandBuffer cmd_bufs[] = { m_cmdbuf.handle() };
Tony Barbourbd094ce2015-10-23 11:00:15 -06001141 VkFence nullFence = { VK_NULL_HANDLE };
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001142 VkSubmitInfo submit_info;
Chia-I Wuf9be13c2015-10-26 20:37:06 +08001143 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1144 submit_info.pNext = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001145 submit_info.waitSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001146 submit_info.pWaitSemaphores = NULL;
Jon Ashburn7f9716c2015-12-30 16:42:50 -07001147 submit_info.pWaitDstStageMask = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001148 submit_info.commandBufferCount = 1;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001149 submit_info.pCommandBuffers = cmd_bufs;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001150 submit_info.signalSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001151 submit_info.pSignalSemaphores = NULL;
1152
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -06001153 err = vkQueueSubmit(m_queue.handle(), 1, &submit_info, nullFence);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001154 assert(!err);
1155
1156 err = vkQueueWaitIdle(m_queue.handle());
1157 assert(!err);
1158
1159}
Tony Barbour96db8822015-02-25 12:28:39 -07001160
Jon Ashburn07daee72015-05-21 18:13:33 -06001161void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -07001162{
Ian Elliottc11750d2015-10-30 13:24:12 -06001163 m_instance = inst;
Ian Elliott7e40db92015-08-21 15:09:33 -06001164 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceSupportKHR);
Ian Elliottc11750d2015-10-30 13:24:12 -06001165 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceCapabilitiesKHR);
1166 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceFormatsKHR);
1167 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfacePresentModesKHR);
Tony Barbour2d6d54e2015-12-03 16:05:11 -07001168 GET_INSTANCE_PROC_ADDR(inst, DestroySurfaceKHR);
Ian Elliott7e40db92015-08-21 15:09:33 -06001169 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1170 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1171 GET_DEVICE_PROC_ADDR(m_device.handle(), DestroySwapchainKHR);
1172 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSwapchainImagesKHR);
1173 GET_DEVICE_PROC_ADDR(m_device.handle(), AcquireNextImageKHR);
1174 GET_DEVICE_PROC_ADDR(m_device.handle(), QueuePresentKHR);
Jon Ashburn07daee72015-05-21 18:13:33 -06001175
Tony Barbour96db8822015-02-25 12:28:39 -07001176 m_images = imagesIn;
1177}
1178
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001179#ifdef _WIN32
1180void TestFrameworkVkPresent::CreateMyWindow()
1181{
1182 WNDCLASSEX win_class;
1183 // const ::testing::TestInfo* const test_info =
1184 // ::testing::UnitTest::GetInstance()->current_test_info();
1185 m_connection = GetModuleHandle(NULL);
1186
1187 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1188 it != m_images.end(); it++) {
1189 if (m_width < it->m_width)
1190 m_width = it->m_width;
1191 if (m_height < it->m_height)
1192 m_height = it->m_height;
1193 }
1194 // Initialize the window class structure:
1195 win_class.cbSize = sizeof(WNDCLASSEX);
1196 win_class.style = CS_HREDRAW | CS_VREDRAW;
1197 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
1198 win_class.cbClsExtra = 0;
1199 win_class.cbWndExtra = 0;
1200 win_class.hInstance = m_connection; // hInstance
1201 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
1202 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
1203 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
1204 win_class.lpszMenuName = NULL;
1205 win_class.lpszClassName = "Test";
1206 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
1207 // Register window class:
1208 if (!RegisterClassEx(&win_class)) {
1209 // It didn't work, so try to give a useful error:
1210 printf("Unexpected error trying to start the application!\n");
1211 fflush(stdout);
1212 exit(1);
1213 }
1214 // Create window with the registered class:
Cody Northrop39582252015-08-05 15:39:31 -06001215 RECT wr = { 0, 0, m_width, m_height };
1216 AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001217 m_window = CreateWindowEx(0,
1218 "Test", // class name
1219 "Test", // app name
1220 WS_OVERLAPPEDWINDOW | // window style
1221 WS_VISIBLE |
1222 WS_SYSMENU,
1223 100,100, // x/y coords
Cody Northrop39582252015-08-05 15:39:31 -06001224 wr.right - wr.left, // width
1225 wr.bottom - wr.top, // height
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001226 NULL, // handle to parent
1227 NULL, // handle to menu
1228 m_connection, // hInstance
1229 NULL); // no extra parameters
1230
1231 if (!m_window) {
1232 // It didn't work, so try to give a useful error:
1233 DWORD error = GetLastError();
1234 char message[120];
1235 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
1236 MessageBox(NULL, message, "Error", MB_OK);
1237 exit(1);
1238 }
Tony-LunarG399dfca2015-05-19 14:08:26 -06001239 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
1240 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001241}
1242#else
Tony Barbour6918cd52015-04-09 12:58:51 -06001243void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -07001244{
Chia-I Wuf8693382015-04-16 22:02:10 +08001245 const xcb_setup_t *setup;
1246 xcb_screen_iterator_t iter;
1247 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -07001248 uint32_t value_mask, value_list[32];
1249
Chia-I Wuf8693382015-04-16 22:02:10 +08001250 m_connection = xcb_connect(NULL, &scr);
1251
1252 setup = xcb_get_setup(m_connection);
1253 iter = xcb_setup_roots_iterator(setup);
1254 while (scr-- > 0)
1255 xcb_screen_next(&iter);
1256
1257 m_screen = iter.data;
1258
1259 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1260 it != m_images.end(); it++) {
1261 if (m_width < it->m_width)
1262 m_width = it->m_width;
1263 if (m_height < it->m_height)
1264 m_height = it->m_height;
1265 }
1266
1267 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -07001268
1269 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +08001270 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -07001271 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
1272 XCB_EVENT_MASK_EXPOSURE |
1273 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
1274
Chia-I Wuf8693382015-04-16 22:02:10 +08001275 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -07001276 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001277 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -07001278 0, 0, m_width, m_height, 0,
1279 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001280 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -07001281 value_mask, value_list);
1282
1283 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +08001284 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -07001285 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +08001286 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001287
Chia-I Wuf8693382015-04-16 22:02:10 +08001288 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
1289 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001290
Chia-I Wuf8693382015-04-16 22:02:10 +08001291 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -07001292 m_window, (*reply).atom, 4, 32, 1,
1293 &(*m_atom_wm_delete_window).atom);
1294 free(reply);
1295
Chia-I Wuf8693382015-04-16 22:02:10 +08001296 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -07001297}
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001298#endif
Tony Barbour96db8822015-02-25 12:28:39 -07001299
Tony Barbour6918cd52015-04-09 12:58:51 -06001300void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -07001301{
Ian Elliottc11750d2015-10-30 13:24:12 -06001302 m_fpDestroySwapchainKHR(m_device.handle(), m_swap_chain, NULL);
Tony Barbour9226a822015-10-23 10:58:56 -06001303
1304 for (uint32_t i = 0; i < m_swapchainImageCount; i++) {
Chia-I Wuf7458c52015-10-26 21:10:41 +08001305 vkDestroyImageView(m_device.handle(), m_buffers[i].view, NULL);
Tony Barbour9226a822015-10-23 10:58:56 -06001306 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001307#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +08001308 xcb_destroy_window(m_connection, m_window);
1309 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001310#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001311}
1312
Tony Barboure1837292015-12-07 13:46:11 -07001313void TestFrameworkVkPresent::DestroyMyWindow()
Tony Barbour2d6d54e2015-12-03 16:05:11 -07001314{
1315#ifndef _WIN32
1316 xcb_destroy_window(m_connection, m_window);
1317 xcb_disconnect(m_connection);
1318#else
1319 DestroyWindow(m_window);
1320#endif
1321}
1322
Tony Barbour6918cd52015-04-09 12:58:51 -06001323void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001324{
1325 if (m_images.size() == 0) return;
1326
Chia-I Wuf8693382015-04-16 22:02:10 +08001327 vk_testing::Environment env;
1328 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -07001329 {
Chia-I Wuf8693382015-04-16 22:02:10 +08001330 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -07001331
Jon Ashburn07daee72015-05-21 18:13:33 -06001332 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001333 vkPresent.CreateMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -06001334 vkPresent.CreateSwapchain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001335 vkPresent.Run();
1336 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -07001337 }
Chia-I Wuf8693382015-04-16 22:02:10 +08001338 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001339}
1340
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001341//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001342// These are the default resources for TBuiltInResources, used for both
1343// - parsing this string for the case where the user didn't supply one
1344// - dumping out a template for user construction of a config file
1345//
1346static const char* DefaultConfig =
1347 "MaxLights 32\n"
1348 "MaxClipPlanes 6\n"
1349 "MaxTextureUnits 32\n"
1350 "MaxTextureCoords 32\n"
1351 "MaxVertexAttribs 64\n"
1352 "MaxVertexUniformComponents 4096\n"
1353 "MaxVaryingFloats 64\n"
1354 "MaxVertexTextureImageUnits 32\n"
1355 "MaxCombinedTextureImageUnits 80\n"
1356 "MaxTextureImageUnits 32\n"
1357 "MaxFragmentUniformComponents 4096\n"
1358 "MaxDrawBuffers 32\n"
1359 "MaxVertexUniformVectors 128\n"
1360 "MaxVaryingVectors 8\n"
1361 "MaxFragmentUniformVectors 16\n"
1362 "MaxVertexOutputVectors 16\n"
1363 "MaxFragmentInputVectors 15\n"
1364 "MinProgramTexelOffset -8\n"
1365 "MaxProgramTexelOffset 7\n"
1366 "MaxClipDistances 8\n"
1367 "MaxComputeWorkGroupCountX 65535\n"
1368 "MaxComputeWorkGroupCountY 65535\n"
1369 "MaxComputeWorkGroupCountZ 65535\n"
1370 "MaxComputeWorkGroupSizeX 1024\n"
1371 "MaxComputeWorkGroupSizeY 1024\n"
1372 "MaxComputeWorkGroupSizeZ 64\n"
1373 "MaxComputeUniformComponents 1024\n"
1374 "MaxComputeTextureImageUnits 16\n"
1375 "MaxComputeImageUniforms 8\n"
1376 "MaxComputeAtomicCounters 8\n"
1377 "MaxComputeAtomicCounterBuffers 1\n"
1378 "MaxVaryingComponents 60\n"
1379 "MaxVertexOutputComponents 64\n"
1380 "MaxGeometryInputComponents 64\n"
1381 "MaxGeometryOutputComponents 128\n"
1382 "MaxFragmentInputComponents 128\n"
1383 "MaxImageUnits 8\n"
1384 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
1385 "MaxCombinedShaderOutputResources 8\n"
1386 "MaxImageSamples 0\n"
1387 "MaxVertexImageUniforms 0\n"
1388 "MaxTessControlImageUniforms 0\n"
1389 "MaxTessEvaluationImageUniforms 0\n"
1390 "MaxGeometryImageUniforms 0\n"
1391 "MaxFragmentImageUniforms 8\n"
1392 "MaxCombinedImageUniforms 8\n"
1393 "MaxGeometryTextureImageUnits 16\n"
1394 "MaxGeometryOutputVertices 256\n"
1395 "MaxGeometryTotalOutputComponents 1024\n"
1396 "MaxGeometryUniformComponents 1024\n"
1397 "MaxGeometryVaryingComponents 64\n"
1398 "MaxTessControlInputComponents 128\n"
1399 "MaxTessControlOutputComponents 128\n"
1400 "MaxTessControlTextureImageUnits 16\n"
1401 "MaxTessControlUniformComponents 1024\n"
1402 "MaxTessControlTotalOutputComponents 4096\n"
1403 "MaxTessEvaluationInputComponents 128\n"
1404 "MaxTessEvaluationOutputComponents 128\n"
1405 "MaxTessEvaluationTextureImageUnits 16\n"
1406 "MaxTessEvaluationUniformComponents 1024\n"
1407 "MaxTessPatchComponents 120\n"
1408 "MaxPatchVertices 32\n"
1409 "MaxTessGenLevel 64\n"
1410 "MaxViewports 16\n"
1411 "MaxVertexAtomicCounters 0\n"
1412 "MaxTessControlAtomicCounters 0\n"
1413 "MaxTessEvaluationAtomicCounters 0\n"
1414 "MaxGeometryAtomicCounters 0\n"
1415 "MaxFragmentAtomicCounters 8\n"
1416 "MaxCombinedAtomicCounters 8\n"
1417 "MaxAtomicCounterBindings 1\n"
1418 "MaxVertexAtomicCounterBuffers 0\n"
1419 "MaxTessControlAtomicCounterBuffers 0\n"
1420 "MaxTessEvaluationAtomicCounterBuffers 0\n"
1421 "MaxGeometryAtomicCounterBuffers 0\n"
1422 "MaxFragmentAtomicCounterBuffers 1\n"
1423 "MaxCombinedAtomicCounterBuffers 1\n"
1424 "MaxAtomicCounterBufferSize 16384\n"
1425 "MaxTransformFeedbackBuffers 4\n"
1426 "MaxTransformFeedbackInterleavedComponents 64\n"
1427 "MaxCullDistances 8\n"
1428 "MaxCombinedClipAndCullDistances 8\n"
1429 "MaxSamples 4\n"
1430
1431 "nonInductiveForLoops 1\n"
1432 "whileLoops 1\n"
1433 "doWhileLoops 1\n"
1434 "generalUniformIndexing 1\n"
1435 "generalAttributeMatrixVectorIndexing 1\n"
1436 "generalVaryingIndexing 1\n"
1437 "generalSamplerIndexing 1\n"
1438 "generalVariableIndexing 1\n"
1439 "generalConstantMatrixVectorIndexing 1\n"
1440 ;
1441
1442//
1443// *.conf => this is a config file that can set limits/resources
1444//
Tony Barbour6918cd52015-04-09 12:58:51 -06001445bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001446{
1447 if (name.size() < 5)
1448 return false;
1449
1450 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
1451 ConfigFile = name;
1452 return true;
1453 }
1454
1455 return false;
1456}
1457
1458//
1459// Parse either a .conf file provided by the user or the default string above.
1460//
Tony Barbour6918cd52015-04-09 12:58:51 -06001461void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001462{
1463 char** configStrings = 0;
1464 char* config = 0;
1465 if (ConfigFile.size() > 0) {
1466 configStrings = ReadFileData(ConfigFile.c_str());
1467 if (configStrings)
1468 config = *configStrings;
1469 else {
1470 printf("Error opening configuration file; will instead use the default configuration\n");
1471 }
1472 }
1473
1474 if (config == 0) {
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001475 config = (char *) alloca(strlen(DefaultConfig) + 1);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001476 strcpy(config, DefaultConfig);
1477 }
1478
1479 const char* delims = " \t\n\r";
1480 const char* token = strtok(config, delims);
1481 while (token) {
1482 const char* valueStr = strtok(0, delims);
1483 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1484 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1485 return;
1486 }
1487 int value = atoi(valueStr);
1488
1489 if (strcmp(token, "MaxLights") == 0)
1490 Resources.maxLights = value;
1491 else if (strcmp(token, "MaxClipPlanes") == 0)
1492 Resources.maxClipPlanes = value;
1493 else if (strcmp(token, "MaxTextureUnits") == 0)
1494 Resources.maxTextureUnits = value;
1495 else if (strcmp(token, "MaxTextureCoords") == 0)
1496 Resources.maxTextureCoords = value;
1497 else if (strcmp(token, "MaxVertexAttribs") == 0)
1498 Resources.maxVertexAttribs = value;
1499 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1500 Resources.maxVertexUniformComponents = value;
1501 else if (strcmp(token, "MaxVaryingFloats") == 0)
1502 Resources.maxVaryingFloats = value;
1503 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1504 Resources.maxVertexTextureImageUnits = value;
1505 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1506 Resources.maxCombinedTextureImageUnits = value;
1507 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1508 Resources.maxTextureImageUnits = value;
1509 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1510 Resources.maxFragmentUniformComponents = value;
1511 else if (strcmp(token, "MaxDrawBuffers") == 0)
1512 Resources.maxDrawBuffers = value;
1513 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1514 Resources.maxVertexUniformVectors = value;
1515 else if (strcmp(token, "MaxVaryingVectors") == 0)
1516 Resources.maxVaryingVectors = value;
1517 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1518 Resources.maxFragmentUniformVectors = value;
1519 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1520 Resources.maxVertexOutputVectors = value;
1521 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1522 Resources.maxFragmentInputVectors = value;
1523 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1524 Resources.minProgramTexelOffset = value;
1525 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1526 Resources.maxProgramTexelOffset = value;
1527 else if (strcmp(token, "MaxClipDistances") == 0)
1528 Resources.maxClipDistances = value;
1529 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1530 Resources.maxComputeWorkGroupCountX = value;
1531 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1532 Resources.maxComputeWorkGroupCountY = value;
1533 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1534 Resources.maxComputeWorkGroupCountZ = value;
1535 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1536 Resources.maxComputeWorkGroupSizeX = value;
1537 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1538 Resources.maxComputeWorkGroupSizeY = value;
1539 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1540 Resources.maxComputeWorkGroupSizeZ = value;
1541 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1542 Resources.maxComputeUniformComponents = value;
1543 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1544 Resources.maxComputeTextureImageUnits = value;
1545 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1546 Resources.maxComputeImageUniforms = value;
1547 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1548 Resources.maxComputeAtomicCounters = value;
1549 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1550 Resources.maxComputeAtomicCounterBuffers = value;
1551 else if (strcmp(token, "MaxVaryingComponents") == 0)
1552 Resources.maxVaryingComponents = value;
1553 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1554 Resources.maxVertexOutputComponents = value;
1555 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1556 Resources.maxGeometryInputComponents = value;
1557 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1558 Resources.maxGeometryOutputComponents = value;
1559 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1560 Resources.maxFragmentInputComponents = value;
1561 else if (strcmp(token, "MaxImageUnits") == 0)
1562 Resources.maxImageUnits = value;
1563 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1564 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1565 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1566 Resources.maxCombinedShaderOutputResources = value;
1567 else if (strcmp(token, "MaxImageSamples") == 0)
1568 Resources.maxImageSamples = value;
1569 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1570 Resources.maxVertexImageUniforms = value;
1571 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1572 Resources.maxTessControlImageUniforms = value;
1573 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1574 Resources.maxTessEvaluationImageUniforms = value;
1575 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1576 Resources.maxGeometryImageUniforms = value;
1577 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1578 Resources.maxFragmentImageUniforms = value;
1579 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1580 Resources.maxCombinedImageUniforms = value;
1581 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1582 Resources.maxGeometryTextureImageUnits = value;
1583 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1584 Resources.maxGeometryOutputVertices = value;
1585 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1586 Resources.maxGeometryTotalOutputComponents = value;
1587 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1588 Resources.maxGeometryUniformComponents = value;
1589 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1590 Resources.maxGeometryVaryingComponents = value;
1591 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1592 Resources.maxTessControlInputComponents = value;
1593 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1594 Resources.maxTessControlOutputComponents = value;
1595 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1596 Resources.maxTessControlTextureImageUnits = value;
1597 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1598 Resources.maxTessControlUniformComponents = value;
1599 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1600 Resources.maxTessControlTotalOutputComponents = value;
1601 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1602 Resources.maxTessEvaluationInputComponents = value;
1603 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1604 Resources.maxTessEvaluationOutputComponents = value;
1605 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1606 Resources.maxTessEvaluationTextureImageUnits = value;
1607 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1608 Resources.maxTessEvaluationUniformComponents = value;
1609 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1610 Resources.maxTessPatchComponents = value;
1611 else if (strcmp(token, "MaxPatchVertices") == 0)
1612 Resources.maxPatchVertices = value;
1613 else if (strcmp(token, "MaxTessGenLevel") == 0)
1614 Resources.maxTessGenLevel = value;
1615 else if (strcmp(token, "MaxViewports") == 0)
1616 Resources.maxViewports = value;
1617 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1618 Resources.maxVertexAtomicCounters = value;
1619 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1620 Resources.maxTessControlAtomicCounters = value;
1621 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1622 Resources.maxTessEvaluationAtomicCounters = value;
1623 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1624 Resources.maxGeometryAtomicCounters = value;
1625 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1626 Resources.maxFragmentAtomicCounters = value;
1627 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1628 Resources.maxCombinedAtomicCounters = value;
1629 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1630 Resources.maxAtomicCounterBindings = value;
1631 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1632 Resources.maxVertexAtomicCounterBuffers = value;
1633 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1634 Resources.maxTessControlAtomicCounterBuffers = value;
1635 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1636 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1637 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1638 Resources.maxGeometryAtomicCounterBuffers = value;
1639 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1640 Resources.maxFragmentAtomicCounterBuffers = value;
1641 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1642 Resources.maxCombinedAtomicCounterBuffers = value;
1643 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1644 Resources.maxAtomicCounterBufferSize = value;
1645 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1646 Resources.maxTransformFeedbackBuffers = value;
1647 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1648 Resources.maxTransformFeedbackInterleavedComponents = value;
1649 else if (strcmp(token, "MaxCullDistances") == 0)
1650 Resources.maxCullDistances = value;
1651 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1652 Resources.maxCombinedClipAndCullDistances = value;
1653 else if (strcmp(token, "MaxSamples") == 0)
1654 Resources.maxSamples = value;
1655
1656 else if (strcmp(token, "nonInductiveForLoops") == 0)
1657 Resources.limits.nonInductiveForLoops = (value != 0);
1658 else if (strcmp(token, "whileLoops") == 0)
1659 Resources.limits.whileLoops = (value != 0);
1660 else if (strcmp(token, "doWhileLoops") == 0)
1661 Resources.limits.doWhileLoops = (value != 0);
1662 else if (strcmp(token, "generalUniformIndexing") == 0)
1663 Resources.limits.generalUniformIndexing = (value != 0);
1664 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1665 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1666 else if (strcmp(token, "generalVaryingIndexing") == 0)
1667 Resources.limits.generalVaryingIndexing = (value != 0);
1668 else if (strcmp(token, "generalSamplerIndexing") == 0)
1669 Resources.limits.generalSamplerIndexing = (value != 0);
1670 else if (strcmp(token, "generalVariableIndexing") == 0)
1671 Resources.limits.generalVariableIndexing = (value != 0);
1672 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1673 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1674 else
1675 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1676
1677 token = strtok(0, delims);
1678 }
1679 if (configStrings)
1680 FreeFileData(configStrings);
1681}
1682
Tony Barbour6918cd52015-04-09 12:58:51 -06001683void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001684{
1685 if (m_compile_options & EOptionRelaxedErrors)
1686 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1687 if (m_compile_options & EOptionIntermediate)
1688 messages = (EShMessages)(messages | EShMsgAST);
1689 if (m_compile_options & EOptionSuppressWarnings)
1690 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1691}
1692
1693//
1694// Malloc a string of sufficient size and read a string into it.
1695//
Tony Barbour6918cd52015-04-09 12:58:51 -06001696char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001697{
1698 FILE *in;
1699 #if defined(_WIN32) && defined(__GNUC__)
1700 in = fopen(fileName, "r");
1701 int errorCode = in ? 0 : 1;
1702 #else
1703 int errorCode = fopen_s(&in, fileName, "r");
1704 #endif
1705
1706 char *fdata;
1707 int count = 0;
1708 const int maxSourceStrings = 5;
1709 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1710
1711 if (errorCode) {
1712 printf("Error: unable to open input file: %s\n", fileName);
1713 return 0;
1714 }
1715
1716 while (fgetc(in) != EOF)
1717 count++;
1718
1719 fseek(in, 0, SEEK_SET);
1720
1721 if (!(fdata = (char*)malloc(count+2))) {
1722 printf("Error allocating memory\n");
1723 return 0;
1724 }
1725 if (fread(fdata,1,count, in)!=count) {
1726 printf("Error reading input file: %s\n", fileName);
1727 return 0;
1728 }
1729 fdata[count] = '\0';
1730 fclose(in);
1731 if (count == 0) {
1732 return_data[0]=(char*)malloc(count+2);
1733 return_data[0][0]='\0';
1734 m_num_shader_strings = 0;
1735 return return_data;
1736 } else
1737 m_num_shader_strings = 1;
1738
1739 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1740 int ptr_len=0,i=0;
1741 while(count>0){
1742 return_data[i]=(char*)malloc(len+2);
1743 memcpy(return_data[i],fdata+ptr_len,len);
1744 return_data[i][len]='\0';
1745 count-=(len);
1746 ptr_len+=(len);
1747 if(count<len){
1748 if(count==0){
1749 m_num_shader_strings=(i+1);
1750 break;
1751 }
1752 len = count;
1753 }
1754 ++i;
1755 }
1756 return return_data;
1757}
1758
Tony Barbour6918cd52015-04-09 12:58:51 -06001759void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001760{
1761 for(int i=0;i<m_num_shader_strings;i++)
1762 free(data[i]);
1763}
1764
1765//
1766// Deduce the language from the filename. Files must end in one of the
1767// following extensions:
1768//
1769// .vert = vertex
1770// .tesc = tessellation control
1771// .tese = tessellation evaluation
1772// .geom = geometry
1773// .frag = fragment
1774// .comp = compute
1775//
Tony Barbour6918cd52015-04-09 12:58:51 -06001776EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001777{
1778 size_t ext = name.rfind('.');
1779 if (ext == std::string::npos) {
1780 return EShLangVertex;
1781 }
1782
1783 std::string suffix = name.substr(ext + 1, std::string::npos);
1784 if (suffix == "vert")
1785 return EShLangVertex;
1786 else if (suffix == "tesc")
1787 return EShLangTessControl;
1788 else if (suffix == "tese")
1789 return EShLangTessEvaluation;
1790 else if (suffix == "geom")
1791 return EShLangGeometry;
1792 else if (suffix == "frag")
1793 return EShLangFragment;
1794 else if (suffix == "comp")
1795 return EShLangCompute;
1796
1797 return EShLangVertex;
1798}
1799
1800//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001801// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001802//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001803EShLanguage VkTestFramework::FindLanguage(const VkShaderStageFlagBits shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001804{
1805 switch (shader_type) {
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001806 case VK_SHADER_STAGE_VERTEX_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001807 return EShLangVertex;
1808
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001809 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001810 return EShLangTessControl;
1811
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001812 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001813 return EShLangTessEvaluation;
1814
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001815 case VK_SHADER_STAGE_GEOMETRY_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001816 return EShLangGeometry;
1817
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001818 case VK_SHADER_STAGE_FRAGMENT_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001819 return EShLangFragment;
1820
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001821 case VK_SHADER_STAGE_COMPUTE_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001822 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001823
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001824 default:
1825 return EShLangVertex;
1826 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001827}
1828
1829
1830//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001831// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001832// Return value of false means an error was encountered.
1833//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001834bool VkTestFramework::GLSLtoSPV(const VkShaderStageFlagBits shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001835 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001836 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001837{
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001838 glslang::TProgram program;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001839 const char *shaderStrings[1];
1840
1841 // TODO: Do we want to load a special config file depending on the
1842 // shader source? Optional name maybe?
1843 // SetConfigFile(fileName);
1844
1845 ProcessConfigFile();
1846
1847 EShMessages messages = EShMsgDefault;
1848 SetMessageOptions(messages);
1849
1850 EShLanguage stage = FindLanguage(shader_type);
1851 glslang::TShader* shader = new glslang::TShader(stage);
1852
1853 shaderStrings[0] = pshader;
1854 shader->setStrings(shaderStrings, 1);
1855
1856 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1857
Cody Northrop195d6622014-11-03 12:54:37 -07001858 if (! (m_compile_options & EOptionSuppressInfolog)) {
1859 puts(shader->getInfoLog());
1860 puts(shader->getInfoDebugLog());
1861 }
1862
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001863 return false; // something didn't work
1864 }
1865
1866 program.addShader(shader);
1867
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001868
1869 //
1870 // Program-level processing...
1871 //
1872
Cody Northrop195d6622014-11-03 12:54:37 -07001873 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001874
Cody Northrop195d6622014-11-03 12:54:37 -07001875 if (! (m_compile_options & EOptionSuppressInfolog)) {
1876 puts(shader->getInfoLog());
1877 puts(shader->getInfoDebugLog());
1878 }
1879
1880 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001881 }
1882
1883 if (m_compile_options & EOptionDumpReflection) {
1884 program.buildReflection();
1885 program.dumpReflection();
1886 }
1887
Cody Northrop5a95b472015-06-03 13:01:54 -06001888 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1889
1890 //
1891 // Test the different modes of SPIR-V modification
1892 //
1893 if (this->m_canonicalize_spv) {
1894 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1895 }
1896
1897 if (this->m_strip_spv) {
1898 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1899 }
1900
1901 if (this->m_do_everything_spv) {
1902 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1903 }
1904
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001905 delete shader;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001906
1907 return true;
1908}
1909
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001910
1911
Tony Barbour6918cd52015-04-09 12:58:51 -06001912VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001913 m_width( 0 ),
1914 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001915 m_data( NULL ),
1916 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001917{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001918}
1919
Tony Barbour6918cd52015-04-09 12:58:51 -06001920VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001921{
1922
1923}
1924
Tony Barbour6918cd52015-04-09 12:58:51 -06001925VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001926{
1927 m_title = copyin.m_title;
1928 m_width = copyin.m_width;
1929 m_height = copyin.m_height;
1930 m_data_size = copyin.m_data_size;
1931 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1932}
1933
Tony Barbour6918cd52015-04-09 12:58:51 -06001934ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001935{
Tony Barbour6918cd52015-04-09 12:58:51 -06001936 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1937 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001938 return output;
1939}
1940
Tony Barbour6918cd52015-04-09 12:58:51 -06001941VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001942{
1943 m_title = rhs.m_title;
1944 m_width = rhs.m_width;
1945 m_height = rhs.m_height;
1946 m_data_size = rhs.m_data_size;
1947 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001948 return *this;
1949}
1950
Tony Barbour6918cd52015-04-09 12:58:51 -06001951int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001952{
1953 if( this->m_data != rhs.m_data) return 0;
1954 return 1;
1955}
1956
1957// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001958int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001959{
1960 if( this->m_data_size < rhs.m_data_size ) return 1;
1961 return 0;
1962}
1963