blob: 205fbcbfb6ec279dd78aeba2dd74f4507e5d0191 [file] [log] [blame]
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001// VK tests
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06002//
3// Copyright (C) 2014 LunarG, Inc.
4//
5// Permission is hereby granted, free of charge, to any person obtaining a
6// copy of this software and associated documentation files (the "Software"),
7// to deal in the Software without restriction, including without limitation
8// the rights to use, copy, modify, merge, publish, distribute, sublicense,
9// and/or sell copies of the Software, and to permit persons to whom the
10// Software is furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included
13// in all copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21// DEALINGS IN THE SOFTWARE.
22
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060023#include "vktestframework.h"
24#include "vkrenderframework.h"
Cody Northrop5a95b472015-06-03 13:01:54 -060025#include "SPIRV/GlslangToSpv.h"
26#include "SPIRV/SPVRemapper.h"
Tony Barbour4ab45422014-12-10 17:00:20 -070027#include <limits.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060028#include <math.h>
Chia-I Wuec664fa2014-12-02 11:54:24 +080029#include <wand/MagickWand.h>
Tony Barbourfeb61962015-09-21 15:17:33 -060030#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +080031#include <xcb/xcb.h>
Tony Barbourfeb61962015-09-21 15:17:33 -060032#endif
Ian Elliott7e40db92015-08-21 15:09:33 -060033#include "vk_ext_khr_swapchain.h"
34#include "vk_ext_khr_device_swapchain.h"
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060035
Tony Barbour3d69c9e2015-05-20 16:53:31 -060036#if defined(PATH_MAX) && !defined(MAX_PATH)
37#define MAX_PATH PATH_MAX
38#endif
39
Tony Barbour6a3faf02015-07-23 10:36:18 -060040#ifdef _WIN32
41#define ERR_EXIT(err_msg, err_class) \
42 do { \
43 MessageBox(NULL, err_msg, err_class, MB_OK); \
44 exit(1); \
45 } while (0)
46#else // _WIN32
47
48#define ERR_EXIT(err_msg, err_class) \
49 do { \
50 printf(err_msg); \
51 fflush(stdout); \
52 exit(1); \
53 } while (0)
54#endif // _WIN32
55
56#define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \
57{ \
58 m_fp##entrypoint = (PFN_vk##entrypoint) vkGetInstanceProcAddr(inst, "vk"#entrypoint); \
59 if (m_fp##entrypoint == NULL) { \
60 ERR_EXIT("vkGetInstanceProcAddr failed to find vk"#entrypoint, \
61 "vkGetInstanceProcAddr Failure"); \
62 } \
63}
64
65#define GET_DEVICE_PROC_ADDR(dev, entrypoint) \
66{ \
67 m_fp##entrypoint = (PFN_vk##entrypoint) vkGetDeviceProcAddr(dev, "vk"#entrypoint); \
68 if (m_fp##entrypoint == NULL) { \
69 ERR_EXIT("vkGetDeviceProcAddr failed to find vk"#entrypoint, \
70 "vkGetDeviceProcAddr Failure"); \
71 } \
72}
73
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060074// Command-line options
75enum TOptions {
76 EOptionNone = 0x000,
77 EOptionIntermediate = 0x001,
78 EOptionSuppressInfolog = 0x002,
79 EOptionMemoryLeakMode = 0x004,
80 EOptionRelaxedErrors = 0x008,
81 EOptionGiveWarnings = 0x010,
82 EOptionLinkProgram = 0x020,
83 EOptionMultiThreaded = 0x040,
84 EOptionDumpConfig = 0x080,
85 EOptionDumpReflection = 0x100,
86 EOptionSuppressWarnings = 0x200,
87 EOptionDumpVersions = 0x400,
Cody Northrop3bfd27c2015-03-17 15:55:58 -060088 EOptionSpv = 0x800,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060089 EOptionDefaultDesktop = 0x1000,
90};
91
Ian Elliott7e40db92015-08-21 15:09:33 -060092typedef struct _SwapchainBuffers {
Tony Barbour6a3faf02015-07-23 10:36:18 -060093 VkImage image;
94 VkCmdBuffer cmd;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -060095 VkImageView view;
Ian Elliott7e40db92015-08-21 15:09:33 -060096} SwapchainBuffers;
Tony Barbour6a3faf02015-07-23 10:36:18 -060097
Chia-I Wuf8693382015-04-16 22:02:10 +080098class TestFrameworkVkPresent
99{
100public:
101 TestFrameworkVkPresent(vk_testing::Device &device);
102
103 void Run();
Jon Ashburn07daee72015-05-21 18:13:33 -0600104 void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst);
Chia-I Wuf8693382015-04-16 22:02:10 +0800105 void CreateMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -0600106 void CreateSwapchain();
Chia-I Wuf8693382015-04-16 22:02:10 +0800107 void TearDown();
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600108#ifdef _WIN32
109 static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
110#endif
111
Chia-I Wuf8693382015-04-16 22:02:10 +0800112
113protected:
114 vk_testing::Device &m_device;
115 vk_testing::Queue &m_queue;
Dana Jansens233a0ea2015-07-30 13:04:16 -0700116 vk_testing::CmdPool m_cmdpool;
Chia-I Wuf8693382015-04-16 22:02:10 +0800117 vk_testing::CmdBuffer m_cmdbuf;
118
119private:
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600120#ifdef _WIN32
121 HINSTANCE m_connection; // hInstance - Windows Instance
122 HWND m_window; // hWnd - window handle
123
124#else
Chia-I Wuf8693382015-04-16 22:02:10 +0800125 xcb_connection_t *m_connection;
126 xcb_screen_t *m_screen;
127 xcb_window_t m_window;
128 xcb_intern_atom_reply_t *m_atom_wm_delete_window;
Ian Elliott7e40db92015-08-21 15:09:33 -0600129 VkPlatformHandleXcbKHR m_platform_handle_xcb;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600130#endif
Courtney Goeltzenleuchterd6079ec2015-04-22 10:09:35 -0600131 std::list<VkTestImageRecord> m_images;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600132 uint32_t m_present_queue_node_index;
Chia-I Wuf8693382015-04-16 22:02:10 +0800133
Ian Elliott7e40db92015-08-21 15:09:33 -0600134 PFN_vkGetPhysicalDeviceSurfaceSupportKHR m_fpGetPhysicalDeviceSurfaceSupportKHR;
135 PFN_vkGetSurfacePropertiesKHR m_fpGetSurfacePropertiesKHR;
136 PFN_vkGetSurfaceFormatsKHR m_fpGetSurfaceFormatsKHR;
137 PFN_vkGetSurfacePresentModesKHR m_fpGetSurfacePresentModesKHR;
138 PFN_vkCreateSwapchainKHR m_fpCreateSwapchainKHR;
139 PFN_vkDestroySwapchainKHR m_fpDestroySwapchainKHR;
140 PFN_vkGetSwapchainImagesKHR m_fpGetSwapchainImagesKHR;
141 PFN_vkAcquireNextImageKHR m_fpAcquireNextImageKHR;
142 PFN_vkQueuePresentKHR m_fpQueuePresentKHR;
143 VkSurfaceDescriptionWindowKHR m_surface_description;
144 uint32_t m_swapchainImageCount;
145 VkSwapchainKHR m_swap_chain;
146 SwapchainBuffers *m_buffers;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600147 VkFormat m_format;
Ian Elliott7e40db92015-08-21 15:09:33 -0600148 VkColorSpaceKHR m_color_space;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600149
150 uint32_t m_current_buffer;
Chia-I Wuf8693382015-04-16 22:02:10 +0800151
152 bool m_quit;
153 bool m_pause;
154
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600155 int m_width;
156 int m_height;
Chia-I Wuf8693382015-04-16 22:02:10 +0800157
158 std::list<VkTestImageRecord>::iterator m_display_image;
159
160 void Display();
Tony Barbourfeb61962015-09-21 15:17:33 -0600161#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800162 void HandleEvent(xcb_generic_event_t *event);
Tony Barbourfeb61962015-09-21 15:17:33 -0600163#endif
Chia-I Wuf8693382015-04-16 22:02:10 +0800164};
165
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600166#ifndef _WIN32
167
168#include <errno.h>
169
170int fopen_s(
171 FILE** pFile,
172 const char* filename,
173 const char* mode
174)
175{
176 if (!pFile || !filename || !mode) {
177 return EINVAL;
178 }
179
180 FILE* f = fopen(filename, mode);
181 if (! f) {
182 if (errno != 0) {
183 return errno;
184 } else {
185 return ENOENT;
186 }
187 }
188 *pFile = f;
189
190 return 0;
191}
192
193#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600194
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600195
196
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600197// Set up environment for GLSL compiler
198// Must be done once per process
199void TestEnvironment::SetUp()
200{
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600201 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600202 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800203
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600204 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600205}
206
207void TestEnvironment::TearDown()
208{
209 glslang::FinalizeProcess();
210}
211
Tony Barbour6918cd52015-04-09 12:58:51 -0600212VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600213 m_compile_options( 0 ),
214 m_num_shader_strings( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600215{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600216
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600217}
218
Tony Barbour6918cd52015-04-09 12:58:51 -0600219VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600220{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600221
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600222}
223
224// Define all the static elements
Cody Northropa3673cf2015-06-09 13:00:45 -0600225bool VkTestFramework::m_show_images = false;
226bool VkTestFramework::m_save_images = false;
227bool VkTestFramework::m_compare_images = false;
228bool VkTestFramework::m_use_glsl = false;
229bool VkTestFramework::m_canonicalize_spv = false;
230bool VkTestFramework::m_strip_spv = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600231bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour6918cd52015-04-09 12:58:51 -0600232int VkTestFramework::m_width = 0;
233int VkTestFramework::m_height = 0;
234std::list<VkTestImageRecord> VkTestFramework::m_images;
235std::list<VkTestImageRecord>::iterator VkTestFramework::m_display_image;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600236int m_display_image_idx = 0;
237
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600238bool VkTestFramework::optionMatch(const char* option, char* optionLine)
239{
240 if (strncmp(option, optionLine, strlen(option)) == 0)
241 return true;
242 else
243 return false;
244}
245
Tony Barbour6918cd52015-04-09 12:58:51 -0600246void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600247{
248 int i, n;
249
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600250 for (i=1, n=1; i< *argc; i++) {
251 if (optionMatch("--show-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600252 m_show_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600253 else if (optionMatch("--save-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600254 m_save_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600255 else if (optionMatch("--no-SPV", argv[i]))
256 m_use_glsl = true;
257 else if (optionMatch("--strip-SPV", argv[i]))
258 m_strip_spv = true;
259 else if (optionMatch("--canonicalize-SPV", argv[i]))
260 m_canonicalize_spv = true;
261 else if (optionMatch("--compare-images", argv[i]))
Tony Barbour247bf372014-10-30 14:29:04 -0600262 m_compare_images = true;
Tony Barbour247bf372014-10-30 14:29:04 -0600263
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600264 else if (optionMatch("--help", argv[i]) ||
265 optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700266 printf("\nOther options:\n");
267 printf("\t--show-images\n"
268 "\t\tDisplay test images in viewer after tests complete.\n");
269 printf("\t--save-images\n"
270 "\t\tSave tests images as ppm files in current working directory.\n"
271 "\t\tUsed to generate golden images for compare-images.\n");
272 printf("\t--compare-images\n"
273 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barboura98d3932014-12-11 09:52:49 -0700274 "\t\tAlso saves the generated test image in current working\n"
275 "\t\t\tdirectory but only if the image is different from the golden\n"
276 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
277 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700278 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600279 printf("\t--no-SPV\n"
280 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600281 printf("\t--strip-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600282 "\t\tStrip SPIR-V debug information (line numbers, names, etc).\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600283 printf("\t--canonicalize-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600284 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600285 exit(0);
286 } else {
287 printf("\nUnrecognized option: %s\n", argv[i]);
288 printf("\nUse --help or -h for option list.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700289 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700290 }
291
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600292 /*
293 * Since the above "consume" inputs, update argv
294 * so that it contains the trimmed list of args for glutInit
295 */
296
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600297 argv[n] = argv[i];
298 n++;
299 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600300}
301
Tony Barbour6918cd52015-04-09 12:58:51 -0600302void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600303{
304 string filename;
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600305 VkResult err;
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600306 uint32_t x, y;
Tony Barbour6918cd52015-04-09 12:58:51 -0600307 VkImageObj displayImage(image->device());
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600308 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbour84d448c2015-04-02 14:02:33 -0600309
Tony Barboure65788f2015-07-21 17:01:42 -0600310 displayImage.init(image->extent().width, image->extent().height, image->format(), VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT, VK_IMAGE_TILING_LINEAR, reqs);
Tony Barbour84d448c2015-04-02 14:02:33 -0600311 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600312
313 filename.append(basename);
314 filename.append(".ppm");
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600315
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600316 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600317 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600318 };
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600319 VkSubresourceLayout sr_layout;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600320
Tony Barbour59a47322015-06-24 16:06:58 -0600321 err = vkGetImageSubresourceLayout(image->device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600322 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600323
Tony Barbour84d448c2015-04-02 14:02:33 -0600324 char *ptr;
Chia-I Wu681d7a02015-07-03 13:44:34 +0800325 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600326 ptr += sr_layout.offset;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600327 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600328 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
329
330 file << "P6\n";
Tony Barbourfeb61962015-09-21 15:17:33 -0600331 file << displayImage.width() << " ";
Tony Barbour84d448c2015-04-02 14:02:33 -0600332 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600333 file << 255 << "\n";
334
Tony Barbour84d448c2015-04-02 14:02:33 -0600335 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700336 const int *row = (const int *) ptr;
337 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600338
Tony Barbourd1c35722015-04-16 15:59:00 -0600339 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700340 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600341 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700342 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
343 file.write((char *) &swapped, 3);
344 row++;
345 }
346 }
Tony Barbourd1c35722015-04-16 15:59:00 -0600347 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700348 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600349 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700350 file.write((char *) row, 3);
351 row++;
352 }
353 }
354 else {
355 printf("Unrecognized image format - will not write image files");
356 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600357 }
358
359 ptr += sr_layout.rowPitch;
360 }
361
362 file.close();
Chia-I Wu681d7a02015-07-03 13:44:34 +0800363 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600364}
365
Tony Barbour6918cd52015-04-09 12:58:51 -0600366void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour247bf372014-10-30 14:29:04 -0600367{
368
369 MagickWand *magick_wand_1;
370 MagickWand *magick_wand_2;
371 MagickWand *compare_wand;
372 MagickBooleanType status;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600373 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600374 double differenz;
375
Tony Barbour4ab45422014-12-10 17:00:20 -0700376 if (getenv("RENDERTEST_GOLDEN_DIR"))
377 {
378 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
379 }
380
Tony Barbour247bf372014-10-30 14:29:04 -0600381 MagickWandGenesis();
382 magick_wand_1=NewMagickWand();
383 sprintf(testimage,"%s.ppm",basename);
384 status=MagickReadImage(magick_wand_1,testimage);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600385 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour247bf372014-10-30 14:29:04 -0600386
387
388 MagickWandGenesis();
389 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700390 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600391 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600392 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour247bf372014-10-30 14:29:04 -0600393
Tony Barbour247bf372014-10-30 14:29:04 -0600394 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
395 if (differenz != 0.0)
396 {
397 char difference[256];
398
399 sprintf(difference,"%s-diff.ppm",basename);
400 status = MagickWriteImage(compare_wand, difference);
401 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
402 }
403 DestroyMagickWand(compare_wand);
404
405 DestroyMagickWand(magick_wand_1);
406 DestroyMagickWand(magick_wand_2);
407 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700408
409 if (differenz == 0.0)
410 {
411 /*
412 * If test image and golden image match, we do not need to
413 * keep around the test image.
414 */
415 remove(testimage);
416 }
Tony Barbour247bf372014-10-30 14:29:04 -0600417}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600418
Tony Barbour6918cd52015-04-09 12:58:51 -0600419void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600420{
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600421 VkResult err;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600422 VkSubresourceLayout sr_layout;
423 char *ptr;
424 VkTestImageRecord record;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600425 VkImageObj displayImage(image->device());
426 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
427
Cody Northropc9a69912015-06-18 17:05:15 -0600428 displayImage.init(image->extent().width, image->extent().height, image->format(), VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT, VK_IMAGE_TILING_LINEAR, reqs);
429
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600430 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600431
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600432 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600433 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600434 };
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600435
Tony Barbour59a47322015-06-24 16:06:58 -0600436 err = vkGetImageSubresourceLayout(displayImage.device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600437 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600438
Chia-I Wu681d7a02015-07-03 13:44:34 +0800439 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600440 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600441
442 ptr += sr_layout.offset;
443
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600444 record.m_title.append(comment);
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600445 record.m_width = displayImage.width();
446 record.m_height = displayImage.height();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600447 // TODO: Need to make this more robust to handle different image formats
Tony-LunarG399dfca2015-05-19 14:08:26 -0600448 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600449 record.m_data = malloc(record.m_data_size);
450 memcpy(record.m_data, ptr, record.m_data_size);
451 m_images.push_back(record);
452 m_display_image = --m_images.end();
453
Chia-I Wu681d7a02015-07-03 13:44:34 +0800454 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600455}
456
Tony Barbour6918cd52015-04-09 12:58:51 -0600457void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600458{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600459 for (int32_t i = 0; i < images.size(); i++) {
460 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600461 }
462}
463
Tony Barbour6918cd52015-04-09 12:58:51 -0600464void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600465{
466 const ::testing::TestInfo* const test_info =
467 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600468 ostringstream filestream;
469 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600470
Tony Barbour247bf372014-10-30 14:29:04 -0600471 m_width = 40;
472
473 if (strcmp(test_info->name(), m_testName.c_str())) {
474 filestream << test_info->name();
475 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700476 m_frameNum = 2;
477 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600478 }
479 else {
480 filestream << test_info->name() << "-" << m_frameNum;
481 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700482 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600483 }
484
Tony Barbour247bf372014-10-30 14:29:04 -0600485 // ToDo - scrub string for bad characters
486
487 if (m_save_images || m_compare_images) {
488 WritePPM(filename.c_str(), image);
489 if (m_compare_images) {
490 Compare(filename.c_str(), image);
491 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600492 }
493
494 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600495 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600496 }
497}
498
Chia-I Wuf8693382015-04-16 22:02:10 +0800499TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
500 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700501 m_queue(*m_device.graphics_queues()[0]),
Dana Jansens233a0ea2015-07-30 13:04:16 -0700502 m_cmdpool(m_device, vk_testing::CmdPool::create_info(m_device.graphics_queue_node_index_)),
503 m_cmdbuf(m_device, vk_testing::CmdBuffer::create_info(m_cmdpool.handle()))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600504{
Tony Barbour96db8822015-02-25 12:28:39 -0700505 m_quit = false;
506 m_pause = false;
507 m_width = 0;
508 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600509}
510
Tony Barbour6918cd52015-04-09 12:58:51 -0600511void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600512{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600513 VkResult U_ASSERT_ONLY err;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600514 vk_testing::Buffer buf;
515 void *dest_ptr;
516
Tony Barbour6a3faf02015-07-23 10:36:18 -0600517 VkSemaphore presentCompleteSemaphore;
518 VkSemaphoreCreateInfo presentCompleteSemaphoreCreateInfo = {};
519 presentCompleteSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
520 presentCompleteSemaphoreCreateInfo.pNext = NULL;
521 presentCompleteSemaphoreCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
522
523
524 err = vkCreateSemaphore(m_device.handle(),
525 &presentCompleteSemaphoreCreateInfo,
526 &presentCompleteSemaphore);
527 assert(!err);
528
529 // Get the index of the next available swapchain image:
Ian Elliott7e40db92015-08-21 15:09:33 -0600530 err = m_fpAcquireNextImageKHR(m_device.handle(), m_swap_chain,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600531 UINT64_MAX,
532 presentCompleteSemaphore,
533 &m_current_buffer);
Ian Elliott7e40db92015-08-21 15:09:33 -0600534 // TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
Tony Barbour6a3faf02015-07-23 10:36:18 -0600535 // return codes
536 assert(!err);
537
538 // Wait for the present complete semaphore to be signaled to ensure
539 // that the image won't be rendered to until the presentation
540 // engine has fully released ownership to the application, and it is
541 // okay to render to the image.
542 vkQueueWaitSemaphore(m_queue.handle(), presentCompleteSemaphore);
Tony Barbour9226a822015-10-23 10:58:56 -0600543 vkDestroySemaphore(m_device.handle(), presentCompleteSemaphore);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600544
545 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Cody Northrop7fb43862015-06-22 14:56:14 -0600546 buf.init_as_src(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800547 dest_ptr = buf.memory().map();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600548 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800549 buf.memory().unmap();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600550
551 m_cmdbuf.begin();
552
553 VkBufferImageCopy region = {};
554 region.imageExtent.height = m_display_image->m_height;
555 region.imageExtent.width = m_display_image->m_width;
556 region.imageExtent.depth = 1;
557
Chia-I Wube2b9172015-07-03 11:49:42 +0800558 vkCmdCopyBufferToImage(m_cmdbuf.handle(),
Chia-I Wu681d7a02015-07-03 13:44:34 +0800559 buf.handle(),
Tony Barbour6a3faf02015-07-23 10:36:18 -0600560 m_buffers[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600561 1, &region);
562 m_cmdbuf.end();
563
564 VkCmdBuffer cmdBufs[1];
Chia-I Wube2b9172015-07-03 11:49:42 +0800565 cmdBufs[0] = m_cmdbuf.handle();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600566
Tony Barbour67e99152015-07-10 14:10:27 -0600567 VkFence nullFence = { VK_NULL_HANDLE };
568 vkQueueSubmit(m_queue.handle(), 1, cmdBufs, nullFence);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600569 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700570
Ian Elliott7e40db92015-08-21 15:09:33 -0600571 VkPresentInfoKHR present = {};
572 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600573 present.pNext = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600574 present.swapchainCount = 1;
575 present.swapchains = & m_swap_chain;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600576 present.imageIndices = &m_current_buffer;
Tony Barbour96db8822015-02-25 12:28:39 -0700577
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600578#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800579 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700580 XCB_PROP_MODE_REPLACE,
581 m_window,
582 XCB_ATOM_WM_NAME,
583 XCB_ATOM_STRING,
584 8,
585 m_display_image->m_title.size(),
586 m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600587#endif
Jon Ashburn07daee72015-05-21 18:13:33 -0600588
Ian Elliott7e40db92015-08-21 15:09:33 -0600589 err = m_fpQueuePresentKHR(m_queue.handle(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700590 assert(!err);
591
592 m_queue.wait();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600593 m_current_buffer = (m_current_buffer + 1) % 2;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600594}
595
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600596#ifdef _WIN32
Tony-LunarG399dfca2015-05-19 14:08:26 -0600597# define PREVIOUSLY_DOWN 1<<29
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600598// MS-Windows event handling function:
599LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
600 UINT uMsg,
601 WPARAM wParam,
602 LPARAM lParam)
603{
604
605 switch(uMsg)
606 {
607 case WM_CLOSE:
608 PostQuitMessage(0);
609 break;
610
611 case WM_PAINT:
612 {
613 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
614 if (me) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600615 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600616 me->Display();
617 }
618 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600619 break;
620
621 case WM_KEYDOWN:
622 {
623 if (lParam & (PREVIOUSLY_DOWN)){
624 break;
625 }
626 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
627 // the window, we put the this pointer into the window's user data so we could get it back now
628 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
629 switch (wParam)
630 {
631 case VK_ESCAPE: me->m_quit = true;
632 break;
633
634 case VK_LEFT: // left arrow key
635 if (me->m_display_image == me->m_images.begin()) {
636 me->m_display_image = --me->m_images.end();
637 }
638 else {
639 --me->m_display_image;
640 }
641 break;
642
643 case VK_RIGHT: // right arrow key
644 ++me->m_display_image;
645 if (me->m_display_image == me->m_images.end()) {
646 me->m_display_image = me->m_images.begin();
647 }
648 break;
649
650 default:
651 break;
652 }
653 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
654 me->Display();
655 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600656 }
657 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
658}
659
660void TestFrameworkVkPresent::Run()
661{
662 MSG msg; // message
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600663
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600664 /* main message loop*/
Tony-LunarG399dfca2015-05-19 14:08:26 -0600665 while(! m_quit) {
666 GetMessage(&msg, m_window, 0, 0);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600667 if (msg.message == WM_QUIT) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600668 m_quit = true; //if found, quit app
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600669 } else {
670 /* Translate and dispatch to event queue*/
671 TranslateMessage(&msg);
672 DispatchMessage(&msg);
673 }
674 }
675}
676
677#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600678void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600679{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600680 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700681 switch (event_code) {
682 case XCB_EXPOSE:
683 Display(); // TODO: handle resize
684 break;
685 case XCB_CLIENT_MESSAGE:
686 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
687 (m_atom_wm_delete_window)->atom) {
688 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600689 }
690 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700691 case XCB_KEY_RELEASE:
692 {
693 const xcb_key_release_event_t *key =
694 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600695
Tony Barbour96db8822015-02-25 12:28:39 -0700696 switch (key->detail) {
697 case 0x9: // Escape
698 m_quit = true;
699 break;
700 case 0x71: // left arrow key
701 if (m_display_image == m_images.begin()) {
702 m_display_image = --m_images.end();
703 } else {
704 --m_display_image;
705 }
706 break;
707 case 0x72: // right arrow key
708 ++m_display_image;
709 if (m_display_image == m_images.end()) {
710 m_display_image = m_images.begin();
711 }
712 break;
713 case 0x41:
714 m_pause = !m_pause;
715 break;
716 }
717 Display();
718 }
719 break;
720 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600721 break;
722 }
Tony Barbour96db8822015-02-25 12:28:39 -0700723}
724
Tony Barbour6918cd52015-04-09 12:58:51 -0600725void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700726{
Chia-I Wuf8693382015-04-16 22:02:10 +0800727 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700728
729 while (! m_quit) {
730 xcb_generic_event_t *event;
731
732 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800733 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700734 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800735 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700736 }
737 if (event) {
738 HandleEvent(event);
739 free(event);
740 }
741 }
742}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600743#endif // _WIN32
Tony Barbour96db8822015-02-25 12:28:39 -0700744
Ian Elliott7e40db92015-08-21 15:09:33 -0600745void TestFrameworkVkPresent::CreateSwapchain()
Tony Barbour96db8822015-02-25 12:28:39 -0700746{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600747 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700748
Tony-LunarG399dfca2015-05-19 14:08:26 -0600749 m_display_image = m_images.begin();
750 m_current_buffer = 0;
751
Tony Barbour6a3faf02015-07-23 10:36:18 -0600752 // Construct the WSI surface description:
Ian Elliott7e40db92015-08-21 15:09:33 -0600753 m_surface_description.sType = VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600754 m_surface_description.pNext = NULL;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600755#ifdef _WIN32
Ian Elliott7e40db92015-08-21 15:09:33 -0600756 m_surface_description.platform = VK_PLATFORM_WIN32_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600757 m_surface_description.pPlatformHandle = m_connection;
758 m_surface_description.pPlatformWindow = m_window;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600759#else // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -0600760 m_platform_handle_xcb.connection = m_connection;
761 m_platform_handle_xcb.root = m_screen->root;
Ian Elliott7e40db92015-08-21 15:09:33 -0600762 m_surface_description.platform = VK_PLATFORM_XCB_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600763 m_surface_description.pPlatformHandle = &m_platform_handle_xcb;
764 m_surface_description.pPlatformWindow = &m_window;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600765#endif // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -0600766
767 // Iterate over each queue to learn whether it supports presenting to WSI:
768 VkBool32 supportsPresent;
769 m_present_queue_node_index = UINT32_MAX;
770 std::vector<vk_testing::Queue *> queues = m_device.graphics_queues();
771 for (int i=0; i < queues.size(); i++)
772 {
773 int family_index = queues[i]->get_family_index();
Ian Elliott7e40db92015-08-21 15:09:33 -0600774 m_fpGetPhysicalDeviceSurfaceSupportKHR(m_device.phy().handle(),
Tony Barbour6a3faf02015-07-23 10:36:18 -0600775 family_index,
Ian Elliott7e40db92015-08-21 15:09:33 -0600776 (VkSurfaceDescriptionKHR *) &m_surface_description,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600777 &supportsPresent);
778 if (supportsPresent) {
779 m_present_queue_node_index = family_index;
780 }
781 }
782
783 assert(m_present_queue_node_index != UINT32_MAX);
784
785
786 // Get the list of VkFormat's that are supported:
Ian Elliott8b139792015-08-07 11:51:12 -0600787 uint32_t formatCount;
Ian Elliott7e40db92015-08-21 15:09:33 -0600788 err = m_fpGetSurfaceFormatsKHR(m_device.handle(),
789 (VkSurfaceDescriptionKHR *) &m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600790 &formatCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600791 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600792 VkSurfaceFormatKHR *surfFormats =
793 (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
794 err = m_fpGetSurfaceFormatsKHR(m_device.handle(),
795 (VkSurfaceDescriptionKHR *) &m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600796 &formatCount, surfFormats);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600797 assert(!err);
798 // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
799 // the surface has no preferred format. Otherwise, at least one
800 // supported format will be returned.
Tony Barbour6a3faf02015-07-23 10:36:18 -0600801 if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED)
802 {
803 m_format = VK_FORMAT_B8G8R8A8_UNORM;
804 }
805 else
806 {
807 assert(formatCount >= 1);
808 m_format = surfFormats[0].format;
809 }
Ian Elliott8b139792015-08-07 11:51:12 -0600810 m_color_space = surfFormats[0].colorSpace;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600811
812 // Check the surface proprties and formats
Ian Elliott7e40db92015-08-21 15:09:33 -0600813 VkSurfacePropertiesKHR surfProperties;
814 err = m_fpGetSurfacePropertiesKHR(m_device.handle(),
815 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600816 &surfProperties);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600817 assert(!err);
818
Ian Elliott8b139792015-08-07 11:51:12 -0600819 uint32_t presentModeCount;
Ian Elliott7e40db92015-08-21 15:09:33 -0600820 err = m_fpGetSurfacePresentModesKHR(m_device.handle(),
821 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600822 &presentModeCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600823 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600824 VkPresentModeKHR *presentModes =
825 (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
Ian Elliott8b139792015-08-07 11:51:12 -0600826 assert(presentModes);
Ian Elliott7e40db92015-08-21 15:09:33 -0600827 err = m_fpGetSurfacePresentModesKHR(m_device.handle(),
828 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600829 &presentModeCount, presentModes);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600830 assert(!err);
831
Ian Elliott7e40db92015-08-21 15:09:33 -0600832 VkExtent2D swapchainExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600833 // width and height are either both -1, or both not -1.
Ian Elliott8b139792015-08-07 11:51:12 -0600834 if (surfProperties.currentExtent.width == -1)
Tony Barbour6a3faf02015-07-23 10:36:18 -0600835 {
836 // If the surface size is undefined, the size is set to
837 // the size of the images requested.
Ian Elliott7e40db92015-08-21 15:09:33 -0600838 swapchainExtent.width = m_width;
839 swapchainExtent.height = m_height;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600840 }
841 else
842 {
843 // If the surface size is defined, the swap chain size must match
Ian Elliott7e40db92015-08-21 15:09:33 -0600844 swapchainExtent = surfProperties.currentExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600845 }
846
847 // If mailbox mode is available, use it, as is the lowest-latency non-
Ian Elliottae0e8242015-08-10 13:20:49 -0600848 // tearing mode. If not, try IMMEDIATE which will usually be available,
849 // and is fastest (though it tears). If not, fall back to FIFO which is
850 // always available.
Ian Elliott7e40db92015-08-21 15:09:33 -0600851 VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600852 for (size_t i = 0; i < presentModeCount; i++) {
Ian Elliott7e40db92015-08-21 15:09:33 -0600853 if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
854 swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600855 break;
856 }
Ian Elliott7e40db92015-08-21 15:09:33 -0600857 if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) &&
858 (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
859 swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
Ian Elliottae0e8242015-08-10 13:20:49 -0600860 }
Tony Barbour6a3faf02015-07-23 10:36:18 -0600861 }
862
863 // Determine the number of VkImage's to use in the swap chain (we desire to
864 // own only 1 image at a time, besides the images being displayed and
865 // queued for display):
Ian Elliott7e40db92015-08-21 15:09:33 -0600866 uint32_t desiredNumberOfSwapchainImages = surfProperties.minImageCount + 1;
Ian Elliott8b139792015-08-07 11:51:12 -0600867 if ((surfProperties.maxImageCount > 0) &&
Ian Elliott7e40db92015-08-21 15:09:33 -0600868 (desiredNumberOfSwapchainImages > surfProperties.maxImageCount))
Tony Barbour6a3faf02015-07-23 10:36:18 -0600869 {
870 // Application must settle for fewer images than desired:
Ian Elliott7e40db92015-08-21 15:09:33 -0600871 desiredNumberOfSwapchainImages = surfProperties.maxImageCount;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600872 }
873
Ian Elliott7e40db92015-08-21 15:09:33 -0600874 VkSurfaceTransformKHR preTransform;
875 if (surfProperties.supportedTransforms & VK_SURFACE_TRANSFORM_NONE_BIT_KHR) {
876 preTransform = VK_SURFACE_TRANSFORM_NONE_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600877 } else {
Ian Elliott8b139792015-08-07 11:51:12 -0600878 preTransform = surfProperties.currentTransform;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600879 }
Ian Elliott1a3845b2015-07-06 14:33:04 -0600880
Cody Northropdf5b0922015-08-28 16:22:48 -0600881 // We want to blit to the swap chain, ensure the driver supports it. Color is always supported, per WSI spec.
882 assert((surfProperties.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT) != 0);
883
Ian Elliott7e40db92015-08-21 15:09:33 -0600884 VkSwapchainCreateInfoKHR swap_chain = {};
Ian Elliotta257eea2015-09-22 10:20:23 -0600885 swap_chain.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600886 swap_chain.pNext = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600887 swap_chain.pSurfaceDescription = (const VkSurfaceDescriptionKHR *)&m_surface_description;
888 swap_chain.minImageCount = desiredNumberOfSwapchainImages;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600889 swap_chain.imageFormat = m_format;
Ian Elliott8b139792015-08-07 11:51:12 -0600890 swap_chain.imageColorSpace = m_color_space;
Ian Elliott7e40db92015-08-21 15:09:33 -0600891 swap_chain.imageExtent.width = swapchainExtent.width;
892 swap_chain.imageExtent.height = swapchainExtent.height;
Cody Northropdf8f42a2015-08-05 15:38:39 -0600893 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT |
894 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600895 swap_chain.preTransform = preTransform;
Chia-I Wuf8693382015-04-16 22:02:10 +0800896 swap_chain.imageArraySize = 1;
Ian Elliott8b139792015-08-07 11:51:12 -0600897 swap_chain.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
898 swap_chain.queueFamilyCount = 0;
899 swap_chain.pQueueFamilyIndices = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600900 swap_chain.presentMode = swapchainPresentMode;
901 swap_chain.oldSwapchain.handle = 0;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600902 swap_chain.clipped = true;
903
904 uint32_t i;
Chia-I Wuf8693382015-04-16 22:02:10 +0800905
Ian Elliott7e40db92015-08-21 15:09:33 -0600906 err = m_fpCreateSwapchainKHR(m_device.handle(), &swap_chain, &m_swap_chain);
Chia-I Wuf8693382015-04-16 22:02:10 +0800907 assert(!err);
908
Ian Elliott7e40db92015-08-21 15:09:33 -0600909 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
910 &m_swapchainImageCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600911 assert(!err);
912
Ian Elliott7e40db92015-08-21 15:09:33 -0600913 VkImage* swapchainImages = (VkImage*)malloc(m_swapchainImageCount * sizeof(VkImage));
914 assert(swapchainImages);
915 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
916 &m_swapchainImageCount, swapchainImages);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600917 assert(!err);
918
Ian Elliott7e40db92015-08-21 15:09:33 -0600919 m_buffers = (SwapchainBuffers*)malloc(sizeof(SwapchainBuffers)*m_swapchainImageCount);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600920 assert(m_buffers);
921
Ian Elliott7e40db92015-08-21 15:09:33 -0600922 for (i = 0; i < m_swapchainImageCount; i++) {
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600923 VkImageViewCreateInfo color_image_view = {};
924 color_image_view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
925 color_image_view.pNext = NULL;
Courtney Goeltzenleuchter00265c82015-09-11 15:22:06 -0600926 color_image_view.viewType = VK_IMAGE_VIEW_TYPE_2D;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600927 color_image_view.format = m_format;
Courtney Goeltzenleuchterba724512015-09-10 17:58:54 -0600928 color_image_view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600929 color_image_view.subresourceRange.baseMipLevel = 0;
930 color_image_view.subresourceRange.mipLevels = 1;
Courtney Goeltzenleuchter4a261892015-09-10 16:38:41 -0600931 color_image_view.subresourceRange.baseArrayLayer = 0;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600932 color_image_view.subresourceRange.arraySize = 1;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600933
Ian Elliott7e40db92015-08-21 15:09:33 -0600934 m_buffers[i].image = swapchainImages[i];
Tony Barbour6a3faf02015-07-23 10:36:18 -0600935
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600936 color_image_view.image = m_buffers[i].image;
937 err = vkCreateImageView(m_device.handle(),
938 &color_image_view, &m_buffers[i].view);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600939 assert(!err);
940 }
Tony Barbour96db8822015-02-25 12:28:39 -0700941}
942
Jon Ashburn07daee72015-05-21 18:13:33 -0600943void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -0700944{
Ian Elliott7e40db92015-08-21 15:09:33 -0600945 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceSupportKHR);
946 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfacePropertiesKHR);
947 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfaceFormatsKHR);
948 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfacePresentModesKHR);
949 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
950 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
951 GET_DEVICE_PROC_ADDR(m_device.handle(), DestroySwapchainKHR);
952 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSwapchainImagesKHR);
953 GET_DEVICE_PROC_ADDR(m_device.handle(), AcquireNextImageKHR);
954 GET_DEVICE_PROC_ADDR(m_device.handle(), QueuePresentKHR);
Jon Ashburn07daee72015-05-21 18:13:33 -0600955
Tony Barbour96db8822015-02-25 12:28:39 -0700956 m_images = imagesIn;
957}
958
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600959#ifdef _WIN32
960void TestFrameworkVkPresent::CreateMyWindow()
961{
962 WNDCLASSEX win_class;
963 // const ::testing::TestInfo* const test_info =
964 // ::testing::UnitTest::GetInstance()->current_test_info();
965 m_connection = GetModuleHandle(NULL);
966
967 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
968 it != m_images.end(); it++) {
969 if (m_width < it->m_width)
970 m_width = it->m_width;
971 if (m_height < it->m_height)
972 m_height = it->m_height;
973 }
974 // Initialize the window class structure:
975 win_class.cbSize = sizeof(WNDCLASSEX);
976 win_class.style = CS_HREDRAW | CS_VREDRAW;
977 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
978 win_class.cbClsExtra = 0;
979 win_class.cbWndExtra = 0;
980 win_class.hInstance = m_connection; // hInstance
981 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
982 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
983 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
984 win_class.lpszMenuName = NULL;
985 win_class.lpszClassName = "Test";
986 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
987 // Register window class:
988 if (!RegisterClassEx(&win_class)) {
989 // It didn't work, so try to give a useful error:
990 printf("Unexpected error trying to start the application!\n");
991 fflush(stdout);
992 exit(1);
993 }
994 // Create window with the registered class:
Cody Northrop39582252015-08-05 15:39:31 -0600995 RECT wr = { 0, 0, m_width, m_height };
996 AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600997 m_window = CreateWindowEx(0,
998 "Test", // class name
999 "Test", // app name
1000 WS_OVERLAPPEDWINDOW | // window style
1001 WS_VISIBLE |
1002 WS_SYSMENU,
1003 100,100, // x/y coords
Cody Northrop39582252015-08-05 15:39:31 -06001004 wr.right - wr.left, // width
1005 wr.bottom - wr.top, // height
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001006 NULL, // handle to parent
1007 NULL, // handle to menu
1008 m_connection, // hInstance
1009 NULL); // no extra parameters
1010
1011 if (!m_window) {
1012 // It didn't work, so try to give a useful error:
1013 DWORD error = GetLastError();
1014 char message[120];
1015 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
1016 MessageBox(NULL, message, "Error", MB_OK);
1017 exit(1);
1018 }
Tony-LunarG399dfca2015-05-19 14:08:26 -06001019 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
1020 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001021}
1022#else
Tony Barbour6918cd52015-04-09 12:58:51 -06001023void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -07001024{
Chia-I Wuf8693382015-04-16 22:02:10 +08001025 const xcb_setup_t *setup;
1026 xcb_screen_iterator_t iter;
1027 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -07001028 uint32_t value_mask, value_list[32];
1029
Chia-I Wuf8693382015-04-16 22:02:10 +08001030 m_connection = xcb_connect(NULL, &scr);
1031
1032 setup = xcb_get_setup(m_connection);
1033 iter = xcb_setup_roots_iterator(setup);
1034 while (scr-- > 0)
1035 xcb_screen_next(&iter);
1036
1037 m_screen = iter.data;
1038
1039 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1040 it != m_images.end(); it++) {
1041 if (m_width < it->m_width)
1042 m_width = it->m_width;
1043 if (m_height < it->m_height)
1044 m_height = it->m_height;
1045 }
1046
1047 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -07001048
1049 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +08001050 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -07001051 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
1052 XCB_EVENT_MASK_EXPOSURE |
1053 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
1054
Chia-I Wuf8693382015-04-16 22:02:10 +08001055 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -07001056 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001057 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -07001058 0, 0, m_width, m_height, 0,
1059 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001060 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -07001061 value_mask, value_list);
1062
1063 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +08001064 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -07001065 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +08001066 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001067
Chia-I Wuf8693382015-04-16 22:02:10 +08001068 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
1069 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001070
Chia-I Wuf8693382015-04-16 22:02:10 +08001071 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -07001072 m_window, (*reply).atom, 4, 32, 1,
1073 &(*m_atom_wm_delete_window).atom);
1074 free(reply);
1075
Chia-I Wuf8693382015-04-16 22:02:10 +08001076 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -07001077}
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001078#endif
Tony Barbour96db8822015-02-25 12:28:39 -07001079
Tony Barbour6918cd52015-04-09 12:58:51 -06001080void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -07001081{
Ian Elliott7e40db92015-08-21 15:09:33 -06001082 m_fpDestroySwapchainKHR(m_device.handle(), m_swap_chain);
Tony Barbour9226a822015-10-23 10:58:56 -06001083
1084 for (uint32_t i = 0; i < m_swapchainImageCount; i++) {
1085 vkDestroyImageView(m_device.handle(), m_buffers[i].view);
1086 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001087#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +08001088 xcb_destroy_window(m_connection, m_window);
1089 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001090#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001091}
1092
Tony Barbour6918cd52015-04-09 12:58:51 -06001093void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001094{
1095 if (m_images.size() == 0) return;
1096
Chia-I Wuf8693382015-04-16 22:02:10 +08001097 vk_testing::Environment env;
1098 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -07001099 {
Chia-I Wuf8693382015-04-16 22:02:10 +08001100 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -07001101
Jon Ashburn07daee72015-05-21 18:13:33 -06001102 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001103 vkPresent.CreateMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -06001104 vkPresent.CreateSwapchain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001105 vkPresent.Run();
1106 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -07001107 }
Chia-I Wuf8693382015-04-16 22:02:10 +08001108 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001109}
1110
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001111//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001112// These are the default resources for TBuiltInResources, used for both
1113// - parsing this string for the case where the user didn't supply one
1114// - dumping out a template for user construction of a config file
1115//
1116static const char* DefaultConfig =
1117 "MaxLights 32\n"
1118 "MaxClipPlanes 6\n"
1119 "MaxTextureUnits 32\n"
1120 "MaxTextureCoords 32\n"
1121 "MaxVertexAttribs 64\n"
1122 "MaxVertexUniformComponents 4096\n"
1123 "MaxVaryingFloats 64\n"
1124 "MaxVertexTextureImageUnits 32\n"
1125 "MaxCombinedTextureImageUnits 80\n"
1126 "MaxTextureImageUnits 32\n"
1127 "MaxFragmentUniformComponents 4096\n"
1128 "MaxDrawBuffers 32\n"
1129 "MaxVertexUniformVectors 128\n"
1130 "MaxVaryingVectors 8\n"
1131 "MaxFragmentUniformVectors 16\n"
1132 "MaxVertexOutputVectors 16\n"
1133 "MaxFragmentInputVectors 15\n"
1134 "MinProgramTexelOffset -8\n"
1135 "MaxProgramTexelOffset 7\n"
1136 "MaxClipDistances 8\n"
1137 "MaxComputeWorkGroupCountX 65535\n"
1138 "MaxComputeWorkGroupCountY 65535\n"
1139 "MaxComputeWorkGroupCountZ 65535\n"
1140 "MaxComputeWorkGroupSizeX 1024\n"
1141 "MaxComputeWorkGroupSizeY 1024\n"
1142 "MaxComputeWorkGroupSizeZ 64\n"
1143 "MaxComputeUniformComponents 1024\n"
1144 "MaxComputeTextureImageUnits 16\n"
1145 "MaxComputeImageUniforms 8\n"
1146 "MaxComputeAtomicCounters 8\n"
1147 "MaxComputeAtomicCounterBuffers 1\n"
1148 "MaxVaryingComponents 60\n"
1149 "MaxVertexOutputComponents 64\n"
1150 "MaxGeometryInputComponents 64\n"
1151 "MaxGeometryOutputComponents 128\n"
1152 "MaxFragmentInputComponents 128\n"
1153 "MaxImageUnits 8\n"
1154 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
1155 "MaxCombinedShaderOutputResources 8\n"
1156 "MaxImageSamples 0\n"
1157 "MaxVertexImageUniforms 0\n"
1158 "MaxTessControlImageUniforms 0\n"
1159 "MaxTessEvaluationImageUniforms 0\n"
1160 "MaxGeometryImageUniforms 0\n"
1161 "MaxFragmentImageUniforms 8\n"
1162 "MaxCombinedImageUniforms 8\n"
1163 "MaxGeometryTextureImageUnits 16\n"
1164 "MaxGeometryOutputVertices 256\n"
1165 "MaxGeometryTotalOutputComponents 1024\n"
1166 "MaxGeometryUniformComponents 1024\n"
1167 "MaxGeometryVaryingComponents 64\n"
1168 "MaxTessControlInputComponents 128\n"
1169 "MaxTessControlOutputComponents 128\n"
1170 "MaxTessControlTextureImageUnits 16\n"
1171 "MaxTessControlUniformComponents 1024\n"
1172 "MaxTessControlTotalOutputComponents 4096\n"
1173 "MaxTessEvaluationInputComponents 128\n"
1174 "MaxTessEvaluationOutputComponents 128\n"
1175 "MaxTessEvaluationTextureImageUnits 16\n"
1176 "MaxTessEvaluationUniformComponents 1024\n"
1177 "MaxTessPatchComponents 120\n"
1178 "MaxPatchVertices 32\n"
1179 "MaxTessGenLevel 64\n"
1180 "MaxViewports 16\n"
1181 "MaxVertexAtomicCounters 0\n"
1182 "MaxTessControlAtomicCounters 0\n"
1183 "MaxTessEvaluationAtomicCounters 0\n"
1184 "MaxGeometryAtomicCounters 0\n"
1185 "MaxFragmentAtomicCounters 8\n"
1186 "MaxCombinedAtomicCounters 8\n"
1187 "MaxAtomicCounterBindings 1\n"
1188 "MaxVertexAtomicCounterBuffers 0\n"
1189 "MaxTessControlAtomicCounterBuffers 0\n"
1190 "MaxTessEvaluationAtomicCounterBuffers 0\n"
1191 "MaxGeometryAtomicCounterBuffers 0\n"
1192 "MaxFragmentAtomicCounterBuffers 1\n"
1193 "MaxCombinedAtomicCounterBuffers 1\n"
1194 "MaxAtomicCounterBufferSize 16384\n"
1195 "MaxTransformFeedbackBuffers 4\n"
1196 "MaxTransformFeedbackInterleavedComponents 64\n"
1197 "MaxCullDistances 8\n"
1198 "MaxCombinedClipAndCullDistances 8\n"
1199 "MaxSamples 4\n"
1200
1201 "nonInductiveForLoops 1\n"
1202 "whileLoops 1\n"
1203 "doWhileLoops 1\n"
1204 "generalUniformIndexing 1\n"
1205 "generalAttributeMatrixVectorIndexing 1\n"
1206 "generalVaryingIndexing 1\n"
1207 "generalSamplerIndexing 1\n"
1208 "generalVariableIndexing 1\n"
1209 "generalConstantMatrixVectorIndexing 1\n"
1210 ;
1211
1212//
1213// *.conf => this is a config file that can set limits/resources
1214//
Tony Barbour6918cd52015-04-09 12:58:51 -06001215bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001216{
1217 if (name.size() < 5)
1218 return false;
1219
1220 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
1221 ConfigFile = name;
1222 return true;
1223 }
1224
1225 return false;
1226}
1227
1228//
1229// Parse either a .conf file provided by the user or the default string above.
1230//
Tony Barbour6918cd52015-04-09 12:58:51 -06001231void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001232{
1233 char** configStrings = 0;
1234 char* config = 0;
1235 if (ConfigFile.size() > 0) {
1236 configStrings = ReadFileData(ConfigFile.c_str());
1237 if (configStrings)
1238 config = *configStrings;
1239 else {
1240 printf("Error opening configuration file; will instead use the default configuration\n");
1241 }
1242 }
1243
1244 if (config == 0) {
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001245 config = (char *) alloca(strlen(DefaultConfig) + 1);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001246 strcpy(config, DefaultConfig);
1247 }
1248
1249 const char* delims = " \t\n\r";
1250 const char* token = strtok(config, delims);
1251 while (token) {
1252 const char* valueStr = strtok(0, delims);
1253 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1254 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1255 return;
1256 }
1257 int value = atoi(valueStr);
1258
1259 if (strcmp(token, "MaxLights") == 0)
1260 Resources.maxLights = value;
1261 else if (strcmp(token, "MaxClipPlanes") == 0)
1262 Resources.maxClipPlanes = value;
1263 else if (strcmp(token, "MaxTextureUnits") == 0)
1264 Resources.maxTextureUnits = value;
1265 else if (strcmp(token, "MaxTextureCoords") == 0)
1266 Resources.maxTextureCoords = value;
1267 else if (strcmp(token, "MaxVertexAttribs") == 0)
1268 Resources.maxVertexAttribs = value;
1269 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1270 Resources.maxVertexUniformComponents = value;
1271 else if (strcmp(token, "MaxVaryingFloats") == 0)
1272 Resources.maxVaryingFloats = value;
1273 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1274 Resources.maxVertexTextureImageUnits = value;
1275 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1276 Resources.maxCombinedTextureImageUnits = value;
1277 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1278 Resources.maxTextureImageUnits = value;
1279 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1280 Resources.maxFragmentUniformComponents = value;
1281 else if (strcmp(token, "MaxDrawBuffers") == 0)
1282 Resources.maxDrawBuffers = value;
1283 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1284 Resources.maxVertexUniformVectors = value;
1285 else if (strcmp(token, "MaxVaryingVectors") == 0)
1286 Resources.maxVaryingVectors = value;
1287 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1288 Resources.maxFragmentUniformVectors = value;
1289 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1290 Resources.maxVertexOutputVectors = value;
1291 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1292 Resources.maxFragmentInputVectors = value;
1293 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1294 Resources.minProgramTexelOffset = value;
1295 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1296 Resources.maxProgramTexelOffset = value;
1297 else if (strcmp(token, "MaxClipDistances") == 0)
1298 Resources.maxClipDistances = value;
1299 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1300 Resources.maxComputeWorkGroupCountX = value;
1301 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1302 Resources.maxComputeWorkGroupCountY = value;
1303 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1304 Resources.maxComputeWorkGroupCountZ = value;
1305 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1306 Resources.maxComputeWorkGroupSizeX = value;
1307 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1308 Resources.maxComputeWorkGroupSizeY = value;
1309 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1310 Resources.maxComputeWorkGroupSizeZ = value;
1311 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1312 Resources.maxComputeUniformComponents = value;
1313 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1314 Resources.maxComputeTextureImageUnits = value;
1315 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1316 Resources.maxComputeImageUniforms = value;
1317 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1318 Resources.maxComputeAtomicCounters = value;
1319 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1320 Resources.maxComputeAtomicCounterBuffers = value;
1321 else if (strcmp(token, "MaxVaryingComponents") == 0)
1322 Resources.maxVaryingComponents = value;
1323 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1324 Resources.maxVertexOutputComponents = value;
1325 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1326 Resources.maxGeometryInputComponents = value;
1327 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1328 Resources.maxGeometryOutputComponents = value;
1329 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1330 Resources.maxFragmentInputComponents = value;
1331 else if (strcmp(token, "MaxImageUnits") == 0)
1332 Resources.maxImageUnits = value;
1333 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1334 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1335 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1336 Resources.maxCombinedShaderOutputResources = value;
1337 else if (strcmp(token, "MaxImageSamples") == 0)
1338 Resources.maxImageSamples = value;
1339 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1340 Resources.maxVertexImageUniforms = value;
1341 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1342 Resources.maxTessControlImageUniforms = value;
1343 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1344 Resources.maxTessEvaluationImageUniforms = value;
1345 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1346 Resources.maxGeometryImageUniforms = value;
1347 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1348 Resources.maxFragmentImageUniforms = value;
1349 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1350 Resources.maxCombinedImageUniforms = value;
1351 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1352 Resources.maxGeometryTextureImageUnits = value;
1353 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1354 Resources.maxGeometryOutputVertices = value;
1355 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1356 Resources.maxGeometryTotalOutputComponents = value;
1357 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1358 Resources.maxGeometryUniformComponents = value;
1359 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1360 Resources.maxGeometryVaryingComponents = value;
1361 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1362 Resources.maxTessControlInputComponents = value;
1363 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1364 Resources.maxTessControlOutputComponents = value;
1365 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1366 Resources.maxTessControlTextureImageUnits = value;
1367 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1368 Resources.maxTessControlUniformComponents = value;
1369 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1370 Resources.maxTessControlTotalOutputComponents = value;
1371 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1372 Resources.maxTessEvaluationInputComponents = value;
1373 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1374 Resources.maxTessEvaluationOutputComponents = value;
1375 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1376 Resources.maxTessEvaluationTextureImageUnits = value;
1377 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1378 Resources.maxTessEvaluationUniformComponents = value;
1379 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1380 Resources.maxTessPatchComponents = value;
1381 else if (strcmp(token, "MaxPatchVertices") == 0)
1382 Resources.maxPatchVertices = value;
1383 else if (strcmp(token, "MaxTessGenLevel") == 0)
1384 Resources.maxTessGenLevel = value;
1385 else if (strcmp(token, "MaxViewports") == 0)
1386 Resources.maxViewports = value;
1387 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1388 Resources.maxVertexAtomicCounters = value;
1389 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1390 Resources.maxTessControlAtomicCounters = value;
1391 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1392 Resources.maxTessEvaluationAtomicCounters = value;
1393 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1394 Resources.maxGeometryAtomicCounters = value;
1395 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1396 Resources.maxFragmentAtomicCounters = value;
1397 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1398 Resources.maxCombinedAtomicCounters = value;
1399 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1400 Resources.maxAtomicCounterBindings = value;
1401 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1402 Resources.maxVertexAtomicCounterBuffers = value;
1403 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1404 Resources.maxTessControlAtomicCounterBuffers = value;
1405 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1406 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1407 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1408 Resources.maxGeometryAtomicCounterBuffers = value;
1409 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1410 Resources.maxFragmentAtomicCounterBuffers = value;
1411 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1412 Resources.maxCombinedAtomicCounterBuffers = value;
1413 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1414 Resources.maxAtomicCounterBufferSize = value;
1415 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1416 Resources.maxTransformFeedbackBuffers = value;
1417 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1418 Resources.maxTransformFeedbackInterleavedComponents = value;
1419 else if (strcmp(token, "MaxCullDistances") == 0)
1420 Resources.maxCullDistances = value;
1421 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1422 Resources.maxCombinedClipAndCullDistances = value;
1423 else if (strcmp(token, "MaxSamples") == 0)
1424 Resources.maxSamples = value;
1425
1426 else if (strcmp(token, "nonInductiveForLoops") == 0)
1427 Resources.limits.nonInductiveForLoops = (value != 0);
1428 else if (strcmp(token, "whileLoops") == 0)
1429 Resources.limits.whileLoops = (value != 0);
1430 else if (strcmp(token, "doWhileLoops") == 0)
1431 Resources.limits.doWhileLoops = (value != 0);
1432 else if (strcmp(token, "generalUniformIndexing") == 0)
1433 Resources.limits.generalUniformIndexing = (value != 0);
1434 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1435 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1436 else if (strcmp(token, "generalVaryingIndexing") == 0)
1437 Resources.limits.generalVaryingIndexing = (value != 0);
1438 else if (strcmp(token, "generalSamplerIndexing") == 0)
1439 Resources.limits.generalSamplerIndexing = (value != 0);
1440 else if (strcmp(token, "generalVariableIndexing") == 0)
1441 Resources.limits.generalVariableIndexing = (value != 0);
1442 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1443 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1444 else
1445 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1446
1447 token = strtok(0, delims);
1448 }
1449 if (configStrings)
1450 FreeFileData(configStrings);
1451}
1452
Tony Barbour6918cd52015-04-09 12:58:51 -06001453void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001454{
1455 if (m_compile_options & EOptionRelaxedErrors)
1456 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1457 if (m_compile_options & EOptionIntermediate)
1458 messages = (EShMessages)(messages | EShMsgAST);
1459 if (m_compile_options & EOptionSuppressWarnings)
1460 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1461}
1462
1463//
1464// Malloc a string of sufficient size and read a string into it.
1465//
Tony Barbour6918cd52015-04-09 12:58:51 -06001466char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001467{
1468 FILE *in;
1469 #if defined(_WIN32) && defined(__GNUC__)
1470 in = fopen(fileName, "r");
1471 int errorCode = in ? 0 : 1;
1472 #else
1473 int errorCode = fopen_s(&in, fileName, "r");
1474 #endif
1475
1476 char *fdata;
1477 int count = 0;
1478 const int maxSourceStrings = 5;
1479 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1480
1481 if (errorCode) {
1482 printf("Error: unable to open input file: %s\n", fileName);
1483 return 0;
1484 }
1485
1486 while (fgetc(in) != EOF)
1487 count++;
1488
1489 fseek(in, 0, SEEK_SET);
1490
1491 if (!(fdata = (char*)malloc(count+2))) {
1492 printf("Error allocating memory\n");
1493 return 0;
1494 }
1495 if (fread(fdata,1,count, in)!=count) {
1496 printf("Error reading input file: %s\n", fileName);
1497 return 0;
1498 }
1499 fdata[count] = '\0';
1500 fclose(in);
1501 if (count == 0) {
1502 return_data[0]=(char*)malloc(count+2);
1503 return_data[0][0]='\0';
1504 m_num_shader_strings = 0;
1505 return return_data;
1506 } else
1507 m_num_shader_strings = 1;
1508
1509 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1510 int ptr_len=0,i=0;
1511 while(count>0){
1512 return_data[i]=(char*)malloc(len+2);
1513 memcpy(return_data[i],fdata+ptr_len,len);
1514 return_data[i][len]='\0';
1515 count-=(len);
1516 ptr_len+=(len);
1517 if(count<len){
1518 if(count==0){
1519 m_num_shader_strings=(i+1);
1520 break;
1521 }
1522 len = count;
1523 }
1524 ++i;
1525 }
1526 return return_data;
1527}
1528
Tony Barbour6918cd52015-04-09 12:58:51 -06001529void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001530{
1531 for(int i=0;i<m_num_shader_strings;i++)
1532 free(data[i]);
1533}
1534
1535//
1536// Deduce the language from the filename. Files must end in one of the
1537// following extensions:
1538//
1539// .vert = vertex
1540// .tesc = tessellation control
1541// .tese = tessellation evaluation
1542// .geom = geometry
1543// .frag = fragment
1544// .comp = compute
1545//
Tony Barbour6918cd52015-04-09 12:58:51 -06001546EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001547{
1548 size_t ext = name.rfind('.');
1549 if (ext == std::string::npos) {
1550 return EShLangVertex;
1551 }
1552
1553 std::string suffix = name.substr(ext + 1, std::string::npos);
1554 if (suffix == "vert")
1555 return EShLangVertex;
1556 else if (suffix == "tesc")
1557 return EShLangTessControl;
1558 else if (suffix == "tese")
1559 return EShLangTessEvaluation;
1560 else if (suffix == "geom")
1561 return EShLangGeometry;
1562 else if (suffix == "frag")
1563 return EShLangFragment;
1564 else if (suffix == "comp")
1565 return EShLangCompute;
1566
1567 return EShLangVertex;
1568}
1569
1570//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001571// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001572//
Tony Barbourd1c35722015-04-16 15:59:00 -06001573EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001574{
1575 switch (shader_type) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001576 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001577 return EShLangVertex;
1578
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001579 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001580 return EShLangTessControl;
1581
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001582 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001583 return EShLangTessEvaluation;
1584
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001585 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001586 return EShLangGeometry;
1587
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001588 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001589 return EShLangFragment;
1590
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001591 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001592 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001593
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001594 default:
1595 return EShLangVertex;
1596 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001597}
1598
1599
1600//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001601// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001602// Return value of false means an error was encountered.
1603//
Tony Barbourd1c35722015-04-16 15:59:00 -06001604bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001605 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001606 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001607{
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001608 glslang::TProgram program;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001609 const char *shaderStrings[1];
1610
1611 // TODO: Do we want to load a special config file depending on the
1612 // shader source? Optional name maybe?
1613 // SetConfigFile(fileName);
1614
1615 ProcessConfigFile();
1616
1617 EShMessages messages = EShMsgDefault;
1618 SetMessageOptions(messages);
1619
1620 EShLanguage stage = FindLanguage(shader_type);
1621 glslang::TShader* shader = new glslang::TShader(stage);
1622
1623 shaderStrings[0] = pshader;
1624 shader->setStrings(shaderStrings, 1);
1625
1626 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1627
Cody Northrop195d6622014-11-03 12:54:37 -07001628 if (! (m_compile_options & EOptionSuppressInfolog)) {
1629 puts(shader->getInfoLog());
1630 puts(shader->getInfoDebugLog());
1631 }
1632
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001633 return false; // something didn't work
1634 }
1635
1636 program.addShader(shader);
1637
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001638
1639 //
1640 // Program-level processing...
1641 //
1642
Cody Northrop195d6622014-11-03 12:54:37 -07001643 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001644
Cody Northrop195d6622014-11-03 12:54:37 -07001645 if (! (m_compile_options & EOptionSuppressInfolog)) {
1646 puts(shader->getInfoLog());
1647 puts(shader->getInfoDebugLog());
1648 }
1649
1650 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001651 }
1652
1653 if (m_compile_options & EOptionDumpReflection) {
1654 program.buildReflection();
1655 program.dumpReflection();
1656 }
1657
Cody Northrop5a95b472015-06-03 13:01:54 -06001658 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1659
1660 //
1661 // Test the different modes of SPIR-V modification
1662 //
1663 if (this->m_canonicalize_spv) {
1664 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1665 }
1666
1667 if (this->m_strip_spv) {
1668 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1669 }
1670
1671 if (this->m_do_everything_spv) {
1672 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1673 }
1674
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001675 delete shader;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001676
1677 return true;
1678}
1679
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001680
1681
Tony Barbour6918cd52015-04-09 12:58:51 -06001682VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001683 m_width( 0 ),
1684 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001685 m_data( NULL ),
1686 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001687{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001688}
1689
Tony Barbour6918cd52015-04-09 12:58:51 -06001690VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001691{
1692
1693}
1694
Tony Barbour6918cd52015-04-09 12:58:51 -06001695VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001696{
1697 m_title = copyin.m_title;
1698 m_width = copyin.m_width;
1699 m_height = copyin.m_height;
1700 m_data_size = copyin.m_data_size;
1701 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1702}
1703
Tony Barbour6918cd52015-04-09 12:58:51 -06001704ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001705{
Tony Barbour6918cd52015-04-09 12:58:51 -06001706 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1707 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001708 return output;
1709}
1710
Tony Barbour6918cd52015-04-09 12:58:51 -06001711VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001712{
1713 m_title = rhs.m_title;
1714 m_width = rhs.m_width;
1715 m_height = rhs.m_height;
1716 m_data_size = rhs.m_data_size;
1717 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001718 return *this;
1719}
1720
Tony Barbour6918cd52015-04-09 12:58:51 -06001721int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001722{
1723 if( this->m_data != rhs.m_data) return 0;
1724 return 1;
1725}
1726
1727// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001728int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001729{
1730 if( this->m_data_size < rhs.m_data_size ) return 1;
1731 return 0;
1732}
1733