blob: ec2c41d003e0cba0112115c6c3aae50e97be99a5 [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);
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700106 VkFormat GetPresentFormat();
Tony Barboure1837292015-12-07 13:46:11 -0700107 void DestroyMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -0600108 void CreateSwapchain();
Tony Barbourbd094ce2015-10-23 11:00:15 -0600109 void SetImageLayout(VkImage image, VkImageAspectFlags aspectMask,
110 VkImageLayout old_image_layout, VkImageLayout new_image_layout);
Chia-I Wuf8693382015-04-16 22:02:10 +0800111 void TearDown();
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600112#ifdef _WIN32
113 static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
Tony Barbourc16220e2016-01-07 11:41:10 -0700114 void CreateMyWindow(bool register_class = true);
115#else
116 void CreateMyWindow();
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600117#endif
118
Chia-I Wuf8693382015-04-16 22:02:10 +0800119
120protected:
121 vk_testing::Device &m_device;
122 vk_testing::Queue &m_queue;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800123 vk_testing::CommandPool m_cmdpool;
124 vk_testing::CommandBuffer m_cmdbuf;
Chia-I Wuf8693382015-04-16 22:02:10 +0800125
126private:
Ian Elliottc11750d2015-10-30 13:24:12 -0600127 VkInstance m_instance;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600128#ifdef _WIN32
129 HINSTANCE m_connection; // hInstance - Windows Instance
130 HWND m_window; // hWnd - window handle
131
132#else
Chia-I Wuf8693382015-04-16 22:02:10 +0800133 xcb_connection_t *m_connection;
134 xcb_screen_t *m_screen;
135 xcb_window_t m_window;
136 xcb_intern_atom_reply_t *m_atom_wm_delete_window;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600137#endif
Ian Elliottc11750d2015-10-30 13:24:12 -0600138 VkSurfaceKHR m_surface;
Courtney Goeltzenleuchterd6079ec2015-04-22 10:09:35 -0600139 std::list<VkTestImageRecord> m_images;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600140 uint32_t m_present_queue_node_index;
Chia-I Wuf8693382015-04-16 22:02:10 +0800141
Ian Elliott7e40db92015-08-21 15:09:33 -0600142 PFN_vkGetPhysicalDeviceSurfaceSupportKHR m_fpGetPhysicalDeviceSurfaceSupportKHR;
Ian Elliottc11750d2015-10-30 13:24:12 -0600143 PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR m_fpGetPhysicalDeviceSurfaceCapabilitiesKHR;
144 PFN_vkGetPhysicalDeviceSurfaceFormatsKHR m_fpGetPhysicalDeviceSurfaceFormatsKHR;
145 PFN_vkGetPhysicalDeviceSurfacePresentModesKHR m_fpGetPhysicalDeviceSurfacePresentModesKHR;
Ian Elliott7e40db92015-08-21 15:09:33 -0600146 PFN_vkCreateSwapchainKHR m_fpCreateSwapchainKHR;
147 PFN_vkDestroySwapchainKHR m_fpDestroySwapchainKHR;
148 PFN_vkGetSwapchainImagesKHR m_fpGetSwapchainImagesKHR;
149 PFN_vkAcquireNextImageKHR m_fpAcquireNextImageKHR;
150 PFN_vkQueuePresentKHR m_fpQueuePresentKHR;
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700151 PFN_vkDestroySurfaceKHR m_fpDestroySurfaceKHR;
Ian Elliott7e40db92015-08-21 15:09:33 -0600152 uint32_t m_swapchainImageCount;
153 VkSwapchainKHR m_swap_chain;
154 SwapchainBuffers *m_buffers;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600155 VkFormat m_format;
Ian Elliott7e40db92015-08-21 15:09:33 -0600156 VkColorSpaceKHR m_color_space;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600157
158 uint32_t m_current_buffer;
Chia-I Wuf8693382015-04-16 22:02:10 +0800159
160 bool m_quit;
161 bool m_pause;
162
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600163 int m_width;
164 int m_height;
Chia-I Wuf8693382015-04-16 22:02:10 +0800165
166 std::list<VkTestImageRecord>::iterator m_display_image;
167
168 void Display();
Tony Barbourfeb61962015-09-21 15:17:33 -0600169#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800170 void HandleEvent(xcb_generic_event_t *event);
Tony Barbourfeb61962015-09-21 15:17:33 -0600171#endif
Chia-I Wuf8693382015-04-16 22:02:10 +0800172};
173
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600174#ifndef _WIN32
175
176#include <errno.h>
177
178int fopen_s(
179 FILE** pFile,
180 const char* filename,
181 const char* mode
182)
183{
184 if (!pFile || !filename || !mode) {
185 return EINVAL;
186 }
187
188 FILE* f = fopen(filename, mode);
189 if (! f) {
190 if (errno != 0) {
191 return errno;
192 } else {
193 return ENOENT;
194 }
195 }
196 *pFile = f;
197
198 return 0;
199}
200
201#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600202
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600203
204
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600205// Set up environment for GLSL compiler
206// Must be done once per process
207void TestEnvironment::SetUp()
208{
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600209 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600210 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800211
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600212 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600213}
214
215void TestEnvironment::TearDown()
216{
217 glslang::FinalizeProcess();
218}
219
Tony Barbour6918cd52015-04-09 12:58:51 -0600220VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600221 m_compile_options( 0 ),
222 m_num_shader_strings( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600223{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600224
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600225}
226
Tony Barbour6918cd52015-04-09 12:58:51 -0600227VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600228{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600229
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600230}
231
232// Define all the static elements
Cody Northropa3673cf2015-06-09 13:00:45 -0600233bool VkTestFramework::m_show_images = false;
234bool VkTestFramework::m_save_images = false;
235bool VkTestFramework::m_compare_images = false;
236bool VkTestFramework::m_use_glsl = false;
237bool VkTestFramework::m_canonicalize_spv = false;
238bool VkTestFramework::m_strip_spv = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600239bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour6918cd52015-04-09 12:58:51 -0600240int VkTestFramework::m_width = 0;
241int VkTestFramework::m_height = 0;
242std::list<VkTestImageRecord> VkTestFramework::m_images;
243std::list<VkTestImageRecord>::iterator VkTestFramework::m_display_image;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600244int m_display_image_idx = 0;
245
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600246bool VkTestFramework::optionMatch(const char* option, char* optionLine)
247{
248 if (strncmp(option, optionLine, strlen(option)) == 0)
249 return true;
250 else
251 return false;
252}
253
Tony Barbour6918cd52015-04-09 12:58:51 -0600254void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600255{
256 int i, n;
257
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600258 for (i=1, n=1; i< *argc; i++) {
259 if (optionMatch("--show-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600260 m_show_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600261 else if (optionMatch("--save-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600262 m_save_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600263 else if (optionMatch("--no-SPV", argv[i]))
264 m_use_glsl = true;
265 else if (optionMatch("--strip-SPV", argv[i]))
266 m_strip_spv = true;
267 else if (optionMatch("--canonicalize-SPV", argv[i]))
268 m_canonicalize_spv = true;
269 else if (optionMatch("--compare-images", argv[i]))
Tony Barbour247bf372014-10-30 14:29:04 -0600270 m_compare_images = true;
Tony Barbour247bf372014-10-30 14:29:04 -0600271
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600272 else if (optionMatch("--help", argv[i]) ||
273 optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700274 printf("\nOther options:\n");
275 printf("\t--show-images\n"
276 "\t\tDisplay test images in viewer after tests complete.\n");
277 printf("\t--save-images\n"
278 "\t\tSave tests images as ppm files in current working directory.\n"
279 "\t\tUsed to generate golden images for compare-images.\n");
280 printf("\t--compare-images\n"
281 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barboura98d3932014-12-11 09:52:49 -0700282 "\t\tAlso saves the generated test image in current working\n"
283 "\t\t\tdirectory but only if the image is different from the golden\n"
284 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
285 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700286 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600287 printf("\t--no-SPV\n"
288 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600289 printf("\t--strip-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600290 "\t\tStrip SPIR-V debug information (line numbers, names, etc).\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600291 printf("\t--canonicalize-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600292 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600293 exit(0);
294 } else {
295 printf("\nUnrecognized option: %s\n", argv[i]);
296 printf("\nUse --help or -h for option list.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700297 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700298 }
299
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600300 /*
301 * Since the above "consume" inputs, update argv
302 * so that it contains the trimmed list of args for glutInit
303 */
304
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600305 argv[n] = argv[i];
306 n++;
307 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600308}
309
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700310VkFormat VkTestFramework::GetFormat(VkInstance instance, vk_testing::Device *device)
311{
312 VkFormatProperties format_props;
313 if (!m_show_images)
314 {
315 vkGetPhysicalDeviceFormatProperties(device->phy().handle(), VK_FORMAT_B8G8R8A8_UNORM, &format_props);
316 if (format_props.linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ||
317 format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)
318 {
319 return VK_FORMAT_B8G8R8A8_UNORM;
320 }
321 vkGetPhysicalDeviceFormatProperties(device->phy().handle(), VK_FORMAT_R8G8B8A8_UNORM, &format_props);
322 if (format_props.linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ||
323 format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)
324 {
325 return VK_FORMAT_R8G8B8A8_UNORM;
326 }
327 printf("Error - device does not support VK_FORMAT_B8G8R8A8_UNORM nor VK_FORMAT_R8G8B8A8_UNORM - exiting\n");
328 exit(0);
329 }
330 else
331 {
332 /* To find which formats are presentable, you have to provide a surface to vkGetPhysicalDeviceSurfaceFormatsKHR */
333 /* To create a surface, you need a window. Use the present object to create a window, use that to create a */
334 /* KHR surface, and then find out what formats are presentable */
335 VkFormat presentFormat;
336 std::list<VkTestImageRecord> list;
337 VkTestImageRecord placeholder;
338 /* Use a dummy image record with non-zero area so the window will create on Windows */
339 placeholder.m_width = placeholder.m_height = 20;
340 list.push_back(placeholder);
341 TestFrameworkVkPresent vkPresent(*device);
342 vkPresent.InitPresentFramework(list, instance);
343 vkPresent.CreateMyWindow();
344 presentFormat = vkPresent.GetPresentFormat();
Tony Barboure1837292015-12-07 13:46:11 -0700345 vkPresent.DestroyMyWindow();
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700346 return presentFormat;
347 }
348}
349
Tony Barbour6918cd52015-04-09 12:58:51 -0600350void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600351{
352 string filename;
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600353 uint32_t x, y;
Tony Barbour6918cd52015-04-09 12:58:51 -0600354 VkImageObj displayImage(image->device());
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600355 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbour84d448c2015-04-02 14:02:33 -0600356
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800357 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 -0600358 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600359
360 filename.append(basename);
361 filename.append(".ppm");
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600362
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600363 const VkImageSubresource sr = {
Courtney Goeltzenleuchter908e7672015-10-21 17:00:51 -0600364 VK_IMAGE_ASPECT_COLOR_BIT, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600365 };
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600366 VkSubresourceLayout sr_layout;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600367
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600368 vkGetImageSubresourceLayout(image->device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600369
Tony Barbour84d448c2015-04-02 14:02:33 -0600370 char *ptr;
Chia-I Wu681d7a02015-07-03 13:44:34 +0800371 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600372 ptr += sr_layout.offset;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600373 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600374 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
375
376 file << "P6\n";
Tony Barbourfeb61962015-09-21 15:17:33 -0600377 file << displayImage.width() << " ";
Tony Barbour84d448c2015-04-02 14:02:33 -0600378 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600379 file << 255 << "\n";
380
Tony Barbour84d448c2015-04-02 14:02:33 -0600381 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700382 const int *row = (const int *) ptr;
383 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600384
Tony Barbourd1c35722015-04-16 15:59:00 -0600385 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700386 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600387 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700388 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
389 file.write((char *) &swapped, 3);
390 row++;
391 }
392 }
Tony Barbourd1c35722015-04-16 15:59:00 -0600393 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700394 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600395 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700396 file.write((char *) row, 3);
397 row++;
398 }
399 }
400 else {
401 printf("Unrecognized image format - will not write image files");
402 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600403 }
404
405 ptr += sr_layout.rowPitch;
406 }
407
408 file.close();
Chia-I Wu681d7a02015-07-03 13:44:34 +0800409 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600410}
411
Tony Barbour6918cd52015-04-09 12:58:51 -0600412void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour247bf372014-10-30 14:29:04 -0600413{
414
415 MagickWand *magick_wand_1;
416 MagickWand *magick_wand_2;
417 MagickWand *compare_wand;
418 MagickBooleanType status;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600419 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600420 double differenz;
421
Tony Barbour4ab45422014-12-10 17:00:20 -0700422 if (getenv("RENDERTEST_GOLDEN_DIR"))
423 {
424 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
425 }
426
Tony Barbour247bf372014-10-30 14:29:04 -0600427 MagickWandGenesis();
428 magick_wand_1=NewMagickWand();
429 sprintf(testimage,"%s.ppm",basename);
430 status=MagickReadImage(magick_wand_1,testimage);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600431 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour247bf372014-10-30 14:29:04 -0600432
433
434 MagickWandGenesis();
435 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700436 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600437 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600438 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour247bf372014-10-30 14:29:04 -0600439
Tony Barbour247bf372014-10-30 14:29:04 -0600440 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
441 if (differenz != 0.0)
442 {
443 char difference[256];
444
445 sprintf(difference,"%s-diff.ppm",basename);
446 status = MagickWriteImage(compare_wand, difference);
447 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
448 }
449 DestroyMagickWand(compare_wand);
450
451 DestroyMagickWand(magick_wand_1);
452 DestroyMagickWand(magick_wand_2);
453 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700454
455 if (differenz == 0.0)
456 {
457 /*
458 * If test image and golden image match, we do not need to
459 * keep around the test image.
460 */
461 remove(testimage);
462 }
Tony Barbour247bf372014-10-30 14:29:04 -0600463}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600464
Tony Barbour6918cd52015-04-09 12:58:51 -0600465void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600466{
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600467 VkSubresourceLayout sr_layout;
468 char *ptr;
469 VkTestImageRecord record;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600470 VkImageObj displayImage(image->device());
471 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
472
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800473 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 -0600474
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600475 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600476
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600477 const VkImageSubresource sr = {
Courtney Goeltzenleuchter908e7672015-10-21 17:00:51 -0600478 VK_IMAGE_ASPECT_COLOR_BIT, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600479 };
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600480
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600481 vkGetImageSubresourceLayout(displayImage.device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600482
Chia-I Wu681d7a02015-07-03 13:44:34 +0800483 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600484 ptr += sr_layout.offset;
485
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600486 record.m_title.append(comment);
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600487 record.m_width = displayImage.width();
488 record.m_height = displayImage.height();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600489 // TODO: Need to make this more robust to handle different image formats
Tony-LunarG399dfca2015-05-19 14:08:26 -0600490 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600491 record.m_data = malloc(record.m_data_size);
492 memcpy(record.m_data, ptr, record.m_data_size);
493 m_images.push_back(record);
494 m_display_image = --m_images.end();
495
Chia-I Wu681d7a02015-07-03 13:44:34 +0800496 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600497}
498
Tony Barbour6918cd52015-04-09 12:58:51 -0600499void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600500{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600501 for (int32_t i = 0; i < images.size(); i++) {
502 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600503 }
504}
505
Tony Barbour6918cd52015-04-09 12:58:51 -0600506void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600507{
508 const ::testing::TestInfo* const test_info =
509 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600510 ostringstream filestream;
511 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600512
Tony Barbour247bf372014-10-30 14:29:04 -0600513 m_width = 40;
514
515 if (strcmp(test_info->name(), m_testName.c_str())) {
516 filestream << test_info->name();
517 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700518 m_frameNum = 2;
519 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600520 }
521 else {
522 filestream << test_info->name() << "-" << m_frameNum;
523 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700524 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600525 }
526
Tony Barbour247bf372014-10-30 14:29:04 -0600527 // ToDo - scrub string for bad characters
528
529 if (m_save_images || m_compare_images) {
530 WritePPM(filename.c_str(), image);
531 if (m_compare_images) {
532 Compare(filename.c_str(), image);
533 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600534 }
535
536 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600537 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600538 }
539}
540
Chia-I Wuf8693382015-04-16 22:02:10 +0800541TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
542 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700543 m_queue(*m_device.graphics_queues()[0]),
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800544 m_cmdpool(m_device, vk_testing::CommandPool::create_info(m_device.graphics_queue_node_index_)),
545 m_cmdbuf(m_device, vk_testing::CommandBuffer::create_info(m_cmdpool.handle()))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600546{
Tony Barbour96db8822015-02-25 12:28:39 -0700547 m_quit = false;
548 m_pause = false;
549 m_width = 0;
550 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600551}
552
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700553VkFormat TestFrameworkVkPresent::GetPresentFormat()
554{
555 uint32_t formatCount;
556 VkResult U_ASSERT_ONLY res;
557 VkSurfaceKHR surface;
558 VkFormat returnFormat;
559
560#ifdef _WIN32
Ian Elliotta8914ac2015-12-11 14:05:35 -0700561 VkWin32SurfaceCreateInfoKHR createInfo;
562 createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
563 createInfo.pNext = NULL;
564 createInfo.flags = 0;
Jon Ashburn88215af2015-12-24 17:08:01 -0700565 createInfo.hinstance = m_connection;
566 createInfo.hwnd = m_window;
Ian Elliotta8914ac2015-12-11 14:05:35 -0700567
568 res = vkCreateWin32SurfaceKHR(m_instance, &createInfo, NULL, &surface);
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700569#else // _WIN32
Ian Elliotta8914ac2015-12-11 14:05:35 -0700570 VkXcbSurfaceCreateInfoKHR createInfo;
571 createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
572 createInfo.pNext = NULL;
573 createInfo.flags = 0;
574 createInfo.connection = m_connection;
575 createInfo.window = m_window;
576
577 res = vkCreateXcbSurfaceKHR(m_instance, &createInfo, NULL, &surface);
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700578#endif // _WIN32
579 assert(res == VK_SUCCESS);
580
581 m_fpGetPhysicalDeviceSurfaceFormatsKHR(
582 m_device.phy().handle(),
583 surface,
584 &formatCount, NULL);
585 VkSurfaceFormatKHR *surfFormats =
586 (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
587 m_fpGetPhysicalDeviceSurfaceFormatsKHR(
588 m_device.phy().handle(),
589 surface,
590 &formatCount, surfFormats);
591
592 m_fpDestroySurfaceKHR(m_instance, surface, NULL);
593
594 returnFormat = surfFormats[0].format;
595 free(surfFormats);
596 return returnFormat;
597}
598
Tony Barbour6918cd52015-04-09 12:58:51 -0600599void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600600{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600601 VkResult U_ASSERT_ONLY err;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600602 vk_testing::Buffer buf;
603 void *dest_ptr;
604
Tony Barbour6a3faf02015-07-23 10:36:18 -0600605 VkSemaphore presentCompleteSemaphore;
606 VkSemaphoreCreateInfo presentCompleteSemaphoreCreateInfo = {};
607 presentCompleteSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
608 presentCompleteSemaphoreCreateInfo.pNext = NULL;
609 presentCompleteSemaphoreCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
610
611
612 err = vkCreateSemaphore(m_device.handle(),
613 &presentCompleteSemaphoreCreateInfo,
Chia-I Wuf7458c52015-10-26 21:10:41 +0800614 NULL, &presentCompleteSemaphore);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600615 assert(!err);
616
617 // Get the index of the next available swapchain image:
Ian Elliott7e40db92015-08-21 15:09:33 -0600618 err = m_fpAcquireNextImageKHR(m_device.handle(), m_swap_chain,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600619 UINT64_MAX,
620 presentCompleteSemaphore,
Ian Elliottc11750d2015-10-30 13:24:12 -0600621 VK_NULL_HANDLE,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600622 &m_current_buffer);
Ian Elliott7e40db92015-08-21 15:09:33 -0600623 // TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
Tony Barbour6a3faf02015-07-23 10:36:18 -0600624 // return codes
625 assert(!err);
626
Tony-LunarG399dfca2015-05-19 14:08:26 -0600627 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Cody Northrop7fb43862015-06-22 14:56:14 -0600628 buf.init_as_src(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800629 dest_ptr = buf.memory().map();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600630 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800631 buf.memory().unmap();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600632
633 m_cmdbuf.begin();
Tony Barbourbd094ce2015-10-23 11:00:15 -0600634 VkImageMemoryBarrier memoryBarrier = {};
635 memoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
636 memoryBarrier.pNext = NULL;
Tony Barbour90ceffb2016-01-05 09:59:05 -0700637 memoryBarrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
638 memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
Ian Elliott1dcd1092015-11-17 17:29:40 -0700639 memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800640 memoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600641 memoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800642 memoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600643 memoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
644 memoryBarrier.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800645 memoryBarrier.subresourceRange.levelCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600646 memoryBarrier.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800647 memoryBarrier.subresourceRange.layerCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -0600648 memoryBarrier.image = m_buffers[m_current_buffer].image;
649 VkImageMemoryBarrier *pmemory_barrier = &memoryBarrier;
Tony Barbour90ceffb2016-01-05 09:59:05 -0700650 vkCmdPipelineBarrier(m_cmdbuf.handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
Jon Ashburnf19916e2016-01-11 13:12:43 -0700651 0, 0, NULL, 0, NULL, 1, pmemory_barrier);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600652
653 VkBufferImageCopy region = {};
Tony Barbourd800bbd2015-11-05 10:54:44 -0700654 region.bufferRowLength = m_display_image->m_width;
655 region.bufferImageHeight = m_display_image->m_height;
656 region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
657 region.imageSubresource.layerCount = 1;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600658 region.imageExtent.height = m_display_image->m_height;
659 region.imageExtent.width = m_display_image->m_width;
660 region.imageExtent.depth = 1;
661
Chia-I Wube2b9172015-07-03 11:49:42 +0800662 vkCmdCopyBufferToImage(m_cmdbuf.handle(),
Chia-I Wu681d7a02015-07-03 13:44:34 +0800663 buf.handle(),
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800664 m_buffers[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600665 1, &region);
Tony Barbourbd094ce2015-10-23 11:00:15 -0600666
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800667 memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
Ian Elliott1dcd1092015-11-17 17:29:40 -0700668 memoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
Tony Barbour90ceffb2016-01-05 09:59:05 -0700669 memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
670 memoryBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
671 vkCmdPipelineBarrier(m_cmdbuf.handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
Jon Ashburnf19916e2016-01-11 13:12:43 -0700672 0, 0, NULL, 0, NULL, 1, pmemory_barrier);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600673 m_cmdbuf.end();
674
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800675 VkCommandBuffer cmdBufs[1];
Chia-I Wube2b9172015-07-03 11:49:42 +0800676 cmdBufs[0] = m_cmdbuf.handle();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600677
Chia-I Wua690b412015-10-29 22:01:53 +0800678 // Wait for the present complete semaphore to be signaled to ensure
679 // that the image won't be rendered to until the presentation
680 // engine has fully released ownership to the application, and it is
681 // okay to render to the image.
Tony Barbour67e99152015-07-10 14:10:27 -0600682 VkFence nullFence = { VK_NULL_HANDLE };
Jon Ashburn8c0c1432015-12-31 12:32:16 -0700683 VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600684 VkSubmitInfo submit_info;
Chia-I Wuf9be13c2015-10-26 20:37:06 +0800685 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
686 submit_info.pNext = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +0800687 submit_info.waitSemaphoreCount = 1;
Jon Ashburn7f9716c2015-12-30 16:42:50 -0700688 submit_info.pWaitSemaphores = &presentCompleteSemaphore;
689 submit_info.pWaitDstStageMask = &pipe_stage_flags;
Chia-I Wud50a7d72015-10-26 20:48:51 +0800690 submit_info.commandBufferCount = 1;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600691 submit_info.pCommandBuffers = cmdBufs;
Chia-I Wud50a7d72015-10-26 20:48:51 +0800692 submit_info.signalSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600693 submit_info.pSignalSemaphores = NULL;
694
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -0600695 vkQueueSubmit(m_queue.handle(), 1, &submit_info, nullFence);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600696 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700697
Chia-I Wuf7458c52015-10-26 21:10:41 +0800698 vkDestroySemaphore(m_device.handle(), presentCompleteSemaphore, NULL);
Chia-I Wua690b412015-10-29 22:01:53 +0800699
Ian Elliott7e40db92015-08-21 15:09:33 -0600700 VkPresentInfoKHR present = {};
701 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600702 present.pNext = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600703 present.swapchainCount = 1;
Ian Elliottc11750d2015-10-30 13:24:12 -0600704 present.pSwapchains = & m_swap_chain;
705 present.pImageIndices = &m_current_buffer;
Tony Barbour96db8822015-02-25 12:28:39 -0700706
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600707#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800708 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700709 XCB_PROP_MODE_REPLACE,
710 m_window,
711 XCB_ATOM_WM_NAME,
712 XCB_ATOM_STRING,
713 8,
714 m_display_image->m_title.size(),
715 m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600716#endif
Jon Ashburn07daee72015-05-21 18:13:33 -0600717
Ian Elliott7e40db92015-08-21 15:09:33 -0600718 err = m_fpQueuePresentKHR(m_queue.handle(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700719 assert(!err);
720
721 m_queue.wait();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600722 m_current_buffer = (m_current_buffer + 1) % 2;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600723}
724
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600725#ifdef _WIN32
Tony-LunarG399dfca2015-05-19 14:08:26 -0600726# define PREVIOUSLY_DOWN 1<<29
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600727// MS-Windows event handling function:
728LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
729 UINT uMsg,
730 WPARAM wParam,
731 LPARAM lParam)
732{
733
734 switch(uMsg)
735 {
736 case WM_CLOSE:
737 PostQuitMessage(0);
738 break;
739
740 case WM_PAINT:
741 {
742 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
743 if (me) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600744 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600745 me->Display();
746 }
747 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600748 break;
749
750 case WM_KEYDOWN:
751 {
752 if (lParam & (PREVIOUSLY_DOWN)){
753 break;
754 }
755 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
756 // the window, we put the this pointer into the window's user data so we could get it back now
757 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
758 switch (wParam)
759 {
760 case VK_ESCAPE: me->m_quit = true;
761 break;
762
763 case VK_LEFT: // left arrow key
764 if (me->m_display_image == me->m_images.begin()) {
765 me->m_display_image = --me->m_images.end();
766 }
767 else {
768 --me->m_display_image;
769 }
770 break;
771
772 case VK_RIGHT: // right arrow key
773 ++me->m_display_image;
774 if (me->m_display_image == me->m_images.end()) {
775 me->m_display_image = me->m_images.begin();
776 }
777 break;
778
779 default:
780 break;
781 }
782 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
783 me->Display();
784 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600785 }
786 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
787}
788
789void TestFrameworkVkPresent::Run()
790{
791 MSG msg; // message
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600792
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600793 /* main message loop*/
Tony-LunarG399dfca2015-05-19 14:08:26 -0600794 while(! m_quit) {
795 GetMessage(&msg, m_window, 0, 0);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600796 if (msg.message == WM_QUIT) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600797 m_quit = true; //if found, quit app
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600798 } else {
799 /* Translate and dispatch to event queue*/
800 TranslateMessage(&msg);
801 DispatchMessage(&msg);
802 }
803 }
804}
805
806#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600807void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600808{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600809 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700810 switch (event_code) {
811 case XCB_EXPOSE:
812 Display(); // TODO: handle resize
813 break;
814 case XCB_CLIENT_MESSAGE:
815 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
816 (m_atom_wm_delete_window)->atom) {
817 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600818 }
819 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700820 case XCB_KEY_RELEASE:
821 {
822 const xcb_key_release_event_t *key =
823 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600824
Tony Barbour96db8822015-02-25 12:28:39 -0700825 switch (key->detail) {
826 case 0x9: // Escape
827 m_quit = true;
828 break;
829 case 0x71: // left arrow key
830 if (m_display_image == m_images.begin()) {
831 m_display_image = --m_images.end();
832 } else {
833 --m_display_image;
834 }
835 break;
836 case 0x72: // right arrow key
837 ++m_display_image;
838 if (m_display_image == m_images.end()) {
839 m_display_image = m_images.begin();
840 }
841 break;
842 case 0x41:
843 m_pause = !m_pause;
844 break;
845 }
846 Display();
847 }
848 break;
849 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600850 break;
851 }
Tony Barbour96db8822015-02-25 12:28:39 -0700852}
853
Tony Barbour6918cd52015-04-09 12:58:51 -0600854void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700855{
Chia-I Wuf8693382015-04-16 22:02:10 +0800856 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700857
858 while (! m_quit) {
859 xcb_generic_event_t *event;
860
861 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800862 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700863 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800864 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700865 }
866 if (event) {
867 HandleEvent(event);
868 free(event);
869 }
870 }
871}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600872#endif // _WIN32
Tony Barbour96db8822015-02-25 12:28:39 -0700873
Ian Elliott7e40db92015-08-21 15:09:33 -0600874void TestFrameworkVkPresent::CreateSwapchain()
Tony Barbour96db8822015-02-25 12:28:39 -0700875{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600876 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700877
Tony-LunarG399dfca2015-05-19 14:08:26 -0600878 m_display_image = m_images.begin();
879 m_current_buffer = 0;
880
Ian Elliottc11750d2015-10-30 13:24:12 -0600881 // Create the WSI surface:
Ian Elliott1a3845b2015-07-06 14:33:04 -0600882#ifdef _WIN32
Ian Elliotta8914ac2015-12-11 14:05:35 -0700883 VkWin32SurfaceCreateInfoKHR createInfo;
884 createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
885 createInfo.pNext = NULL;
886 createInfo.flags = 0;
Jon Ashburn88215af2015-12-24 17:08:01 -0700887 createInfo.hinstance = m_connection;
888 createInfo.hwnd = m_window;
Ian Elliotta8914ac2015-12-11 14:05:35 -0700889
890 err = vkCreateWin32SurfaceKHR(m_instance, &createInfo, NULL, &m_surface);
Ian Elliott1a3845b2015-07-06 14:33:04 -0600891#else // _WIN32
Ian Elliotta8914ac2015-12-11 14:05:35 -0700892 VkXcbSurfaceCreateInfoKHR createInfo;
893 createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
894 createInfo.pNext = NULL;
895 createInfo.flags = 0;
896 createInfo.connection = m_connection;
897 createInfo.window = m_window;
898
899 err = vkCreateXcbSurfaceKHR(m_instance, &createInfo, NULL, &m_surface);
Ian Elliott1a3845b2015-07-06 14:33:04 -0600900#endif // _WIN32
Ian Elliottc11750d2015-10-30 13:24:12 -0600901 assert(!err);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600902
903 // Iterate over each queue to learn whether it supports presenting to WSI:
904 VkBool32 supportsPresent;
905 m_present_queue_node_index = UINT32_MAX;
906 std::vector<vk_testing::Queue *> queues = m_device.graphics_queues();
907 for (int i=0; i < queues.size(); i++)
908 {
909 int family_index = queues[i]->get_family_index();
Ian Elliott7e40db92015-08-21 15:09:33 -0600910 m_fpGetPhysicalDeviceSurfaceSupportKHR(m_device.phy().handle(),
Tony Barbour6a3faf02015-07-23 10:36:18 -0600911 family_index,
Ian Elliottc11750d2015-10-30 13:24:12 -0600912 m_surface,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600913 &supportsPresent);
914 if (supportsPresent) {
915 m_present_queue_node_index = family_index;
916 }
917 }
918
919 assert(m_present_queue_node_index != UINT32_MAX);
920
921
922 // Get the list of VkFormat's that are supported:
Ian Elliott8b139792015-08-07 11:51:12 -0600923 uint32_t formatCount;
Ian Elliottc11750d2015-10-30 13:24:12 -0600924 err = m_fpGetPhysicalDeviceSurfaceFormatsKHR(m_device.phy().handle(),
925 m_surface,
Ian Elliott8b139792015-08-07 11:51:12 -0600926 &formatCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600927 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600928 VkSurfaceFormatKHR *surfFormats =
929 (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
Ian Elliottc11750d2015-10-30 13:24:12 -0600930 err = m_fpGetPhysicalDeviceSurfaceFormatsKHR(m_device.phy().handle(),
931 m_surface,
Ian Elliott8b139792015-08-07 11:51:12 -0600932 &formatCount, surfFormats);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600933 assert(!err);
934 // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
935 // the surface has no preferred format. Otherwise, at least one
936 // supported format will be returned.
Tony Barbour6a3faf02015-07-23 10:36:18 -0600937 if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED)
938 {
939 m_format = VK_FORMAT_B8G8R8A8_UNORM;
940 }
941 else
942 {
943 assert(formatCount >= 1);
944 m_format = surfFormats[0].format;
945 }
Ian Elliott8b139792015-08-07 11:51:12 -0600946 m_color_space = surfFormats[0].colorSpace;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600947
Ian Elliottc11750d2015-10-30 13:24:12 -0600948 // Check the surface capabilities and formats
949 VkSurfaceCapabilitiesKHR surfCapabilities;
950 err = m_fpGetPhysicalDeviceSurfaceCapabilitiesKHR(m_device.phy().handle(),
951 m_surface,
952 &surfCapabilities);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600953 assert(!err);
954
Ian Elliott8b139792015-08-07 11:51:12 -0600955 uint32_t presentModeCount;
Ian Elliottc11750d2015-10-30 13:24:12 -0600956 err = m_fpGetPhysicalDeviceSurfacePresentModesKHR(m_device.phy().handle(),
957 m_surface,
Ian Elliott8b139792015-08-07 11:51:12 -0600958 &presentModeCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600959 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600960 VkPresentModeKHR *presentModes =
961 (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
Ian Elliott8b139792015-08-07 11:51:12 -0600962 assert(presentModes);
Ian Elliottc11750d2015-10-30 13:24:12 -0600963 err = m_fpGetPhysicalDeviceSurfacePresentModesKHR(m_device.phy().handle(),
964 m_surface,
Ian Elliott8b139792015-08-07 11:51:12 -0600965 &presentModeCount, presentModes);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600966 assert(!err);
967
Ian Elliott7e40db92015-08-21 15:09:33 -0600968 VkExtent2D swapchainExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600969 // width and height are either both -1, or both not -1.
Ian Elliottc11750d2015-10-30 13:24:12 -0600970 if (surfCapabilities.currentExtent.width == -1)
Tony Barbour6a3faf02015-07-23 10:36:18 -0600971 {
972 // If the surface size is undefined, the size is set to
973 // the size of the images requested.
Ian Elliott7e40db92015-08-21 15:09:33 -0600974 swapchainExtent.width = m_width;
975 swapchainExtent.height = m_height;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600976 }
977 else
978 {
979 // If the surface size is defined, the swap chain size must match
Ian Elliottc11750d2015-10-30 13:24:12 -0600980 swapchainExtent = surfCapabilities.currentExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600981 }
982
983 // If mailbox mode is available, use it, as is the lowest-latency non-
Ian Elliottae0e8242015-08-10 13:20:49 -0600984 // tearing mode. If not, try IMMEDIATE which will usually be available,
985 // and is fastest (though it tears). If not, fall back to FIFO which is
986 // always available.
Ian Elliott7e40db92015-08-21 15:09:33 -0600987 VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600988 for (size_t i = 0; i < presentModeCount; i++) {
Ian Elliott7e40db92015-08-21 15:09:33 -0600989 if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
990 swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600991 break;
992 }
Ian Elliott7e40db92015-08-21 15:09:33 -0600993 if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) &&
994 (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
995 swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
Ian Elliottae0e8242015-08-10 13:20:49 -0600996 }
Tony Barbour6a3faf02015-07-23 10:36:18 -0600997 }
998
999 // Determine the number of VkImage's to use in the swap chain (we desire to
1000 // own only 1 image at a time, besides the images being displayed and
1001 // queued for display):
Ian Elliottc11750d2015-10-30 13:24:12 -06001002 uint32_t desiredNumberOfSwapchainImages = surfCapabilities.minImageCount + 1;
1003 if ((surfCapabilities.maxImageCount > 0) &&
1004 (desiredNumberOfSwapchainImages > surfCapabilities.maxImageCount))
Tony Barbour6a3faf02015-07-23 10:36:18 -06001005 {
1006 // Application must settle for fewer images than desired:
Ian Elliottc11750d2015-10-30 13:24:12 -06001007 desiredNumberOfSwapchainImages = surfCapabilities.maxImageCount;
Tony Barbour6a3faf02015-07-23 10:36:18 -06001008 }
1009
Ian Elliottc11750d2015-10-30 13:24:12 -06001010 VkSurfaceTransformFlagsKHR preTransform;
Ian Elliotta8914ac2015-12-11 14:05:35 -07001011 if (surfCapabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) {
1012 preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -06001013 } else {
Ian Elliottc11750d2015-10-30 13:24:12 -06001014 preTransform = surfCapabilities.currentTransform;
Tony Barbour6a3faf02015-07-23 10:36:18 -06001015 }
Ian Elliott1a3845b2015-07-06 14:33:04 -06001016
Cody Northropdf5b0922015-08-28 16:22:48 -06001017 // 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 -06001018 assert((surfCapabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) != 0);
Cody Northropdf5b0922015-08-28 16:22:48 -06001019
Ian Elliott7e40db92015-08-21 15:09:33 -06001020 VkSwapchainCreateInfoKHR swap_chain = {};
Ian Elliotta257eea2015-09-22 10:20:23 -06001021 swap_chain.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
Ian Elliott1a3845b2015-07-06 14:33:04 -06001022 swap_chain.pNext = NULL;
Ian Elliottc11750d2015-10-30 13:24:12 -06001023 swap_chain.surface = m_surface;
Ian Elliott7e40db92015-08-21 15:09:33 -06001024 swap_chain.minImageCount = desiredNumberOfSwapchainImages;
Tony Barbour6a3faf02015-07-23 10:36:18 -06001025 swap_chain.imageFormat = m_format;
Ian Elliott8b139792015-08-07 11:51:12 -06001026 swap_chain.imageColorSpace = m_color_space;
Ian Elliott7e40db92015-08-21 15:09:33 -06001027 swap_chain.imageExtent.width = swapchainExtent.width;
1028 swap_chain.imageExtent.height = swapchainExtent.height;
Ian Elliottc11750d2015-10-30 13:24:12 -06001029 swap_chain.imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1030 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1031 swap_chain.preTransform = (VkSurfaceTransformFlagBitsKHR) preTransform;
1032 swap_chain.imageArrayLayers = 1;
1033 swap_chain.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
1034 swap_chain.queueFamilyIndexCount = 0;
Ian Elliott8b139792015-08-07 11:51:12 -06001035 swap_chain.pQueueFamilyIndices = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -06001036 swap_chain.presentMode = swapchainPresentMode;
Chia-I Wue2fc5522015-10-26 20:04:44 +08001037 swap_chain.oldSwapchain = VK_NULL_HANDLE;
Tony Barbour6a3faf02015-07-23 10:36:18 -06001038 swap_chain.clipped = true;
1039
1040 uint32_t i;
Chia-I Wuf8693382015-04-16 22:02:10 +08001041
Ian Elliottc11750d2015-10-30 13:24:12 -06001042 err = m_fpCreateSwapchainKHR(m_device.handle(), &swap_chain, NULL, &m_swap_chain);
Chia-I Wuf8693382015-04-16 22:02:10 +08001043 assert(!err);
1044
Ian Elliott7e40db92015-08-21 15:09:33 -06001045 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
1046 &m_swapchainImageCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -06001047 assert(!err);
1048
Ian Elliott7e40db92015-08-21 15:09:33 -06001049 VkImage* swapchainImages = (VkImage*)malloc(m_swapchainImageCount * sizeof(VkImage));
1050 assert(swapchainImages);
1051 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
1052 &m_swapchainImageCount, swapchainImages);
Tony Barbour6a3faf02015-07-23 10:36:18 -06001053 assert(!err);
1054
Ian Elliott7e40db92015-08-21 15:09:33 -06001055 m_buffers = (SwapchainBuffers*)malloc(sizeof(SwapchainBuffers)*m_swapchainImageCount);
Tony Barbour6a3faf02015-07-23 10:36:18 -06001056 assert(m_buffers);
1057
Ian Elliott7e40db92015-08-21 15:09:33 -06001058 for (i = 0; i < m_swapchainImageCount; i++) {
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -06001059 VkImageViewCreateInfo color_image_view = {};
1060 color_image_view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
1061 color_image_view.pNext = NULL;
1062 color_image_view.format = m_format;
Tony Barbourd800bbd2015-11-05 10:54:44 -07001063 color_image_view.components.r = VK_COMPONENT_SWIZZLE_R;
1064 color_image_view.components.g = VK_COMPONENT_SWIZZLE_G;
1065 color_image_view.components.b = VK_COMPONENT_SWIZZLE_B;
1066 color_image_view.components.a = VK_COMPONENT_SWIZZLE_A;
Courtney Goeltzenleuchterba724512015-09-10 17:58:54 -06001067 color_image_view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -06001068 color_image_view.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001069 color_image_view.subresourceRange.levelCount = 1;
Courtney Goeltzenleuchter4a261892015-09-10 16:38:41 -06001070 color_image_view.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001071 color_image_view.subresourceRange.layerCount = 1;
Tony Barbourd800bbd2015-11-05 10:54:44 -07001072 color_image_view.viewType = VK_IMAGE_VIEW_TYPE_2D;
1073 color_image_view.flags = 0;
Tony Barbour6a3faf02015-07-23 10:36:18 -06001074
Ian Elliott7e40db92015-08-21 15:09:33 -06001075 m_buffers[i].image = swapchainImages[i];
Tony Barbour6a3faf02015-07-23 10:36:18 -06001076
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -06001077 color_image_view.image = m_buffers[i].image;
1078 err = vkCreateImageView(m_device.handle(),
Chia-I Wuf7458c52015-10-26 21:10:41 +08001079 &color_image_view, NULL, &m_buffers[i].view);
Tony Barbour6a3faf02015-07-23 10:36:18 -06001080 assert(!err);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001081
1082 /* Set image layout to PRESENT_SOURCE_KHR so that before the copy, it can be set to */
1083 /* TRANSFER_DESTINATION_OPTIMAL */
1084 SetImageLayout(m_buffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT,
Ian Elliott1dcd1092015-11-17 17:29:40 -07001085 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001086
Tony Barbour6a3faf02015-07-23 10:36:18 -06001087 }
Tony Barbour96db8822015-02-25 12:28:39 -07001088}
Tony Barbourbd094ce2015-10-23 11:00:15 -06001089void TestFrameworkVkPresent::SetImageLayout(VkImage image, VkImageAspectFlags aspectMask,
1090 VkImageLayout old_image_layout, VkImageLayout new_image_layout)
1091{
1092 VkResult U_ASSERT_ONLY err;
1093
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001094 VkCommandBufferBeginInfo cmd_buf_info = {};
Jon Ashburnf19916e2016-01-11 13:12:43 -07001095 VkCommandBufferInheritanceInfo cmd_buf_hinfo = {};
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001096 cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001097 cmd_buf_info.pNext = NULL;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001098 cmd_buf_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
Jon Ashburnf19916e2016-01-11 13:12:43 -07001099 cmd_buf_info.pInheritanceInfo = &cmd_buf_hinfo;
1100 cmd_buf_hinfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
1101 cmd_buf_hinfo.pNext = NULL;
1102 cmd_buf_hinfo.renderPass = { VK_NULL_HANDLE };
1103 cmd_buf_hinfo.subpass = 0;
1104 cmd_buf_hinfo.framebuffer = { VK_NULL_HANDLE };
1105 cmd_buf_hinfo.occlusionQueryEnable = VK_FALSE;
1106 cmd_buf_hinfo.queryFlags = 0;
1107 cmd_buf_hinfo.pipelineStatistics = 0;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001108
1109 err = vkBeginCommandBuffer(m_cmdbuf.handle(), &cmd_buf_info);
1110 assert(!err);
1111
1112 VkImageMemoryBarrier image_memory_barrier = {};
1113 image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
1114 image_memory_barrier.pNext = NULL;
Chia-I Wua4594202015-10-27 19:54:37 +08001115 image_memory_barrier.srcAccessMask = 0;
1116 image_memory_barrier.dstAccessMask = 0;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001117 image_memory_barrier.oldLayout = old_image_layout;
1118 image_memory_barrier.newLayout = new_image_layout;
1119 image_memory_barrier.image = image;
1120 image_memory_barrier.subresourceRange.aspectMask = aspectMask;
1121 image_memory_barrier.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001122 image_memory_barrier.subresourceRange.levelCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001123 image_memory_barrier.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001124 image_memory_barrier.subresourceRange.layerCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001125
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001126 if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
Tony Barbourbd094ce2015-10-23 11:00:15 -06001127 /* Make sure anything that was copying from this image has completed */
Chia-I Wua4594202015-10-27 19:54:37 +08001128 image_memory_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001129 }
1130
1131 if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
1132 /* Make sure any Copy or CPU writes to image are flushed */
Chia-I Wua4594202015-10-27 19:54:37 +08001133 image_memory_barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001134 }
1135
1136 VkImageMemoryBarrier *pmemory_barrier = &image_memory_barrier;
1137
1138 VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1139 VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1140
Jon Ashburnf19916e2016-01-11 13:12:43 -07001141 vkCmdPipelineBarrier(m_cmdbuf.handle(), src_stages, dest_stages, 0, 0, NULL, 0, NULL, 1, pmemory_barrier);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001142
1143 err = vkEndCommandBuffer(m_cmdbuf.handle());
1144 assert(!err);
1145
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001146 const VkCommandBuffer cmd_bufs[] = { m_cmdbuf.handle() };
Tony Barbourbd094ce2015-10-23 11:00:15 -06001147 VkFence nullFence = { VK_NULL_HANDLE };
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001148 VkSubmitInfo submit_info;
Chia-I Wuf9be13c2015-10-26 20:37:06 +08001149 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1150 submit_info.pNext = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001151 submit_info.waitSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001152 submit_info.pWaitSemaphores = NULL;
Jon Ashburn7f9716c2015-12-30 16:42:50 -07001153 submit_info.pWaitDstStageMask = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001154 submit_info.commandBufferCount = 1;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001155 submit_info.pCommandBuffers = cmd_bufs;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001156 submit_info.signalSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001157 submit_info.pSignalSemaphores = NULL;
1158
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -06001159 err = vkQueueSubmit(m_queue.handle(), 1, &submit_info, nullFence);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001160 assert(!err);
1161
1162 err = vkQueueWaitIdle(m_queue.handle());
1163 assert(!err);
1164
1165}
Tony Barbour96db8822015-02-25 12:28:39 -07001166
Jon Ashburn07daee72015-05-21 18:13:33 -06001167void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -07001168{
Ian Elliottc11750d2015-10-30 13:24:12 -06001169 m_instance = inst;
Ian Elliott7e40db92015-08-21 15:09:33 -06001170 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceSupportKHR);
Ian Elliottc11750d2015-10-30 13:24:12 -06001171 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceCapabilitiesKHR);
1172 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceFormatsKHR);
1173 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfacePresentModesKHR);
Tony Barbour2d6d54e2015-12-03 16:05:11 -07001174 GET_INSTANCE_PROC_ADDR(inst, DestroySurfaceKHR);
Ian Elliott7e40db92015-08-21 15:09:33 -06001175 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1176 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1177 GET_DEVICE_PROC_ADDR(m_device.handle(), DestroySwapchainKHR);
1178 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSwapchainImagesKHR);
1179 GET_DEVICE_PROC_ADDR(m_device.handle(), AcquireNextImageKHR);
1180 GET_DEVICE_PROC_ADDR(m_device.handle(), QueuePresentKHR);
Jon Ashburn07daee72015-05-21 18:13:33 -06001181
Tony Barbour96db8822015-02-25 12:28:39 -07001182 m_images = imagesIn;
1183}
1184
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001185#ifdef _WIN32
Tony Barbourc16220e2016-01-07 11:41:10 -07001186void TestFrameworkVkPresent::CreateMyWindow(bool register_class)
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001187{
Tony Barbourc16220e2016-01-07 11:41:10 -07001188 WNDCLASSEX win_class;
1189 // const ::testing::TestInfo* const test_info =
1190 // ::testing::UnitTest::GetInstance()->current_test_info();
1191 m_connection = GetModuleHandle(NULL);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001192
Tony Barbourc16220e2016-01-07 11:41:10 -07001193 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1194 it != m_images.end(); it++) {
1195 if (m_width < it->m_width)
1196 m_width = it->m_width;
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001197 if (m_height < it->m_height)
Tony Barbourc16220e2016-01-07 11:41:10 -07001198 m_height = it->m_height;
1199 }
1200
1201 if (register_class) {
1202 // Initialize the window class structure:
1203 win_class.cbSize = sizeof(WNDCLASSEX);
1204 win_class.style = CS_HREDRAW | CS_VREDRAW;
1205 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
1206 win_class.cbClsExtra = 0;
1207 win_class.cbWndExtra = 0;
1208 win_class.hInstance = m_connection; // hInstance
1209 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
1210 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
1211 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
1212 win_class.lpszMenuName = NULL;
1213 win_class.lpszClassName = "Test";
1214 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
1215 // Register window class:
1216 if (!RegisterClassEx(&win_class)) {
1217 // It didn't work, so try to give a useful error:
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001218 printf("Unexpected error trying to start the application!\n");
Tony Barbourc16220e2016-01-07 11:41:10 -07001219 fflush(stdout);
1220 exit(1);
1221 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001222 }
1223 // Create window with the registered class:
Cody Northrop39582252015-08-05 15:39:31 -06001224 RECT wr = { 0, 0, m_width, m_height };
1225 AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001226 m_window = CreateWindowEx(0,
1227 "Test", // class name
1228 "Test", // app name
1229 WS_OVERLAPPEDWINDOW | // window style
1230 WS_VISIBLE |
1231 WS_SYSMENU,
1232 100,100, // x/y coords
Cody Northrop39582252015-08-05 15:39:31 -06001233 wr.right - wr.left, // width
1234 wr.bottom - wr.top, // height
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001235 NULL, // handle to parent
1236 NULL, // handle to menu
1237 m_connection, // hInstance
1238 NULL); // no extra parameters
1239
1240 if (!m_window) {
1241 // It didn't work, so try to give a useful error:
1242 DWORD error = GetLastError();
1243 char message[120];
1244 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
1245 MessageBox(NULL, message, "Error", MB_OK);
1246 exit(1);
1247 }
Tony-LunarG399dfca2015-05-19 14:08:26 -06001248 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
1249 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001250}
1251#else
Tony Barbour6918cd52015-04-09 12:58:51 -06001252void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -07001253{
Chia-I Wuf8693382015-04-16 22:02:10 +08001254 const xcb_setup_t *setup;
1255 xcb_screen_iterator_t iter;
1256 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -07001257 uint32_t value_mask, value_list[32];
1258
Chia-I Wuf8693382015-04-16 22:02:10 +08001259 m_connection = xcb_connect(NULL, &scr);
1260
1261 setup = xcb_get_setup(m_connection);
1262 iter = xcb_setup_roots_iterator(setup);
1263 while (scr-- > 0)
1264 xcb_screen_next(&iter);
1265
1266 m_screen = iter.data;
1267
1268 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1269 it != m_images.end(); it++) {
1270 if (m_width < it->m_width)
1271 m_width = it->m_width;
1272 if (m_height < it->m_height)
1273 m_height = it->m_height;
1274 }
1275
1276 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -07001277
1278 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +08001279 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -07001280 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
1281 XCB_EVENT_MASK_EXPOSURE |
1282 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
1283
Chia-I Wuf8693382015-04-16 22:02:10 +08001284 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -07001285 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001286 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -07001287 0, 0, m_width, m_height, 0,
1288 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001289 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -07001290 value_mask, value_list);
1291
1292 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +08001293 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -07001294 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +08001295 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001296
Chia-I Wuf8693382015-04-16 22:02:10 +08001297 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
1298 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001299
Chia-I Wuf8693382015-04-16 22:02:10 +08001300 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -07001301 m_window, (*reply).atom, 4, 32, 1,
1302 &(*m_atom_wm_delete_window).atom);
1303 free(reply);
1304
Chia-I Wuf8693382015-04-16 22:02:10 +08001305 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -07001306}
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001307#endif
Tony Barbour96db8822015-02-25 12:28:39 -07001308
Tony Barbour6918cd52015-04-09 12:58:51 -06001309void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -07001310{
Ian Elliottc11750d2015-10-30 13:24:12 -06001311 m_fpDestroySwapchainKHR(m_device.handle(), m_swap_chain, NULL);
Tony Barbour9226a822015-10-23 10:58:56 -06001312
1313 for (uint32_t i = 0; i < m_swapchainImageCount; i++) {
Chia-I Wuf7458c52015-10-26 21:10:41 +08001314 vkDestroyImageView(m_device.handle(), m_buffers[i].view, NULL);
Tony Barbour9226a822015-10-23 10:58:56 -06001315 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001316#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +08001317 xcb_destroy_window(m_connection, m_window);
1318 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001319#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001320}
1321
Tony Barboure1837292015-12-07 13:46:11 -07001322void TestFrameworkVkPresent::DestroyMyWindow()
Tony Barbour2d6d54e2015-12-03 16:05:11 -07001323{
1324#ifndef _WIN32
1325 xcb_destroy_window(m_connection, m_window);
1326 xcb_disconnect(m_connection);
1327#else
1328 DestroyWindow(m_window);
1329#endif
1330}
1331
Tony Barbour6918cd52015-04-09 12:58:51 -06001332void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001333{
1334 if (m_images.size() == 0) return;
1335
Chia-I Wuf8693382015-04-16 22:02:10 +08001336 vk_testing::Environment env;
1337 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -07001338 {
Chia-I Wuf8693382015-04-16 22:02:10 +08001339 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -07001340
Jon Ashburn07daee72015-05-21 18:13:33 -06001341 vkPresent.InitPresentFramework(m_images, env.get_instance());
Tony Barbourc16220e2016-01-07 11:41:10 -07001342#ifdef _WIN32
1343 vkPresent.CreateMyWindow(false);
1344#else
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001345 vkPresent.CreateMyWindow();
Tony Barbourc16220e2016-01-07 11:41:10 -07001346#endif
Ian Elliott7e40db92015-08-21 15:09:33 -06001347 vkPresent.CreateSwapchain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001348 vkPresent.Run();
1349 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -07001350 }
Chia-I Wuf8693382015-04-16 22:02:10 +08001351 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001352}
1353
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001354//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001355// These are the default resources for TBuiltInResources, used for both
1356// - parsing this string for the case where the user didn't supply one
1357// - dumping out a template for user construction of a config file
1358//
1359static const char* DefaultConfig =
1360 "MaxLights 32\n"
1361 "MaxClipPlanes 6\n"
1362 "MaxTextureUnits 32\n"
1363 "MaxTextureCoords 32\n"
1364 "MaxVertexAttribs 64\n"
1365 "MaxVertexUniformComponents 4096\n"
1366 "MaxVaryingFloats 64\n"
1367 "MaxVertexTextureImageUnits 32\n"
1368 "MaxCombinedTextureImageUnits 80\n"
1369 "MaxTextureImageUnits 32\n"
1370 "MaxFragmentUniformComponents 4096\n"
1371 "MaxDrawBuffers 32\n"
1372 "MaxVertexUniformVectors 128\n"
1373 "MaxVaryingVectors 8\n"
1374 "MaxFragmentUniformVectors 16\n"
1375 "MaxVertexOutputVectors 16\n"
1376 "MaxFragmentInputVectors 15\n"
1377 "MinProgramTexelOffset -8\n"
1378 "MaxProgramTexelOffset 7\n"
1379 "MaxClipDistances 8\n"
1380 "MaxComputeWorkGroupCountX 65535\n"
1381 "MaxComputeWorkGroupCountY 65535\n"
1382 "MaxComputeWorkGroupCountZ 65535\n"
1383 "MaxComputeWorkGroupSizeX 1024\n"
1384 "MaxComputeWorkGroupSizeY 1024\n"
1385 "MaxComputeWorkGroupSizeZ 64\n"
1386 "MaxComputeUniformComponents 1024\n"
1387 "MaxComputeTextureImageUnits 16\n"
1388 "MaxComputeImageUniforms 8\n"
1389 "MaxComputeAtomicCounters 8\n"
1390 "MaxComputeAtomicCounterBuffers 1\n"
1391 "MaxVaryingComponents 60\n"
1392 "MaxVertexOutputComponents 64\n"
1393 "MaxGeometryInputComponents 64\n"
1394 "MaxGeometryOutputComponents 128\n"
1395 "MaxFragmentInputComponents 128\n"
1396 "MaxImageUnits 8\n"
1397 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
1398 "MaxCombinedShaderOutputResources 8\n"
1399 "MaxImageSamples 0\n"
1400 "MaxVertexImageUniforms 0\n"
1401 "MaxTessControlImageUniforms 0\n"
1402 "MaxTessEvaluationImageUniforms 0\n"
1403 "MaxGeometryImageUniforms 0\n"
1404 "MaxFragmentImageUniforms 8\n"
1405 "MaxCombinedImageUniforms 8\n"
1406 "MaxGeometryTextureImageUnits 16\n"
1407 "MaxGeometryOutputVertices 256\n"
1408 "MaxGeometryTotalOutputComponents 1024\n"
1409 "MaxGeometryUniformComponents 1024\n"
1410 "MaxGeometryVaryingComponents 64\n"
1411 "MaxTessControlInputComponents 128\n"
1412 "MaxTessControlOutputComponents 128\n"
1413 "MaxTessControlTextureImageUnits 16\n"
1414 "MaxTessControlUniformComponents 1024\n"
1415 "MaxTessControlTotalOutputComponents 4096\n"
1416 "MaxTessEvaluationInputComponents 128\n"
1417 "MaxTessEvaluationOutputComponents 128\n"
1418 "MaxTessEvaluationTextureImageUnits 16\n"
1419 "MaxTessEvaluationUniformComponents 1024\n"
1420 "MaxTessPatchComponents 120\n"
1421 "MaxPatchVertices 32\n"
1422 "MaxTessGenLevel 64\n"
1423 "MaxViewports 16\n"
1424 "MaxVertexAtomicCounters 0\n"
1425 "MaxTessControlAtomicCounters 0\n"
1426 "MaxTessEvaluationAtomicCounters 0\n"
1427 "MaxGeometryAtomicCounters 0\n"
1428 "MaxFragmentAtomicCounters 8\n"
1429 "MaxCombinedAtomicCounters 8\n"
1430 "MaxAtomicCounterBindings 1\n"
1431 "MaxVertexAtomicCounterBuffers 0\n"
1432 "MaxTessControlAtomicCounterBuffers 0\n"
1433 "MaxTessEvaluationAtomicCounterBuffers 0\n"
1434 "MaxGeometryAtomicCounterBuffers 0\n"
1435 "MaxFragmentAtomicCounterBuffers 1\n"
1436 "MaxCombinedAtomicCounterBuffers 1\n"
1437 "MaxAtomicCounterBufferSize 16384\n"
1438 "MaxTransformFeedbackBuffers 4\n"
1439 "MaxTransformFeedbackInterleavedComponents 64\n"
1440 "MaxCullDistances 8\n"
1441 "MaxCombinedClipAndCullDistances 8\n"
1442 "MaxSamples 4\n"
1443
1444 "nonInductiveForLoops 1\n"
1445 "whileLoops 1\n"
1446 "doWhileLoops 1\n"
1447 "generalUniformIndexing 1\n"
1448 "generalAttributeMatrixVectorIndexing 1\n"
1449 "generalVaryingIndexing 1\n"
1450 "generalSamplerIndexing 1\n"
1451 "generalVariableIndexing 1\n"
1452 "generalConstantMatrixVectorIndexing 1\n"
1453 ;
1454
1455//
1456// *.conf => this is a config file that can set limits/resources
1457//
Tony Barbour6918cd52015-04-09 12:58:51 -06001458bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001459{
1460 if (name.size() < 5)
1461 return false;
1462
1463 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
1464 ConfigFile = name;
1465 return true;
1466 }
1467
1468 return false;
1469}
1470
1471//
1472// Parse either a .conf file provided by the user or the default string above.
1473//
Tony Barbour6918cd52015-04-09 12:58:51 -06001474void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001475{
1476 char** configStrings = 0;
1477 char* config = 0;
1478 if (ConfigFile.size() > 0) {
1479 configStrings = ReadFileData(ConfigFile.c_str());
1480 if (configStrings)
1481 config = *configStrings;
1482 else {
1483 printf("Error opening configuration file; will instead use the default configuration\n");
1484 }
1485 }
1486
1487 if (config == 0) {
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001488 config = (char *) alloca(strlen(DefaultConfig) + 1);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001489 strcpy(config, DefaultConfig);
1490 }
1491
1492 const char* delims = " \t\n\r";
1493 const char* token = strtok(config, delims);
1494 while (token) {
1495 const char* valueStr = strtok(0, delims);
1496 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1497 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1498 return;
1499 }
1500 int value = atoi(valueStr);
1501
1502 if (strcmp(token, "MaxLights") == 0)
1503 Resources.maxLights = value;
1504 else if (strcmp(token, "MaxClipPlanes") == 0)
1505 Resources.maxClipPlanes = value;
1506 else if (strcmp(token, "MaxTextureUnits") == 0)
1507 Resources.maxTextureUnits = value;
1508 else if (strcmp(token, "MaxTextureCoords") == 0)
1509 Resources.maxTextureCoords = value;
1510 else if (strcmp(token, "MaxVertexAttribs") == 0)
1511 Resources.maxVertexAttribs = value;
1512 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1513 Resources.maxVertexUniformComponents = value;
1514 else if (strcmp(token, "MaxVaryingFloats") == 0)
1515 Resources.maxVaryingFloats = value;
1516 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1517 Resources.maxVertexTextureImageUnits = value;
1518 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1519 Resources.maxCombinedTextureImageUnits = value;
1520 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1521 Resources.maxTextureImageUnits = value;
1522 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1523 Resources.maxFragmentUniformComponents = value;
1524 else if (strcmp(token, "MaxDrawBuffers") == 0)
1525 Resources.maxDrawBuffers = value;
1526 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1527 Resources.maxVertexUniformVectors = value;
1528 else if (strcmp(token, "MaxVaryingVectors") == 0)
1529 Resources.maxVaryingVectors = value;
1530 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1531 Resources.maxFragmentUniformVectors = value;
1532 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1533 Resources.maxVertexOutputVectors = value;
1534 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1535 Resources.maxFragmentInputVectors = value;
1536 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1537 Resources.minProgramTexelOffset = value;
1538 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1539 Resources.maxProgramTexelOffset = value;
1540 else if (strcmp(token, "MaxClipDistances") == 0)
1541 Resources.maxClipDistances = value;
1542 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1543 Resources.maxComputeWorkGroupCountX = value;
1544 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1545 Resources.maxComputeWorkGroupCountY = value;
1546 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1547 Resources.maxComputeWorkGroupCountZ = value;
1548 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1549 Resources.maxComputeWorkGroupSizeX = value;
1550 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1551 Resources.maxComputeWorkGroupSizeY = value;
1552 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1553 Resources.maxComputeWorkGroupSizeZ = value;
1554 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1555 Resources.maxComputeUniformComponents = value;
1556 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1557 Resources.maxComputeTextureImageUnits = value;
1558 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1559 Resources.maxComputeImageUniforms = value;
1560 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1561 Resources.maxComputeAtomicCounters = value;
1562 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1563 Resources.maxComputeAtomicCounterBuffers = value;
1564 else if (strcmp(token, "MaxVaryingComponents") == 0)
1565 Resources.maxVaryingComponents = value;
1566 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1567 Resources.maxVertexOutputComponents = value;
1568 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1569 Resources.maxGeometryInputComponents = value;
1570 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1571 Resources.maxGeometryOutputComponents = value;
1572 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1573 Resources.maxFragmentInputComponents = value;
1574 else if (strcmp(token, "MaxImageUnits") == 0)
1575 Resources.maxImageUnits = value;
1576 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1577 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1578 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1579 Resources.maxCombinedShaderOutputResources = value;
1580 else if (strcmp(token, "MaxImageSamples") == 0)
1581 Resources.maxImageSamples = value;
1582 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1583 Resources.maxVertexImageUniforms = value;
1584 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1585 Resources.maxTessControlImageUniforms = value;
1586 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1587 Resources.maxTessEvaluationImageUniforms = value;
1588 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1589 Resources.maxGeometryImageUniforms = value;
1590 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1591 Resources.maxFragmentImageUniforms = value;
1592 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1593 Resources.maxCombinedImageUniforms = value;
1594 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1595 Resources.maxGeometryTextureImageUnits = value;
1596 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1597 Resources.maxGeometryOutputVertices = value;
1598 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1599 Resources.maxGeometryTotalOutputComponents = value;
1600 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1601 Resources.maxGeometryUniformComponents = value;
1602 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1603 Resources.maxGeometryVaryingComponents = value;
1604 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1605 Resources.maxTessControlInputComponents = value;
1606 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1607 Resources.maxTessControlOutputComponents = value;
1608 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1609 Resources.maxTessControlTextureImageUnits = value;
1610 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1611 Resources.maxTessControlUniformComponents = value;
1612 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1613 Resources.maxTessControlTotalOutputComponents = value;
1614 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1615 Resources.maxTessEvaluationInputComponents = value;
1616 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1617 Resources.maxTessEvaluationOutputComponents = value;
1618 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1619 Resources.maxTessEvaluationTextureImageUnits = value;
1620 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1621 Resources.maxTessEvaluationUniformComponents = value;
1622 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1623 Resources.maxTessPatchComponents = value;
1624 else if (strcmp(token, "MaxPatchVertices") == 0)
1625 Resources.maxPatchVertices = value;
1626 else if (strcmp(token, "MaxTessGenLevel") == 0)
1627 Resources.maxTessGenLevel = value;
1628 else if (strcmp(token, "MaxViewports") == 0)
1629 Resources.maxViewports = value;
1630 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1631 Resources.maxVertexAtomicCounters = value;
1632 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1633 Resources.maxTessControlAtomicCounters = value;
1634 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1635 Resources.maxTessEvaluationAtomicCounters = value;
1636 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1637 Resources.maxGeometryAtomicCounters = value;
1638 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1639 Resources.maxFragmentAtomicCounters = value;
1640 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1641 Resources.maxCombinedAtomicCounters = value;
1642 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1643 Resources.maxAtomicCounterBindings = value;
1644 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1645 Resources.maxVertexAtomicCounterBuffers = value;
1646 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1647 Resources.maxTessControlAtomicCounterBuffers = value;
1648 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1649 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1650 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1651 Resources.maxGeometryAtomicCounterBuffers = value;
1652 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1653 Resources.maxFragmentAtomicCounterBuffers = value;
1654 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1655 Resources.maxCombinedAtomicCounterBuffers = value;
1656 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1657 Resources.maxAtomicCounterBufferSize = value;
1658 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1659 Resources.maxTransformFeedbackBuffers = value;
1660 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1661 Resources.maxTransformFeedbackInterleavedComponents = value;
1662 else if (strcmp(token, "MaxCullDistances") == 0)
1663 Resources.maxCullDistances = value;
1664 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1665 Resources.maxCombinedClipAndCullDistances = value;
1666 else if (strcmp(token, "MaxSamples") == 0)
1667 Resources.maxSamples = value;
1668
1669 else if (strcmp(token, "nonInductiveForLoops") == 0)
1670 Resources.limits.nonInductiveForLoops = (value != 0);
1671 else if (strcmp(token, "whileLoops") == 0)
1672 Resources.limits.whileLoops = (value != 0);
1673 else if (strcmp(token, "doWhileLoops") == 0)
1674 Resources.limits.doWhileLoops = (value != 0);
1675 else if (strcmp(token, "generalUniformIndexing") == 0)
1676 Resources.limits.generalUniformIndexing = (value != 0);
1677 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1678 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1679 else if (strcmp(token, "generalVaryingIndexing") == 0)
1680 Resources.limits.generalVaryingIndexing = (value != 0);
1681 else if (strcmp(token, "generalSamplerIndexing") == 0)
1682 Resources.limits.generalSamplerIndexing = (value != 0);
1683 else if (strcmp(token, "generalVariableIndexing") == 0)
1684 Resources.limits.generalVariableIndexing = (value != 0);
1685 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1686 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1687 else
1688 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1689
1690 token = strtok(0, delims);
1691 }
1692 if (configStrings)
1693 FreeFileData(configStrings);
1694}
1695
Tony Barbour6918cd52015-04-09 12:58:51 -06001696void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001697{
1698 if (m_compile_options & EOptionRelaxedErrors)
1699 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1700 if (m_compile_options & EOptionIntermediate)
1701 messages = (EShMessages)(messages | EShMsgAST);
1702 if (m_compile_options & EOptionSuppressWarnings)
1703 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1704}
1705
1706//
1707// Malloc a string of sufficient size and read a string into it.
1708//
Tony Barbour6918cd52015-04-09 12:58:51 -06001709char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001710{
1711 FILE *in;
1712 #if defined(_WIN32) && defined(__GNUC__)
1713 in = fopen(fileName, "r");
1714 int errorCode = in ? 0 : 1;
1715 #else
1716 int errorCode = fopen_s(&in, fileName, "r");
1717 #endif
1718
1719 char *fdata;
1720 int count = 0;
1721 const int maxSourceStrings = 5;
1722 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1723
1724 if (errorCode) {
1725 printf("Error: unable to open input file: %s\n", fileName);
1726 return 0;
1727 }
1728
1729 while (fgetc(in) != EOF)
1730 count++;
1731
1732 fseek(in, 0, SEEK_SET);
1733
1734 if (!(fdata = (char*)malloc(count+2))) {
1735 printf("Error allocating memory\n");
1736 return 0;
1737 }
1738 if (fread(fdata,1,count, in)!=count) {
1739 printf("Error reading input file: %s\n", fileName);
1740 return 0;
1741 }
1742 fdata[count] = '\0';
1743 fclose(in);
1744 if (count == 0) {
1745 return_data[0]=(char*)malloc(count+2);
1746 return_data[0][0]='\0';
1747 m_num_shader_strings = 0;
1748 return return_data;
1749 } else
1750 m_num_shader_strings = 1;
1751
1752 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1753 int ptr_len=0,i=0;
1754 while(count>0){
1755 return_data[i]=(char*)malloc(len+2);
1756 memcpy(return_data[i],fdata+ptr_len,len);
1757 return_data[i][len]='\0';
1758 count-=(len);
1759 ptr_len+=(len);
1760 if(count<len){
1761 if(count==0){
1762 m_num_shader_strings=(i+1);
1763 break;
1764 }
1765 len = count;
1766 }
1767 ++i;
1768 }
1769 return return_data;
1770}
1771
Tony Barbour6918cd52015-04-09 12:58:51 -06001772void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001773{
1774 for(int i=0;i<m_num_shader_strings;i++)
1775 free(data[i]);
1776}
1777
1778//
1779// Deduce the language from the filename. Files must end in one of the
1780// following extensions:
1781//
1782// .vert = vertex
1783// .tesc = tessellation control
1784// .tese = tessellation evaluation
1785// .geom = geometry
1786// .frag = fragment
1787// .comp = compute
1788//
Tony Barbour6918cd52015-04-09 12:58:51 -06001789EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001790{
1791 size_t ext = name.rfind('.');
1792 if (ext == std::string::npos) {
1793 return EShLangVertex;
1794 }
1795
1796 std::string suffix = name.substr(ext + 1, std::string::npos);
1797 if (suffix == "vert")
1798 return EShLangVertex;
1799 else if (suffix == "tesc")
1800 return EShLangTessControl;
1801 else if (suffix == "tese")
1802 return EShLangTessEvaluation;
1803 else if (suffix == "geom")
1804 return EShLangGeometry;
1805 else if (suffix == "frag")
1806 return EShLangFragment;
1807 else if (suffix == "comp")
1808 return EShLangCompute;
1809
1810 return EShLangVertex;
1811}
1812
1813//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001814// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001815//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001816EShLanguage VkTestFramework::FindLanguage(const VkShaderStageFlagBits shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001817{
1818 switch (shader_type) {
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001819 case VK_SHADER_STAGE_VERTEX_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001820 return EShLangVertex;
1821
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001822 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001823 return EShLangTessControl;
1824
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001825 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001826 return EShLangTessEvaluation;
1827
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001828 case VK_SHADER_STAGE_GEOMETRY_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001829 return EShLangGeometry;
1830
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001831 case VK_SHADER_STAGE_FRAGMENT_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001832 return EShLangFragment;
1833
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001834 case VK_SHADER_STAGE_COMPUTE_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001835 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001836
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001837 default:
1838 return EShLangVertex;
1839 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001840}
1841
1842
1843//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001844// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001845// Return value of false means an error was encountered.
1846//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001847bool VkTestFramework::GLSLtoSPV(const VkShaderStageFlagBits shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001848 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001849 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001850{
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001851 glslang::TProgram program;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001852 const char *shaderStrings[1];
1853
1854 // TODO: Do we want to load a special config file depending on the
1855 // shader source? Optional name maybe?
1856 // SetConfigFile(fileName);
1857
1858 ProcessConfigFile();
1859
1860 EShMessages messages = EShMsgDefault;
1861 SetMessageOptions(messages);
GregF7ed37422016-01-21 10:00:36 -07001862 messages = static_cast<EShMessages>(messages | EShMsgSpvRules | EShMsgVulkanRules);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001863
1864 EShLanguage stage = FindLanguage(shader_type);
1865 glslang::TShader* shader = new glslang::TShader(stage);
1866
1867 shaderStrings[0] = pshader;
1868 shader->setStrings(shaderStrings, 1);
1869
1870 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1871
Cody Northrop195d6622014-11-03 12:54:37 -07001872 if (! (m_compile_options & EOptionSuppressInfolog)) {
1873 puts(shader->getInfoLog());
1874 puts(shader->getInfoDebugLog());
1875 }
1876
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001877 return false; // something didn't work
1878 }
1879
1880 program.addShader(shader);
1881
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001882
1883 //
1884 // Program-level processing...
1885 //
1886
Cody Northrop195d6622014-11-03 12:54:37 -07001887 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001888
Cody Northrop195d6622014-11-03 12:54:37 -07001889 if (! (m_compile_options & EOptionSuppressInfolog)) {
1890 puts(shader->getInfoLog());
1891 puts(shader->getInfoDebugLog());
1892 }
1893
1894 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001895 }
1896
1897 if (m_compile_options & EOptionDumpReflection) {
1898 program.buildReflection();
1899 program.dumpReflection();
1900 }
1901
Cody Northrop5a95b472015-06-03 13:01:54 -06001902 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1903
1904 //
1905 // Test the different modes of SPIR-V modification
1906 //
1907 if (this->m_canonicalize_spv) {
1908 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1909 }
1910
1911 if (this->m_strip_spv) {
1912 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1913 }
1914
1915 if (this->m_do_everything_spv) {
1916 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1917 }
1918
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001919 delete shader;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001920
1921 return true;
1922}
1923
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001924
1925
Tony Barbour6918cd52015-04-09 12:58:51 -06001926VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001927 m_width( 0 ),
1928 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001929 m_data( NULL ),
1930 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001931{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001932}
1933
Tony Barbour6918cd52015-04-09 12:58:51 -06001934VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001935{
1936
1937}
1938
Tony Barbour6918cd52015-04-09 12:58:51 -06001939VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001940{
1941 m_title = copyin.m_title;
1942 m_width = copyin.m_width;
1943 m_height = copyin.m_height;
1944 m_data_size = copyin.m_data_size;
1945 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1946}
1947
Tony Barbour6918cd52015-04-09 12:58:51 -06001948ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001949{
Tony Barbour6918cd52015-04-09 12:58:51 -06001950 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1951 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001952 return output;
1953}
1954
Tony Barbour6918cd52015-04-09 12:58:51 -06001955VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001956{
1957 m_title = rhs.m_title;
1958 m_width = rhs.m_width;
1959 m_height = rhs.m_height;
1960 m_data_size = rhs.m_data_size;
1961 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001962 return *this;
1963}
1964
Tony Barbour6918cd52015-04-09 12:58:51 -06001965int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001966{
1967 if( this->m_data != rhs.m_data) return 0;
1968 return 1;
1969}
1970
1971// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001972int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001973{
1974 if( this->m_data_size < rhs.m_data_size ) return 1;
1975 return 0;
1976}
1977