blob: 6ecb5ef244dd0512bddab0063173a7fc08b98f87 [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,
Chia-I Wu53534662015-10-26 17:08:33 +0800651 0, 1, (const void * const*)&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,
Chia-I Wu53534662015-10-26 17:08:33 +0800672 0, 1, (const void * const*)&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 = {};
1095 cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001096 cmd_buf_info.pNext = NULL;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001097 cmd_buf_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001098 cmd_buf_info.renderPass = { VK_NULL_HANDLE };
1099 cmd_buf_info.subpass = 0;
1100 cmd_buf_info.framebuffer = { VK_NULL_HANDLE };
Chia-I Wub8d47ae2015-11-11 10:18:12 +08001101 cmd_buf_info.occlusionQueryEnable = VK_FALSE;
1102 cmd_buf_info.queryFlags = 0;
1103 cmd_buf_info.pipelineStatistics = 0;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001104
1105 err = vkBeginCommandBuffer(m_cmdbuf.handle(), &cmd_buf_info);
1106 assert(!err);
1107
1108 VkImageMemoryBarrier image_memory_barrier = {};
1109 image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
1110 image_memory_barrier.pNext = NULL;
Chia-I Wua4594202015-10-27 19:54:37 +08001111 image_memory_barrier.srcAccessMask = 0;
1112 image_memory_barrier.dstAccessMask = 0;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001113 image_memory_barrier.oldLayout = old_image_layout;
1114 image_memory_barrier.newLayout = new_image_layout;
1115 image_memory_barrier.image = image;
1116 image_memory_barrier.subresourceRange.aspectMask = aspectMask;
1117 image_memory_barrier.subresourceRange.baseMipLevel = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001118 image_memory_barrier.subresourceRange.levelCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001119 image_memory_barrier.subresourceRange.baseArrayLayer = 0;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001120 image_memory_barrier.subresourceRange.layerCount = 1;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001121
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001122 if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
Tony Barbourbd094ce2015-10-23 11:00:15 -06001123 /* Make sure anything that was copying from this image has completed */
Chia-I Wua4594202015-10-27 19:54:37 +08001124 image_memory_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001125 }
1126
1127 if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
1128 /* Make sure any Copy or CPU writes to image are flushed */
Chia-I Wua4594202015-10-27 19:54:37 +08001129 image_memory_barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
Tony Barbourbd094ce2015-10-23 11:00:15 -06001130 }
1131
1132 VkImageMemoryBarrier *pmemory_barrier = &image_memory_barrier;
1133
1134 VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1135 VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1136
Chia-I Wu53534662015-10-26 17:08:33 +08001137 vkCmdPipelineBarrier(m_cmdbuf.handle(), src_stages, dest_stages, 0, 1, (const void * const*)&pmemory_barrier);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001138
1139 err = vkEndCommandBuffer(m_cmdbuf.handle());
1140 assert(!err);
1141
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001142 const VkCommandBuffer cmd_bufs[] = { m_cmdbuf.handle() };
Tony Barbourbd094ce2015-10-23 11:00:15 -06001143 VkFence nullFence = { VK_NULL_HANDLE };
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001144 VkSubmitInfo submit_info;
Chia-I Wuf9be13c2015-10-26 20:37:06 +08001145 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1146 submit_info.pNext = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001147 submit_info.waitSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001148 submit_info.pWaitSemaphores = NULL;
Jon Ashburn7f9716c2015-12-30 16:42:50 -07001149 submit_info.pWaitDstStageMask = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001150 submit_info.commandBufferCount = 1;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001151 submit_info.pCommandBuffers = cmd_bufs;
Chia-I Wud50a7d72015-10-26 20:48:51 +08001152 submit_info.signalSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -06001153 submit_info.pSignalSemaphores = NULL;
1154
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -06001155 err = vkQueueSubmit(m_queue.handle(), 1, &submit_info, nullFence);
Tony Barbourbd094ce2015-10-23 11:00:15 -06001156 assert(!err);
1157
1158 err = vkQueueWaitIdle(m_queue.handle());
1159 assert(!err);
1160
1161}
Tony Barbour96db8822015-02-25 12:28:39 -07001162
Jon Ashburn07daee72015-05-21 18:13:33 -06001163void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -07001164{
Ian Elliottc11750d2015-10-30 13:24:12 -06001165 m_instance = inst;
Ian Elliott7e40db92015-08-21 15:09:33 -06001166 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceSupportKHR);
Ian Elliottc11750d2015-10-30 13:24:12 -06001167 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceCapabilitiesKHR);
1168 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceFormatsKHR);
1169 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfacePresentModesKHR);
Tony Barbour2d6d54e2015-12-03 16:05:11 -07001170 GET_INSTANCE_PROC_ADDR(inst, DestroySurfaceKHR);
Ian Elliott7e40db92015-08-21 15:09:33 -06001171 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1172 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
1173 GET_DEVICE_PROC_ADDR(m_device.handle(), DestroySwapchainKHR);
1174 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSwapchainImagesKHR);
1175 GET_DEVICE_PROC_ADDR(m_device.handle(), AcquireNextImageKHR);
1176 GET_DEVICE_PROC_ADDR(m_device.handle(), QueuePresentKHR);
Jon Ashburn07daee72015-05-21 18:13:33 -06001177
Tony Barbour96db8822015-02-25 12:28:39 -07001178 m_images = imagesIn;
1179}
1180
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001181#ifdef _WIN32
Tony Barbourc16220e2016-01-07 11:41:10 -07001182void TestFrameworkVkPresent::CreateMyWindow(bool register_class)
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001183{
Tony Barbourc16220e2016-01-07 11:41:10 -07001184 WNDCLASSEX win_class;
1185 // const ::testing::TestInfo* const test_info =
1186 // ::testing::UnitTest::GetInstance()->current_test_info();
1187 m_connection = GetModuleHandle(NULL);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001188
Tony Barbourc16220e2016-01-07 11:41:10 -07001189 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1190 it != m_images.end(); it++) {
1191 if (m_width < it->m_width)
1192 m_width = it->m_width;
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001193 if (m_height < it->m_height)
Tony Barbourc16220e2016-01-07 11:41:10 -07001194 m_height = it->m_height;
1195 }
1196
1197 if (register_class) {
1198 // Initialize the window class structure:
1199 win_class.cbSize = sizeof(WNDCLASSEX);
1200 win_class.style = CS_HREDRAW | CS_VREDRAW;
1201 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
1202 win_class.cbClsExtra = 0;
1203 win_class.cbWndExtra = 0;
1204 win_class.hInstance = m_connection; // hInstance
1205 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
1206 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
1207 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
1208 win_class.lpszMenuName = NULL;
1209 win_class.lpszClassName = "Test";
1210 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
1211 // Register window class:
1212 if (!RegisterClassEx(&win_class)) {
1213 // It didn't work, so try to give a useful error:
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001214 printf("Unexpected error trying to start the application!\n");
Tony Barbourc16220e2016-01-07 11:41:10 -07001215 fflush(stdout);
1216 exit(1);
1217 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001218 }
1219 // Create window with the registered class:
Cody Northrop39582252015-08-05 15:39:31 -06001220 RECT wr = { 0, 0, m_width, m_height };
1221 AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001222 m_window = CreateWindowEx(0,
1223 "Test", // class name
1224 "Test", // app name
1225 WS_OVERLAPPEDWINDOW | // window style
1226 WS_VISIBLE |
1227 WS_SYSMENU,
1228 100,100, // x/y coords
Cody Northrop39582252015-08-05 15:39:31 -06001229 wr.right - wr.left, // width
1230 wr.bottom - wr.top, // height
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001231 NULL, // handle to parent
1232 NULL, // handle to menu
1233 m_connection, // hInstance
1234 NULL); // no extra parameters
1235
1236 if (!m_window) {
1237 // It didn't work, so try to give a useful error:
1238 DWORD error = GetLastError();
1239 char message[120];
1240 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
1241 MessageBox(NULL, message, "Error", MB_OK);
1242 exit(1);
1243 }
Tony-LunarG399dfca2015-05-19 14:08:26 -06001244 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
1245 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001246}
1247#else
Tony Barbour6918cd52015-04-09 12:58:51 -06001248void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -07001249{
Chia-I Wuf8693382015-04-16 22:02:10 +08001250 const xcb_setup_t *setup;
1251 xcb_screen_iterator_t iter;
1252 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -07001253 uint32_t value_mask, value_list[32];
1254
Chia-I Wuf8693382015-04-16 22:02:10 +08001255 m_connection = xcb_connect(NULL, &scr);
1256
1257 setup = xcb_get_setup(m_connection);
1258 iter = xcb_setup_roots_iterator(setup);
1259 while (scr-- > 0)
1260 xcb_screen_next(&iter);
1261
1262 m_screen = iter.data;
1263
1264 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1265 it != m_images.end(); it++) {
1266 if (m_width < it->m_width)
1267 m_width = it->m_width;
1268 if (m_height < it->m_height)
1269 m_height = it->m_height;
1270 }
1271
1272 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -07001273
1274 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +08001275 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -07001276 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
1277 XCB_EVENT_MASK_EXPOSURE |
1278 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
1279
Chia-I Wuf8693382015-04-16 22:02:10 +08001280 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -07001281 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001282 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -07001283 0, 0, m_width, m_height, 0,
1284 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001285 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -07001286 value_mask, value_list);
1287
1288 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +08001289 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -07001290 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +08001291 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001292
Chia-I Wuf8693382015-04-16 22:02:10 +08001293 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
1294 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001295
Chia-I Wuf8693382015-04-16 22:02:10 +08001296 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -07001297 m_window, (*reply).atom, 4, 32, 1,
1298 &(*m_atom_wm_delete_window).atom);
1299 free(reply);
1300
Chia-I Wuf8693382015-04-16 22:02:10 +08001301 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -07001302}
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001303#endif
Tony Barbour96db8822015-02-25 12:28:39 -07001304
Tony Barbour6918cd52015-04-09 12:58:51 -06001305void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -07001306{
Ian Elliottc11750d2015-10-30 13:24:12 -06001307 m_fpDestroySwapchainKHR(m_device.handle(), m_swap_chain, NULL);
Tony Barbour9226a822015-10-23 10:58:56 -06001308
1309 for (uint32_t i = 0; i < m_swapchainImageCount; i++) {
Chia-I Wuf7458c52015-10-26 21:10:41 +08001310 vkDestroyImageView(m_device.handle(), m_buffers[i].view, NULL);
Tony Barbour9226a822015-10-23 10:58:56 -06001311 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001312#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +08001313 xcb_destroy_window(m_connection, m_window);
1314 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001315#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001316}
1317
Tony Barboure1837292015-12-07 13:46:11 -07001318void TestFrameworkVkPresent::DestroyMyWindow()
Tony Barbour2d6d54e2015-12-03 16:05:11 -07001319{
1320#ifndef _WIN32
1321 xcb_destroy_window(m_connection, m_window);
1322 xcb_disconnect(m_connection);
1323#else
1324 DestroyWindow(m_window);
1325#endif
1326}
1327
Tony Barbour6918cd52015-04-09 12:58:51 -06001328void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001329{
1330 if (m_images.size() == 0) return;
1331
Chia-I Wuf8693382015-04-16 22:02:10 +08001332 vk_testing::Environment env;
1333 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -07001334 {
Chia-I Wuf8693382015-04-16 22:02:10 +08001335 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -07001336
Jon Ashburn07daee72015-05-21 18:13:33 -06001337 vkPresent.InitPresentFramework(m_images, env.get_instance());
Tony Barbourc16220e2016-01-07 11:41:10 -07001338#ifdef _WIN32
1339 vkPresent.CreateMyWindow(false);
1340#else
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001341 vkPresent.CreateMyWindow();
Tony Barbourc16220e2016-01-07 11:41:10 -07001342#endif
Ian Elliott7e40db92015-08-21 15:09:33 -06001343 vkPresent.CreateSwapchain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001344 vkPresent.Run();
1345 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -07001346 }
Chia-I Wuf8693382015-04-16 22:02:10 +08001347 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001348}
1349
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001350//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001351// These are the default resources for TBuiltInResources, used for both
1352// - parsing this string for the case where the user didn't supply one
1353// - dumping out a template for user construction of a config file
1354//
1355static const char* DefaultConfig =
1356 "MaxLights 32\n"
1357 "MaxClipPlanes 6\n"
1358 "MaxTextureUnits 32\n"
1359 "MaxTextureCoords 32\n"
1360 "MaxVertexAttribs 64\n"
1361 "MaxVertexUniformComponents 4096\n"
1362 "MaxVaryingFloats 64\n"
1363 "MaxVertexTextureImageUnits 32\n"
1364 "MaxCombinedTextureImageUnits 80\n"
1365 "MaxTextureImageUnits 32\n"
1366 "MaxFragmentUniformComponents 4096\n"
1367 "MaxDrawBuffers 32\n"
1368 "MaxVertexUniformVectors 128\n"
1369 "MaxVaryingVectors 8\n"
1370 "MaxFragmentUniformVectors 16\n"
1371 "MaxVertexOutputVectors 16\n"
1372 "MaxFragmentInputVectors 15\n"
1373 "MinProgramTexelOffset -8\n"
1374 "MaxProgramTexelOffset 7\n"
1375 "MaxClipDistances 8\n"
1376 "MaxComputeWorkGroupCountX 65535\n"
1377 "MaxComputeWorkGroupCountY 65535\n"
1378 "MaxComputeWorkGroupCountZ 65535\n"
1379 "MaxComputeWorkGroupSizeX 1024\n"
1380 "MaxComputeWorkGroupSizeY 1024\n"
1381 "MaxComputeWorkGroupSizeZ 64\n"
1382 "MaxComputeUniformComponents 1024\n"
1383 "MaxComputeTextureImageUnits 16\n"
1384 "MaxComputeImageUniforms 8\n"
1385 "MaxComputeAtomicCounters 8\n"
1386 "MaxComputeAtomicCounterBuffers 1\n"
1387 "MaxVaryingComponents 60\n"
1388 "MaxVertexOutputComponents 64\n"
1389 "MaxGeometryInputComponents 64\n"
1390 "MaxGeometryOutputComponents 128\n"
1391 "MaxFragmentInputComponents 128\n"
1392 "MaxImageUnits 8\n"
1393 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
1394 "MaxCombinedShaderOutputResources 8\n"
1395 "MaxImageSamples 0\n"
1396 "MaxVertexImageUniforms 0\n"
1397 "MaxTessControlImageUniforms 0\n"
1398 "MaxTessEvaluationImageUniforms 0\n"
1399 "MaxGeometryImageUniforms 0\n"
1400 "MaxFragmentImageUniforms 8\n"
1401 "MaxCombinedImageUniforms 8\n"
1402 "MaxGeometryTextureImageUnits 16\n"
1403 "MaxGeometryOutputVertices 256\n"
1404 "MaxGeometryTotalOutputComponents 1024\n"
1405 "MaxGeometryUniformComponents 1024\n"
1406 "MaxGeometryVaryingComponents 64\n"
1407 "MaxTessControlInputComponents 128\n"
1408 "MaxTessControlOutputComponents 128\n"
1409 "MaxTessControlTextureImageUnits 16\n"
1410 "MaxTessControlUniformComponents 1024\n"
1411 "MaxTessControlTotalOutputComponents 4096\n"
1412 "MaxTessEvaluationInputComponents 128\n"
1413 "MaxTessEvaluationOutputComponents 128\n"
1414 "MaxTessEvaluationTextureImageUnits 16\n"
1415 "MaxTessEvaluationUniformComponents 1024\n"
1416 "MaxTessPatchComponents 120\n"
1417 "MaxPatchVertices 32\n"
1418 "MaxTessGenLevel 64\n"
1419 "MaxViewports 16\n"
1420 "MaxVertexAtomicCounters 0\n"
1421 "MaxTessControlAtomicCounters 0\n"
1422 "MaxTessEvaluationAtomicCounters 0\n"
1423 "MaxGeometryAtomicCounters 0\n"
1424 "MaxFragmentAtomicCounters 8\n"
1425 "MaxCombinedAtomicCounters 8\n"
1426 "MaxAtomicCounterBindings 1\n"
1427 "MaxVertexAtomicCounterBuffers 0\n"
1428 "MaxTessControlAtomicCounterBuffers 0\n"
1429 "MaxTessEvaluationAtomicCounterBuffers 0\n"
1430 "MaxGeometryAtomicCounterBuffers 0\n"
1431 "MaxFragmentAtomicCounterBuffers 1\n"
1432 "MaxCombinedAtomicCounterBuffers 1\n"
1433 "MaxAtomicCounterBufferSize 16384\n"
1434 "MaxTransformFeedbackBuffers 4\n"
1435 "MaxTransformFeedbackInterleavedComponents 64\n"
1436 "MaxCullDistances 8\n"
1437 "MaxCombinedClipAndCullDistances 8\n"
1438 "MaxSamples 4\n"
1439
1440 "nonInductiveForLoops 1\n"
1441 "whileLoops 1\n"
1442 "doWhileLoops 1\n"
1443 "generalUniformIndexing 1\n"
1444 "generalAttributeMatrixVectorIndexing 1\n"
1445 "generalVaryingIndexing 1\n"
1446 "generalSamplerIndexing 1\n"
1447 "generalVariableIndexing 1\n"
1448 "generalConstantMatrixVectorIndexing 1\n"
1449 ;
1450
1451//
1452// *.conf => this is a config file that can set limits/resources
1453//
Tony Barbour6918cd52015-04-09 12:58:51 -06001454bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001455{
1456 if (name.size() < 5)
1457 return false;
1458
1459 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
1460 ConfigFile = name;
1461 return true;
1462 }
1463
1464 return false;
1465}
1466
1467//
1468// Parse either a .conf file provided by the user or the default string above.
1469//
Tony Barbour6918cd52015-04-09 12:58:51 -06001470void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001471{
1472 char** configStrings = 0;
1473 char* config = 0;
1474 if (ConfigFile.size() > 0) {
1475 configStrings = ReadFileData(ConfigFile.c_str());
1476 if (configStrings)
1477 config = *configStrings;
1478 else {
1479 printf("Error opening configuration file; will instead use the default configuration\n");
1480 }
1481 }
1482
1483 if (config == 0) {
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001484 config = (char *) alloca(strlen(DefaultConfig) + 1);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001485 strcpy(config, DefaultConfig);
1486 }
1487
1488 const char* delims = " \t\n\r";
1489 const char* token = strtok(config, delims);
1490 while (token) {
1491 const char* valueStr = strtok(0, delims);
1492 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1493 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1494 return;
1495 }
1496 int value = atoi(valueStr);
1497
1498 if (strcmp(token, "MaxLights") == 0)
1499 Resources.maxLights = value;
1500 else if (strcmp(token, "MaxClipPlanes") == 0)
1501 Resources.maxClipPlanes = value;
1502 else if (strcmp(token, "MaxTextureUnits") == 0)
1503 Resources.maxTextureUnits = value;
1504 else if (strcmp(token, "MaxTextureCoords") == 0)
1505 Resources.maxTextureCoords = value;
1506 else if (strcmp(token, "MaxVertexAttribs") == 0)
1507 Resources.maxVertexAttribs = value;
1508 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1509 Resources.maxVertexUniformComponents = value;
1510 else if (strcmp(token, "MaxVaryingFloats") == 0)
1511 Resources.maxVaryingFloats = value;
1512 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1513 Resources.maxVertexTextureImageUnits = value;
1514 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1515 Resources.maxCombinedTextureImageUnits = value;
1516 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1517 Resources.maxTextureImageUnits = value;
1518 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1519 Resources.maxFragmentUniformComponents = value;
1520 else if (strcmp(token, "MaxDrawBuffers") == 0)
1521 Resources.maxDrawBuffers = value;
1522 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1523 Resources.maxVertexUniformVectors = value;
1524 else if (strcmp(token, "MaxVaryingVectors") == 0)
1525 Resources.maxVaryingVectors = value;
1526 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1527 Resources.maxFragmentUniformVectors = value;
1528 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1529 Resources.maxVertexOutputVectors = value;
1530 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1531 Resources.maxFragmentInputVectors = value;
1532 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1533 Resources.minProgramTexelOffset = value;
1534 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1535 Resources.maxProgramTexelOffset = value;
1536 else if (strcmp(token, "MaxClipDistances") == 0)
1537 Resources.maxClipDistances = value;
1538 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1539 Resources.maxComputeWorkGroupCountX = value;
1540 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1541 Resources.maxComputeWorkGroupCountY = value;
1542 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1543 Resources.maxComputeWorkGroupCountZ = value;
1544 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1545 Resources.maxComputeWorkGroupSizeX = value;
1546 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1547 Resources.maxComputeWorkGroupSizeY = value;
1548 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1549 Resources.maxComputeWorkGroupSizeZ = value;
1550 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1551 Resources.maxComputeUniformComponents = value;
1552 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1553 Resources.maxComputeTextureImageUnits = value;
1554 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1555 Resources.maxComputeImageUniforms = value;
1556 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1557 Resources.maxComputeAtomicCounters = value;
1558 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1559 Resources.maxComputeAtomicCounterBuffers = value;
1560 else if (strcmp(token, "MaxVaryingComponents") == 0)
1561 Resources.maxVaryingComponents = value;
1562 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1563 Resources.maxVertexOutputComponents = value;
1564 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1565 Resources.maxGeometryInputComponents = value;
1566 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1567 Resources.maxGeometryOutputComponents = value;
1568 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1569 Resources.maxFragmentInputComponents = value;
1570 else if (strcmp(token, "MaxImageUnits") == 0)
1571 Resources.maxImageUnits = value;
1572 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1573 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1574 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1575 Resources.maxCombinedShaderOutputResources = value;
1576 else if (strcmp(token, "MaxImageSamples") == 0)
1577 Resources.maxImageSamples = value;
1578 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1579 Resources.maxVertexImageUniforms = value;
1580 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1581 Resources.maxTessControlImageUniforms = value;
1582 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1583 Resources.maxTessEvaluationImageUniforms = value;
1584 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1585 Resources.maxGeometryImageUniforms = value;
1586 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1587 Resources.maxFragmentImageUniforms = value;
1588 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1589 Resources.maxCombinedImageUniforms = value;
1590 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1591 Resources.maxGeometryTextureImageUnits = value;
1592 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1593 Resources.maxGeometryOutputVertices = value;
1594 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1595 Resources.maxGeometryTotalOutputComponents = value;
1596 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1597 Resources.maxGeometryUniformComponents = value;
1598 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1599 Resources.maxGeometryVaryingComponents = value;
1600 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1601 Resources.maxTessControlInputComponents = value;
1602 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1603 Resources.maxTessControlOutputComponents = value;
1604 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1605 Resources.maxTessControlTextureImageUnits = value;
1606 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1607 Resources.maxTessControlUniformComponents = value;
1608 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1609 Resources.maxTessControlTotalOutputComponents = value;
1610 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1611 Resources.maxTessEvaluationInputComponents = value;
1612 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1613 Resources.maxTessEvaluationOutputComponents = value;
1614 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1615 Resources.maxTessEvaluationTextureImageUnits = value;
1616 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1617 Resources.maxTessEvaluationUniformComponents = value;
1618 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1619 Resources.maxTessPatchComponents = value;
1620 else if (strcmp(token, "MaxPatchVertices") == 0)
1621 Resources.maxPatchVertices = value;
1622 else if (strcmp(token, "MaxTessGenLevel") == 0)
1623 Resources.maxTessGenLevel = value;
1624 else if (strcmp(token, "MaxViewports") == 0)
1625 Resources.maxViewports = value;
1626 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1627 Resources.maxVertexAtomicCounters = value;
1628 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1629 Resources.maxTessControlAtomicCounters = value;
1630 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1631 Resources.maxTessEvaluationAtomicCounters = value;
1632 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1633 Resources.maxGeometryAtomicCounters = value;
1634 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1635 Resources.maxFragmentAtomicCounters = value;
1636 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1637 Resources.maxCombinedAtomicCounters = value;
1638 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1639 Resources.maxAtomicCounterBindings = value;
1640 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1641 Resources.maxVertexAtomicCounterBuffers = value;
1642 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1643 Resources.maxTessControlAtomicCounterBuffers = value;
1644 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1645 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1646 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1647 Resources.maxGeometryAtomicCounterBuffers = value;
1648 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1649 Resources.maxFragmentAtomicCounterBuffers = value;
1650 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1651 Resources.maxCombinedAtomicCounterBuffers = value;
1652 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1653 Resources.maxAtomicCounterBufferSize = value;
1654 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1655 Resources.maxTransformFeedbackBuffers = value;
1656 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1657 Resources.maxTransformFeedbackInterleavedComponents = value;
1658 else if (strcmp(token, "MaxCullDistances") == 0)
1659 Resources.maxCullDistances = value;
1660 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1661 Resources.maxCombinedClipAndCullDistances = value;
1662 else if (strcmp(token, "MaxSamples") == 0)
1663 Resources.maxSamples = value;
1664
1665 else if (strcmp(token, "nonInductiveForLoops") == 0)
1666 Resources.limits.nonInductiveForLoops = (value != 0);
1667 else if (strcmp(token, "whileLoops") == 0)
1668 Resources.limits.whileLoops = (value != 0);
1669 else if (strcmp(token, "doWhileLoops") == 0)
1670 Resources.limits.doWhileLoops = (value != 0);
1671 else if (strcmp(token, "generalUniformIndexing") == 0)
1672 Resources.limits.generalUniformIndexing = (value != 0);
1673 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1674 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1675 else if (strcmp(token, "generalVaryingIndexing") == 0)
1676 Resources.limits.generalVaryingIndexing = (value != 0);
1677 else if (strcmp(token, "generalSamplerIndexing") == 0)
1678 Resources.limits.generalSamplerIndexing = (value != 0);
1679 else if (strcmp(token, "generalVariableIndexing") == 0)
1680 Resources.limits.generalVariableIndexing = (value != 0);
1681 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1682 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1683 else
1684 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1685
1686 token = strtok(0, delims);
1687 }
1688 if (configStrings)
1689 FreeFileData(configStrings);
1690}
1691
Tony Barbour6918cd52015-04-09 12:58:51 -06001692void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001693{
1694 if (m_compile_options & EOptionRelaxedErrors)
1695 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1696 if (m_compile_options & EOptionIntermediate)
1697 messages = (EShMessages)(messages | EShMsgAST);
1698 if (m_compile_options & EOptionSuppressWarnings)
1699 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1700}
1701
1702//
1703// Malloc a string of sufficient size and read a string into it.
1704//
Tony Barbour6918cd52015-04-09 12:58:51 -06001705char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001706{
1707 FILE *in;
1708 #if defined(_WIN32) && defined(__GNUC__)
1709 in = fopen(fileName, "r");
1710 int errorCode = in ? 0 : 1;
1711 #else
1712 int errorCode = fopen_s(&in, fileName, "r");
1713 #endif
1714
1715 char *fdata;
1716 int count = 0;
1717 const int maxSourceStrings = 5;
1718 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1719
1720 if (errorCode) {
1721 printf("Error: unable to open input file: %s\n", fileName);
1722 return 0;
1723 }
1724
1725 while (fgetc(in) != EOF)
1726 count++;
1727
1728 fseek(in, 0, SEEK_SET);
1729
1730 if (!(fdata = (char*)malloc(count+2))) {
1731 printf("Error allocating memory\n");
1732 return 0;
1733 }
1734 if (fread(fdata,1,count, in)!=count) {
1735 printf("Error reading input file: %s\n", fileName);
1736 return 0;
1737 }
1738 fdata[count] = '\0';
1739 fclose(in);
1740 if (count == 0) {
1741 return_data[0]=(char*)malloc(count+2);
1742 return_data[0][0]='\0';
1743 m_num_shader_strings = 0;
1744 return return_data;
1745 } else
1746 m_num_shader_strings = 1;
1747
1748 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1749 int ptr_len=0,i=0;
1750 while(count>0){
1751 return_data[i]=(char*)malloc(len+2);
1752 memcpy(return_data[i],fdata+ptr_len,len);
1753 return_data[i][len]='\0';
1754 count-=(len);
1755 ptr_len+=(len);
1756 if(count<len){
1757 if(count==0){
1758 m_num_shader_strings=(i+1);
1759 break;
1760 }
1761 len = count;
1762 }
1763 ++i;
1764 }
1765 return return_data;
1766}
1767
Tony Barbour6918cd52015-04-09 12:58:51 -06001768void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001769{
1770 for(int i=0;i<m_num_shader_strings;i++)
1771 free(data[i]);
1772}
1773
1774//
1775// Deduce the language from the filename. Files must end in one of the
1776// following extensions:
1777//
1778// .vert = vertex
1779// .tesc = tessellation control
1780// .tese = tessellation evaluation
1781// .geom = geometry
1782// .frag = fragment
1783// .comp = compute
1784//
Tony Barbour6918cd52015-04-09 12:58:51 -06001785EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001786{
1787 size_t ext = name.rfind('.');
1788 if (ext == std::string::npos) {
1789 return EShLangVertex;
1790 }
1791
1792 std::string suffix = name.substr(ext + 1, std::string::npos);
1793 if (suffix == "vert")
1794 return EShLangVertex;
1795 else if (suffix == "tesc")
1796 return EShLangTessControl;
1797 else if (suffix == "tese")
1798 return EShLangTessEvaluation;
1799 else if (suffix == "geom")
1800 return EShLangGeometry;
1801 else if (suffix == "frag")
1802 return EShLangFragment;
1803 else if (suffix == "comp")
1804 return EShLangCompute;
1805
1806 return EShLangVertex;
1807}
1808
1809//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001810// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001811//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001812EShLanguage VkTestFramework::FindLanguage(const VkShaderStageFlagBits shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001813{
1814 switch (shader_type) {
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001815 case VK_SHADER_STAGE_VERTEX_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001816 return EShLangVertex;
1817
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001818 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001819 return EShLangTessControl;
1820
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001821 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001822 return EShLangTessEvaluation;
1823
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001824 case VK_SHADER_STAGE_GEOMETRY_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001825 return EShLangGeometry;
1826
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001827 case VK_SHADER_STAGE_FRAGMENT_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001828 return EShLangFragment;
1829
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001830 case VK_SHADER_STAGE_COMPUTE_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001831 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001832
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001833 default:
1834 return EShLangVertex;
1835 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001836}
1837
1838
1839//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001840// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001841// Return value of false means an error was encountered.
1842//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -06001843bool VkTestFramework::GLSLtoSPV(const VkShaderStageFlagBits shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001844 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001845 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001846{
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001847 glslang::TProgram program;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001848 const char *shaderStrings[1];
1849
1850 // TODO: Do we want to load a special config file depending on the
1851 // shader source? Optional name maybe?
1852 // SetConfigFile(fileName);
1853
1854 ProcessConfigFile();
1855
1856 EShMessages messages = EShMsgDefault;
1857 SetMessageOptions(messages);
1858
1859 EShLanguage stage = FindLanguage(shader_type);
1860 glslang::TShader* shader = new glslang::TShader(stage);
1861
1862 shaderStrings[0] = pshader;
1863 shader->setStrings(shaderStrings, 1);
1864
1865 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1866
Cody Northrop195d6622014-11-03 12:54:37 -07001867 if (! (m_compile_options & EOptionSuppressInfolog)) {
1868 puts(shader->getInfoLog());
1869 puts(shader->getInfoDebugLog());
1870 }
1871
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001872 return false; // something didn't work
1873 }
1874
1875 program.addShader(shader);
1876
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001877
1878 //
1879 // Program-level processing...
1880 //
1881
Cody Northrop195d6622014-11-03 12:54:37 -07001882 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001883
Cody Northrop195d6622014-11-03 12:54:37 -07001884 if (! (m_compile_options & EOptionSuppressInfolog)) {
1885 puts(shader->getInfoLog());
1886 puts(shader->getInfoDebugLog());
1887 }
1888
1889 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001890 }
1891
1892 if (m_compile_options & EOptionDumpReflection) {
1893 program.buildReflection();
1894 program.dumpReflection();
1895 }
1896
Cody Northrop5a95b472015-06-03 13:01:54 -06001897 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1898
1899 //
1900 // Test the different modes of SPIR-V modification
1901 //
1902 if (this->m_canonicalize_spv) {
1903 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1904 }
1905
1906 if (this->m_strip_spv) {
1907 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1908 }
1909
1910 if (this->m_do_everything_spv) {
1911 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1912 }
1913
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001914 delete shader;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001915
1916 return true;
1917}
1918
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001919
1920
Tony Barbour6918cd52015-04-09 12:58:51 -06001921VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001922 m_width( 0 ),
1923 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001924 m_data( NULL ),
1925 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001926{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001927}
1928
Tony Barbour6918cd52015-04-09 12:58:51 -06001929VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001930{
1931
1932}
1933
Tony Barbour6918cd52015-04-09 12:58:51 -06001934VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001935{
1936 m_title = copyin.m_title;
1937 m_width = copyin.m_width;
1938 m_height = copyin.m_height;
1939 m_data_size = copyin.m_data_size;
1940 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1941}
1942
Tony Barbour6918cd52015-04-09 12:58:51 -06001943ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001944{
Tony Barbour6918cd52015-04-09 12:58:51 -06001945 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1946 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001947 return output;
1948}
1949
Tony Barbour6918cd52015-04-09 12:58:51 -06001950VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001951{
1952 m_title = rhs.m_title;
1953 m_width = rhs.m_width;
1954 m_height = rhs.m_height;
1955 m_data_size = rhs.m_data_size;
1956 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001957 return *this;
1958}
1959
Tony Barbour6918cd52015-04-09 12:58:51 -06001960int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001961{
1962 if( this->m_data != rhs.m_data) return 0;
1963 return 1;
1964}
1965
1966// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001967int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001968{
1969 if( this->m_data_size < rhs.m_data_size ) return 1;
1970 return 0;
1971}
1972