blob: 2be27ea9d35a29672d93bcb2c2c954f4a44fcbfe [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-LunarG399dfca2015-05-19 14:08:26 -0600543
544 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Cody Northrop7fb43862015-06-22 14:56:14 -0600545 buf.init_as_src(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800546 dest_ptr = buf.memory().map();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600547 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800548 buf.memory().unmap();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600549
550 m_cmdbuf.begin();
551
552 VkBufferImageCopy region = {};
553 region.imageExtent.height = m_display_image->m_height;
554 region.imageExtent.width = m_display_image->m_width;
555 region.imageExtent.depth = 1;
556
Chia-I Wube2b9172015-07-03 11:49:42 +0800557 vkCmdCopyBufferToImage(m_cmdbuf.handle(),
Chia-I Wu681d7a02015-07-03 13:44:34 +0800558 buf.handle(),
Tony Barbour6a3faf02015-07-23 10:36:18 -0600559 m_buffers[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600560 1, &region);
561 m_cmdbuf.end();
562
563 VkCmdBuffer cmdBufs[1];
Chia-I Wube2b9172015-07-03 11:49:42 +0800564 cmdBufs[0] = m_cmdbuf.handle();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600565
Tony Barbour67e99152015-07-10 14:10:27 -0600566 VkFence nullFence = { VK_NULL_HANDLE };
567 vkQueueSubmit(m_queue.handle(), 1, cmdBufs, nullFence);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600568 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700569
Ian Elliott7e40db92015-08-21 15:09:33 -0600570 VkPresentInfoKHR present = {};
571 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600572 present.pNext = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600573 present.swapchainCount = 1;
574 present.swapchains = & m_swap_chain;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600575 present.imageIndices = &m_current_buffer;
Tony Barbour96db8822015-02-25 12:28:39 -0700576
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600577#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800578 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700579 XCB_PROP_MODE_REPLACE,
580 m_window,
581 XCB_ATOM_WM_NAME,
582 XCB_ATOM_STRING,
583 8,
584 m_display_image->m_title.size(),
585 m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600586#endif
Jon Ashburn07daee72015-05-21 18:13:33 -0600587
Ian Elliott7e40db92015-08-21 15:09:33 -0600588 err = m_fpQueuePresentKHR(m_queue.handle(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700589 assert(!err);
590
591 m_queue.wait();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600592 m_current_buffer = (m_current_buffer + 1) % 2;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600593}
594
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600595#ifdef _WIN32
Tony-LunarG399dfca2015-05-19 14:08:26 -0600596# define PREVIOUSLY_DOWN 1<<29
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600597// MS-Windows event handling function:
598LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
599 UINT uMsg,
600 WPARAM wParam,
601 LPARAM lParam)
602{
603
604 switch(uMsg)
605 {
606 case WM_CLOSE:
607 PostQuitMessage(0);
608 break;
609
610 case WM_PAINT:
611 {
612 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
613 if (me) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600614 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600615 me->Display();
616 }
617 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600618 break;
619
620 case WM_KEYDOWN:
621 {
622 if (lParam & (PREVIOUSLY_DOWN)){
623 break;
624 }
625 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
626 // the window, we put the this pointer into the window's user data so we could get it back now
627 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
628 switch (wParam)
629 {
630 case VK_ESCAPE: me->m_quit = true;
631 break;
632
633 case VK_LEFT: // left arrow key
634 if (me->m_display_image == me->m_images.begin()) {
635 me->m_display_image = --me->m_images.end();
636 }
637 else {
638 --me->m_display_image;
639 }
640 break;
641
642 case VK_RIGHT: // right arrow key
643 ++me->m_display_image;
644 if (me->m_display_image == me->m_images.end()) {
645 me->m_display_image = me->m_images.begin();
646 }
647 break;
648
649 default:
650 break;
651 }
652 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
653 me->Display();
654 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600655 }
656 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
657}
658
659void TestFrameworkVkPresent::Run()
660{
661 MSG msg; // message
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600662
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600663 /* main message loop*/
Tony-LunarG399dfca2015-05-19 14:08:26 -0600664 while(! m_quit) {
665 GetMessage(&msg, m_window, 0, 0);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600666 if (msg.message == WM_QUIT) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600667 m_quit = true; //if found, quit app
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600668 } else {
669 /* Translate and dispatch to event queue*/
670 TranslateMessage(&msg);
671 DispatchMessage(&msg);
672 }
673 }
674}
675
676#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600677void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600678{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600679 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700680 switch (event_code) {
681 case XCB_EXPOSE:
682 Display(); // TODO: handle resize
683 break;
684 case XCB_CLIENT_MESSAGE:
685 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
686 (m_atom_wm_delete_window)->atom) {
687 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600688 }
689 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700690 case XCB_KEY_RELEASE:
691 {
692 const xcb_key_release_event_t *key =
693 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600694
Tony Barbour96db8822015-02-25 12:28:39 -0700695 switch (key->detail) {
696 case 0x9: // Escape
697 m_quit = true;
698 break;
699 case 0x71: // left arrow key
700 if (m_display_image == m_images.begin()) {
701 m_display_image = --m_images.end();
702 } else {
703 --m_display_image;
704 }
705 break;
706 case 0x72: // right arrow key
707 ++m_display_image;
708 if (m_display_image == m_images.end()) {
709 m_display_image = m_images.begin();
710 }
711 break;
712 case 0x41:
713 m_pause = !m_pause;
714 break;
715 }
716 Display();
717 }
718 break;
719 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600720 break;
721 }
Tony Barbour96db8822015-02-25 12:28:39 -0700722}
723
Tony Barbour6918cd52015-04-09 12:58:51 -0600724void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700725{
Chia-I Wuf8693382015-04-16 22:02:10 +0800726 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700727
728 while (! m_quit) {
729 xcb_generic_event_t *event;
730
731 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800732 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700733 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800734 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700735 }
736 if (event) {
737 HandleEvent(event);
738 free(event);
739 }
740 }
741}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600742#endif // _WIN32
Tony Barbour96db8822015-02-25 12:28:39 -0700743
Ian Elliott7e40db92015-08-21 15:09:33 -0600744void TestFrameworkVkPresent::CreateSwapchain()
Tony Barbour96db8822015-02-25 12:28:39 -0700745{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600746 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700747
Tony-LunarG399dfca2015-05-19 14:08:26 -0600748 m_display_image = m_images.begin();
749 m_current_buffer = 0;
750
Tony Barbour6a3faf02015-07-23 10:36:18 -0600751 // Construct the WSI surface description:
Ian Elliott7e40db92015-08-21 15:09:33 -0600752 m_surface_description.sType = VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600753 m_surface_description.pNext = NULL;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600754#ifdef _WIN32
Ian Elliott7e40db92015-08-21 15:09:33 -0600755 m_surface_description.platform = VK_PLATFORM_WIN32_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600756 m_surface_description.pPlatformHandle = m_connection;
757 m_surface_description.pPlatformWindow = m_window;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600758#else // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -0600759 m_platform_handle_xcb.connection = m_connection;
760 m_platform_handle_xcb.root = m_screen->root;
Ian Elliott7e40db92015-08-21 15:09:33 -0600761 m_surface_description.platform = VK_PLATFORM_XCB_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600762 m_surface_description.pPlatformHandle = &m_platform_handle_xcb;
763 m_surface_description.pPlatformWindow = &m_window;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600764#endif // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -0600765
766 // Iterate over each queue to learn whether it supports presenting to WSI:
767 VkBool32 supportsPresent;
768 m_present_queue_node_index = UINT32_MAX;
769 std::vector<vk_testing::Queue *> queues = m_device.graphics_queues();
770 for (int i=0; i < queues.size(); i++)
771 {
772 int family_index = queues[i]->get_family_index();
Ian Elliott7e40db92015-08-21 15:09:33 -0600773 m_fpGetPhysicalDeviceSurfaceSupportKHR(m_device.phy().handle(),
Tony Barbour6a3faf02015-07-23 10:36:18 -0600774 family_index,
Ian Elliott7e40db92015-08-21 15:09:33 -0600775 (VkSurfaceDescriptionKHR *) &m_surface_description,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600776 &supportsPresent);
777 if (supportsPresent) {
778 m_present_queue_node_index = family_index;
779 }
780 }
781
782 assert(m_present_queue_node_index != UINT32_MAX);
783
784
785 // Get the list of VkFormat's that are supported:
Ian Elliott8b139792015-08-07 11:51:12 -0600786 uint32_t formatCount;
Ian Elliott7e40db92015-08-21 15:09:33 -0600787 err = m_fpGetSurfaceFormatsKHR(m_device.handle(),
788 (VkSurfaceDescriptionKHR *) &m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600789 &formatCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600790 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600791 VkSurfaceFormatKHR *surfFormats =
792 (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
793 err = m_fpGetSurfaceFormatsKHR(m_device.handle(),
794 (VkSurfaceDescriptionKHR *) &m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600795 &formatCount, surfFormats);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600796 assert(!err);
797 // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
798 // the surface has no preferred format. Otherwise, at least one
799 // supported format will be returned.
Tony Barbour6a3faf02015-07-23 10:36:18 -0600800 if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED)
801 {
802 m_format = VK_FORMAT_B8G8R8A8_UNORM;
803 }
804 else
805 {
806 assert(formatCount >= 1);
807 m_format = surfFormats[0].format;
808 }
Ian Elliott8b139792015-08-07 11:51:12 -0600809 m_color_space = surfFormats[0].colorSpace;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600810
811 // Check the surface proprties and formats
Ian Elliott7e40db92015-08-21 15:09:33 -0600812 VkSurfacePropertiesKHR surfProperties;
813 err = m_fpGetSurfacePropertiesKHR(m_device.handle(),
814 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600815 &surfProperties);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600816 assert(!err);
817
Ian Elliott8b139792015-08-07 11:51:12 -0600818 uint32_t presentModeCount;
Ian Elliott7e40db92015-08-21 15:09:33 -0600819 err = m_fpGetSurfacePresentModesKHR(m_device.handle(),
820 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600821 &presentModeCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600822 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600823 VkPresentModeKHR *presentModes =
824 (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
Ian Elliott8b139792015-08-07 11:51:12 -0600825 assert(presentModes);
Ian Elliott7e40db92015-08-21 15:09:33 -0600826 err = m_fpGetSurfacePresentModesKHR(m_device.handle(),
827 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600828 &presentModeCount, presentModes);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600829 assert(!err);
830
Ian Elliott7e40db92015-08-21 15:09:33 -0600831 VkExtent2D swapchainExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600832 // width and height are either both -1, or both not -1.
Ian Elliott8b139792015-08-07 11:51:12 -0600833 if (surfProperties.currentExtent.width == -1)
Tony Barbour6a3faf02015-07-23 10:36:18 -0600834 {
835 // If the surface size is undefined, the size is set to
836 // the size of the images requested.
Ian Elliott7e40db92015-08-21 15:09:33 -0600837 swapchainExtent.width = m_width;
838 swapchainExtent.height = m_height;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600839 }
840 else
841 {
842 // If the surface size is defined, the swap chain size must match
Ian Elliott7e40db92015-08-21 15:09:33 -0600843 swapchainExtent = surfProperties.currentExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600844 }
845
846 // If mailbox mode is available, use it, as is the lowest-latency non-
Ian Elliottae0e8242015-08-10 13:20:49 -0600847 // tearing mode. If not, try IMMEDIATE which will usually be available,
848 // and is fastest (though it tears). If not, fall back to FIFO which is
849 // always available.
Ian Elliott7e40db92015-08-21 15:09:33 -0600850 VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600851 for (size_t i = 0; i < presentModeCount; i++) {
Ian Elliott7e40db92015-08-21 15:09:33 -0600852 if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
853 swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600854 break;
855 }
Ian Elliott7e40db92015-08-21 15:09:33 -0600856 if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) &&
857 (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
858 swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
Ian Elliottae0e8242015-08-10 13:20:49 -0600859 }
Tony Barbour6a3faf02015-07-23 10:36:18 -0600860 }
861
862 // Determine the number of VkImage's to use in the swap chain (we desire to
863 // own only 1 image at a time, besides the images being displayed and
864 // queued for display):
Ian Elliott7e40db92015-08-21 15:09:33 -0600865 uint32_t desiredNumberOfSwapchainImages = surfProperties.minImageCount + 1;
Ian Elliott8b139792015-08-07 11:51:12 -0600866 if ((surfProperties.maxImageCount > 0) &&
Ian Elliott7e40db92015-08-21 15:09:33 -0600867 (desiredNumberOfSwapchainImages > surfProperties.maxImageCount))
Tony Barbour6a3faf02015-07-23 10:36:18 -0600868 {
869 // Application must settle for fewer images than desired:
Ian Elliott7e40db92015-08-21 15:09:33 -0600870 desiredNumberOfSwapchainImages = surfProperties.maxImageCount;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600871 }
872
Ian Elliott7e40db92015-08-21 15:09:33 -0600873 VkSurfaceTransformKHR preTransform;
874 if (surfProperties.supportedTransforms & VK_SURFACE_TRANSFORM_NONE_BIT_KHR) {
875 preTransform = VK_SURFACE_TRANSFORM_NONE_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600876 } else {
Ian Elliott8b139792015-08-07 11:51:12 -0600877 preTransform = surfProperties.currentTransform;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600878 }
Ian Elliott1a3845b2015-07-06 14:33:04 -0600879
Cody Northropdf5b0922015-08-28 16:22:48 -0600880 // We want to blit to the swap chain, ensure the driver supports it. Color is always supported, per WSI spec.
881 assert((surfProperties.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT) != 0);
882
Ian Elliott7e40db92015-08-21 15:09:33 -0600883 VkSwapchainCreateInfoKHR swap_chain = {};
Ian Elliotta257eea2015-09-22 10:20:23 -0600884 swap_chain.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600885 swap_chain.pNext = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600886 swap_chain.pSurfaceDescription = (const VkSurfaceDescriptionKHR *)&m_surface_description;
887 swap_chain.minImageCount = desiredNumberOfSwapchainImages;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600888 swap_chain.imageFormat = m_format;
Ian Elliott8b139792015-08-07 11:51:12 -0600889 swap_chain.imageColorSpace = m_color_space;
Ian Elliott7e40db92015-08-21 15:09:33 -0600890 swap_chain.imageExtent.width = swapchainExtent.width;
891 swap_chain.imageExtent.height = swapchainExtent.height;
Cody Northropdf8f42a2015-08-05 15:38:39 -0600892 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT |
893 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600894 swap_chain.preTransform = preTransform;
Chia-I Wuf8693382015-04-16 22:02:10 +0800895 swap_chain.imageArraySize = 1;
Ian Elliott8b139792015-08-07 11:51:12 -0600896 swap_chain.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
897 swap_chain.queueFamilyCount = 0;
898 swap_chain.pQueueFamilyIndices = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600899 swap_chain.presentMode = swapchainPresentMode;
900 swap_chain.oldSwapchain.handle = 0;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600901 swap_chain.clipped = true;
902
903 uint32_t i;
Chia-I Wuf8693382015-04-16 22:02:10 +0800904
Ian Elliott7e40db92015-08-21 15:09:33 -0600905 err = m_fpCreateSwapchainKHR(m_device.handle(), &swap_chain, &m_swap_chain);
Chia-I Wuf8693382015-04-16 22:02:10 +0800906 assert(!err);
907
Ian Elliott7e40db92015-08-21 15:09:33 -0600908 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
909 &m_swapchainImageCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600910 assert(!err);
911
Ian Elliott7e40db92015-08-21 15:09:33 -0600912 VkImage* swapchainImages = (VkImage*)malloc(m_swapchainImageCount * sizeof(VkImage));
913 assert(swapchainImages);
914 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
915 &m_swapchainImageCount, swapchainImages);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600916 assert(!err);
917
Ian Elliott7e40db92015-08-21 15:09:33 -0600918 m_buffers = (SwapchainBuffers*)malloc(sizeof(SwapchainBuffers)*m_swapchainImageCount);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600919 assert(m_buffers);
920
Ian Elliott7e40db92015-08-21 15:09:33 -0600921 for (i = 0; i < m_swapchainImageCount; i++) {
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600922 VkImageViewCreateInfo color_image_view = {};
923 color_image_view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
924 color_image_view.pNext = NULL;
Courtney Goeltzenleuchter00265c82015-09-11 15:22:06 -0600925 color_image_view.viewType = VK_IMAGE_VIEW_TYPE_2D;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600926 color_image_view.format = m_format;
Courtney Goeltzenleuchterba724512015-09-10 17:58:54 -0600927 color_image_view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600928 color_image_view.subresourceRange.baseMipLevel = 0;
929 color_image_view.subresourceRange.mipLevels = 1;
Courtney Goeltzenleuchter4a261892015-09-10 16:38:41 -0600930 color_image_view.subresourceRange.baseArrayLayer = 0;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600931 color_image_view.subresourceRange.arraySize = 1;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600932
Ian Elliott7e40db92015-08-21 15:09:33 -0600933 m_buffers[i].image = swapchainImages[i];
Tony Barbour6a3faf02015-07-23 10:36:18 -0600934
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600935 color_image_view.image = m_buffers[i].image;
936 err = vkCreateImageView(m_device.handle(),
937 &color_image_view, &m_buffers[i].view);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600938 assert(!err);
939 }
Tony Barbour96db8822015-02-25 12:28:39 -0700940}
941
Jon Ashburn07daee72015-05-21 18:13:33 -0600942void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -0700943{
Ian Elliott7e40db92015-08-21 15:09:33 -0600944 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceSupportKHR);
945 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfacePropertiesKHR);
946 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfaceFormatsKHR);
947 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfacePresentModesKHR);
948 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
949 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
950 GET_DEVICE_PROC_ADDR(m_device.handle(), DestroySwapchainKHR);
951 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSwapchainImagesKHR);
952 GET_DEVICE_PROC_ADDR(m_device.handle(), AcquireNextImageKHR);
953 GET_DEVICE_PROC_ADDR(m_device.handle(), QueuePresentKHR);
Jon Ashburn07daee72015-05-21 18:13:33 -0600954
Tony Barbour96db8822015-02-25 12:28:39 -0700955 m_images = imagesIn;
956}
957
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600958#ifdef _WIN32
959void TestFrameworkVkPresent::CreateMyWindow()
960{
961 WNDCLASSEX win_class;
962 // const ::testing::TestInfo* const test_info =
963 // ::testing::UnitTest::GetInstance()->current_test_info();
964 m_connection = GetModuleHandle(NULL);
965
966 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
967 it != m_images.end(); it++) {
968 if (m_width < it->m_width)
969 m_width = it->m_width;
970 if (m_height < it->m_height)
971 m_height = it->m_height;
972 }
973 // Initialize the window class structure:
974 win_class.cbSize = sizeof(WNDCLASSEX);
975 win_class.style = CS_HREDRAW | CS_VREDRAW;
976 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
977 win_class.cbClsExtra = 0;
978 win_class.cbWndExtra = 0;
979 win_class.hInstance = m_connection; // hInstance
980 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
981 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
982 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
983 win_class.lpszMenuName = NULL;
984 win_class.lpszClassName = "Test";
985 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
986 // Register window class:
987 if (!RegisterClassEx(&win_class)) {
988 // It didn't work, so try to give a useful error:
989 printf("Unexpected error trying to start the application!\n");
990 fflush(stdout);
991 exit(1);
992 }
993 // Create window with the registered class:
Cody Northrop39582252015-08-05 15:39:31 -0600994 RECT wr = { 0, 0, m_width, m_height };
995 AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600996 m_window = CreateWindowEx(0,
997 "Test", // class name
998 "Test", // app name
999 WS_OVERLAPPEDWINDOW | // window style
1000 WS_VISIBLE |
1001 WS_SYSMENU,
1002 100,100, // x/y coords
Cody Northrop39582252015-08-05 15:39:31 -06001003 wr.right - wr.left, // width
1004 wr.bottom - wr.top, // height
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001005 NULL, // handle to parent
1006 NULL, // handle to menu
1007 m_connection, // hInstance
1008 NULL); // no extra parameters
1009
1010 if (!m_window) {
1011 // It didn't work, so try to give a useful error:
1012 DWORD error = GetLastError();
1013 char message[120];
1014 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
1015 MessageBox(NULL, message, "Error", MB_OK);
1016 exit(1);
1017 }
Tony-LunarG399dfca2015-05-19 14:08:26 -06001018 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
1019 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001020}
1021#else
Tony Barbour6918cd52015-04-09 12:58:51 -06001022void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -07001023{
Chia-I Wuf8693382015-04-16 22:02:10 +08001024 const xcb_setup_t *setup;
1025 xcb_screen_iterator_t iter;
1026 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -07001027 uint32_t value_mask, value_list[32];
1028
Chia-I Wuf8693382015-04-16 22:02:10 +08001029 m_connection = xcb_connect(NULL, &scr);
1030
1031 setup = xcb_get_setup(m_connection);
1032 iter = xcb_setup_roots_iterator(setup);
1033 while (scr-- > 0)
1034 xcb_screen_next(&iter);
1035
1036 m_screen = iter.data;
1037
1038 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1039 it != m_images.end(); it++) {
1040 if (m_width < it->m_width)
1041 m_width = it->m_width;
1042 if (m_height < it->m_height)
1043 m_height = it->m_height;
1044 }
1045
1046 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -07001047
1048 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +08001049 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -07001050 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
1051 XCB_EVENT_MASK_EXPOSURE |
1052 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
1053
Chia-I Wuf8693382015-04-16 22:02:10 +08001054 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -07001055 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001056 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -07001057 0, 0, m_width, m_height, 0,
1058 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001059 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -07001060 value_mask, value_list);
1061
1062 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +08001063 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -07001064 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +08001065 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001066
Chia-I Wuf8693382015-04-16 22:02:10 +08001067 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
1068 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001069
Chia-I Wuf8693382015-04-16 22:02:10 +08001070 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -07001071 m_window, (*reply).atom, 4, 32, 1,
1072 &(*m_atom_wm_delete_window).atom);
1073 free(reply);
1074
Chia-I Wuf8693382015-04-16 22:02:10 +08001075 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -07001076}
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001077#endif
Tony Barbour96db8822015-02-25 12:28:39 -07001078
Tony Barbour6918cd52015-04-09 12:58:51 -06001079void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -07001080{
Ian Elliott7e40db92015-08-21 15:09:33 -06001081 m_fpDestroySwapchainKHR(m_device.handle(), m_swap_chain);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001082#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +08001083 xcb_destroy_window(m_connection, m_window);
1084 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001085#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001086}
1087
Tony Barbour6918cd52015-04-09 12:58:51 -06001088void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001089{
1090 if (m_images.size() == 0) return;
1091
Chia-I Wuf8693382015-04-16 22:02:10 +08001092 vk_testing::Environment env;
1093 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -07001094 {
Chia-I Wuf8693382015-04-16 22:02:10 +08001095 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -07001096
Jon Ashburn07daee72015-05-21 18:13:33 -06001097 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001098 vkPresent.CreateMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -06001099 vkPresent.CreateSwapchain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001100 vkPresent.Run();
1101 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -07001102 }
Chia-I Wuf8693382015-04-16 22:02:10 +08001103 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001104}
1105
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001106//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001107// These are the default resources for TBuiltInResources, used for both
1108// - parsing this string for the case where the user didn't supply one
1109// - dumping out a template for user construction of a config file
1110//
1111static const char* DefaultConfig =
1112 "MaxLights 32\n"
1113 "MaxClipPlanes 6\n"
1114 "MaxTextureUnits 32\n"
1115 "MaxTextureCoords 32\n"
1116 "MaxVertexAttribs 64\n"
1117 "MaxVertexUniformComponents 4096\n"
1118 "MaxVaryingFloats 64\n"
1119 "MaxVertexTextureImageUnits 32\n"
1120 "MaxCombinedTextureImageUnits 80\n"
1121 "MaxTextureImageUnits 32\n"
1122 "MaxFragmentUniformComponents 4096\n"
1123 "MaxDrawBuffers 32\n"
1124 "MaxVertexUniformVectors 128\n"
1125 "MaxVaryingVectors 8\n"
1126 "MaxFragmentUniformVectors 16\n"
1127 "MaxVertexOutputVectors 16\n"
1128 "MaxFragmentInputVectors 15\n"
1129 "MinProgramTexelOffset -8\n"
1130 "MaxProgramTexelOffset 7\n"
1131 "MaxClipDistances 8\n"
1132 "MaxComputeWorkGroupCountX 65535\n"
1133 "MaxComputeWorkGroupCountY 65535\n"
1134 "MaxComputeWorkGroupCountZ 65535\n"
1135 "MaxComputeWorkGroupSizeX 1024\n"
1136 "MaxComputeWorkGroupSizeY 1024\n"
1137 "MaxComputeWorkGroupSizeZ 64\n"
1138 "MaxComputeUniformComponents 1024\n"
1139 "MaxComputeTextureImageUnits 16\n"
1140 "MaxComputeImageUniforms 8\n"
1141 "MaxComputeAtomicCounters 8\n"
1142 "MaxComputeAtomicCounterBuffers 1\n"
1143 "MaxVaryingComponents 60\n"
1144 "MaxVertexOutputComponents 64\n"
1145 "MaxGeometryInputComponents 64\n"
1146 "MaxGeometryOutputComponents 128\n"
1147 "MaxFragmentInputComponents 128\n"
1148 "MaxImageUnits 8\n"
1149 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
1150 "MaxCombinedShaderOutputResources 8\n"
1151 "MaxImageSamples 0\n"
1152 "MaxVertexImageUniforms 0\n"
1153 "MaxTessControlImageUniforms 0\n"
1154 "MaxTessEvaluationImageUniforms 0\n"
1155 "MaxGeometryImageUniforms 0\n"
1156 "MaxFragmentImageUniforms 8\n"
1157 "MaxCombinedImageUniforms 8\n"
1158 "MaxGeometryTextureImageUnits 16\n"
1159 "MaxGeometryOutputVertices 256\n"
1160 "MaxGeometryTotalOutputComponents 1024\n"
1161 "MaxGeometryUniformComponents 1024\n"
1162 "MaxGeometryVaryingComponents 64\n"
1163 "MaxTessControlInputComponents 128\n"
1164 "MaxTessControlOutputComponents 128\n"
1165 "MaxTessControlTextureImageUnits 16\n"
1166 "MaxTessControlUniformComponents 1024\n"
1167 "MaxTessControlTotalOutputComponents 4096\n"
1168 "MaxTessEvaluationInputComponents 128\n"
1169 "MaxTessEvaluationOutputComponents 128\n"
1170 "MaxTessEvaluationTextureImageUnits 16\n"
1171 "MaxTessEvaluationUniformComponents 1024\n"
1172 "MaxTessPatchComponents 120\n"
1173 "MaxPatchVertices 32\n"
1174 "MaxTessGenLevel 64\n"
1175 "MaxViewports 16\n"
1176 "MaxVertexAtomicCounters 0\n"
1177 "MaxTessControlAtomicCounters 0\n"
1178 "MaxTessEvaluationAtomicCounters 0\n"
1179 "MaxGeometryAtomicCounters 0\n"
1180 "MaxFragmentAtomicCounters 8\n"
1181 "MaxCombinedAtomicCounters 8\n"
1182 "MaxAtomicCounterBindings 1\n"
1183 "MaxVertexAtomicCounterBuffers 0\n"
1184 "MaxTessControlAtomicCounterBuffers 0\n"
1185 "MaxTessEvaluationAtomicCounterBuffers 0\n"
1186 "MaxGeometryAtomicCounterBuffers 0\n"
1187 "MaxFragmentAtomicCounterBuffers 1\n"
1188 "MaxCombinedAtomicCounterBuffers 1\n"
1189 "MaxAtomicCounterBufferSize 16384\n"
1190 "MaxTransformFeedbackBuffers 4\n"
1191 "MaxTransformFeedbackInterleavedComponents 64\n"
1192 "MaxCullDistances 8\n"
1193 "MaxCombinedClipAndCullDistances 8\n"
1194 "MaxSamples 4\n"
1195
1196 "nonInductiveForLoops 1\n"
1197 "whileLoops 1\n"
1198 "doWhileLoops 1\n"
1199 "generalUniformIndexing 1\n"
1200 "generalAttributeMatrixVectorIndexing 1\n"
1201 "generalVaryingIndexing 1\n"
1202 "generalSamplerIndexing 1\n"
1203 "generalVariableIndexing 1\n"
1204 "generalConstantMatrixVectorIndexing 1\n"
1205 ;
1206
1207//
1208// *.conf => this is a config file that can set limits/resources
1209//
Tony Barbour6918cd52015-04-09 12:58:51 -06001210bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001211{
1212 if (name.size() < 5)
1213 return false;
1214
1215 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
1216 ConfigFile = name;
1217 return true;
1218 }
1219
1220 return false;
1221}
1222
1223//
1224// Parse either a .conf file provided by the user or the default string above.
1225//
Tony Barbour6918cd52015-04-09 12:58:51 -06001226void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001227{
1228 char** configStrings = 0;
1229 char* config = 0;
1230 if (ConfigFile.size() > 0) {
1231 configStrings = ReadFileData(ConfigFile.c_str());
1232 if (configStrings)
1233 config = *configStrings;
1234 else {
1235 printf("Error opening configuration file; will instead use the default configuration\n");
1236 }
1237 }
1238
1239 if (config == 0) {
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001240 config = (char *) alloca(strlen(DefaultConfig) + 1);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001241 strcpy(config, DefaultConfig);
1242 }
1243
1244 const char* delims = " \t\n\r";
1245 const char* token = strtok(config, delims);
1246 while (token) {
1247 const char* valueStr = strtok(0, delims);
1248 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1249 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1250 return;
1251 }
1252 int value = atoi(valueStr);
1253
1254 if (strcmp(token, "MaxLights") == 0)
1255 Resources.maxLights = value;
1256 else if (strcmp(token, "MaxClipPlanes") == 0)
1257 Resources.maxClipPlanes = value;
1258 else if (strcmp(token, "MaxTextureUnits") == 0)
1259 Resources.maxTextureUnits = value;
1260 else if (strcmp(token, "MaxTextureCoords") == 0)
1261 Resources.maxTextureCoords = value;
1262 else if (strcmp(token, "MaxVertexAttribs") == 0)
1263 Resources.maxVertexAttribs = value;
1264 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1265 Resources.maxVertexUniformComponents = value;
1266 else if (strcmp(token, "MaxVaryingFloats") == 0)
1267 Resources.maxVaryingFloats = value;
1268 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1269 Resources.maxVertexTextureImageUnits = value;
1270 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1271 Resources.maxCombinedTextureImageUnits = value;
1272 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1273 Resources.maxTextureImageUnits = value;
1274 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1275 Resources.maxFragmentUniformComponents = value;
1276 else if (strcmp(token, "MaxDrawBuffers") == 0)
1277 Resources.maxDrawBuffers = value;
1278 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1279 Resources.maxVertexUniformVectors = value;
1280 else if (strcmp(token, "MaxVaryingVectors") == 0)
1281 Resources.maxVaryingVectors = value;
1282 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1283 Resources.maxFragmentUniformVectors = value;
1284 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1285 Resources.maxVertexOutputVectors = value;
1286 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1287 Resources.maxFragmentInputVectors = value;
1288 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1289 Resources.minProgramTexelOffset = value;
1290 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1291 Resources.maxProgramTexelOffset = value;
1292 else if (strcmp(token, "MaxClipDistances") == 0)
1293 Resources.maxClipDistances = value;
1294 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1295 Resources.maxComputeWorkGroupCountX = value;
1296 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1297 Resources.maxComputeWorkGroupCountY = value;
1298 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1299 Resources.maxComputeWorkGroupCountZ = value;
1300 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1301 Resources.maxComputeWorkGroupSizeX = value;
1302 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1303 Resources.maxComputeWorkGroupSizeY = value;
1304 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1305 Resources.maxComputeWorkGroupSizeZ = value;
1306 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1307 Resources.maxComputeUniformComponents = value;
1308 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1309 Resources.maxComputeTextureImageUnits = value;
1310 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1311 Resources.maxComputeImageUniforms = value;
1312 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1313 Resources.maxComputeAtomicCounters = value;
1314 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1315 Resources.maxComputeAtomicCounterBuffers = value;
1316 else if (strcmp(token, "MaxVaryingComponents") == 0)
1317 Resources.maxVaryingComponents = value;
1318 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1319 Resources.maxVertexOutputComponents = value;
1320 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1321 Resources.maxGeometryInputComponents = value;
1322 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1323 Resources.maxGeometryOutputComponents = value;
1324 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1325 Resources.maxFragmentInputComponents = value;
1326 else if (strcmp(token, "MaxImageUnits") == 0)
1327 Resources.maxImageUnits = value;
1328 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1329 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1330 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1331 Resources.maxCombinedShaderOutputResources = value;
1332 else if (strcmp(token, "MaxImageSamples") == 0)
1333 Resources.maxImageSamples = value;
1334 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1335 Resources.maxVertexImageUniforms = value;
1336 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1337 Resources.maxTessControlImageUniforms = value;
1338 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1339 Resources.maxTessEvaluationImageUniforms = value;
1340 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1341 Resources.maxGeometryImageUniforms = value;
1342 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1343 Resources.maxFragmentImageUniforms = value;
1344 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1345 Resources.maxCombinedImageUniforms = value;
1346 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1347 Resources.maxGeometryTextureImageUnits = value;
1348 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1349 Resources.maxGeometryOutputVertices = value;
1350 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1351 Resources.maxGeometryTotalOutputComponents = value;
1352 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1353 Resources.maxGeometryUniformComponents = value;
1354 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1355 Resources.maxGeometryVaryingComponents = value;
1356 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1357 Resources.maxTessControlInputComponents = value;
1358 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1359 Resources.maxTessControlOutputComponents = value;
1360 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1361 Resources.maxTessControlTextureImageUnits = value;
1362 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1363 Resources.maxTessControlUniformComponents = value;
1364 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1365 Resources.maxTessControlTotalOutputComponents = value;
1366 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1367 Resources.maxTessEvaluationInputComponents = value;
1368 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1369 Resources.maxTessEvaluationOutputComponents = value;
1370 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1371 Resources.maxTessEvaluationTextureImageUnits = value;
1372 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1373 Resources.maxTessEvaluationUniformComponents = value;
1374 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1375 Resources.maxTessPatchComponents = value;
1376 else if (strcmp(token, "MaxPatchVertices") == 0)
1377 Resources.maxPatchVertices = value;
1378 else if (strcmp(token, "MaxTessGenLevel") == 0)
1379 Resources.maxTessGenLevel = value;
1380 else if (strcmp(token, "MaxViewports") == 0)
1381 Resources.maxViewports = value;
1382 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1383 Resources.maxVertexAtomicCounters = value;
1384 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1385 Resources.maxTessControlAtomicCounters = value;
1386 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1387 Resources.maxTessEvaluationAtomicCounters = value;
1388 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1389 Resources.maxGeometryAtomicCounters = value;
1390 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1391 Resources.maxFragmentAtomicCounters = value;
1392 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1393 Resources.maxCombinedAtomicCounters = value;
1394 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1395 Resources.maxAtomicCounterBindings = value;
1396 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1397 Resources.maxVertexAtomicCounterBuffers = value;
1398 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1399 Resources.maxTessControlAtomicCounterBuffers = value;
1400 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1401 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1402 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1403 Resources.maxGeometryAtomicCounterBuffers = value;
1404 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1405 Resources.maxFragmentAtomicCounterBuffers = value;
1406 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1407 Resources.maxCombinedAtomicCounterBuffers = value;
1408 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1409 Resources.maxAtomicCounterBufferSize = value;
1410 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1411 Resources.maxTransformFeedbackBuffers = value;
1412 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1413 Resources.maxTransformFeedbackInterleavedComponents = value;
1414 else if (strcmp(token, "MaxCullDistances") == 0)
1415 Resources.maxCullDistances = value;
1416 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1417 Resources.maxCombinedClipAndCullDistances = value;
1418 else if (strcmp(token, "MaxSamples") == 0)
1419 Resources.maxSamples = value;
1420
1421 else if (strcmp(token, "nonInductiveForLoops") == 0)
1422 Resources.limits.nonInductiveForLoops = (value != 0);
1423 else if (strcmp(token, "whileLoops") == 0)
1424 Resources.limits.whileLoops = (value != 0);
1425 else if (strcmp(token, "doWhileLoops") == 0)
1426 Resources.limits.doWhileLoops = (value != 0);
1427 else if (strcmp(token, "generalUniformIndexing") == 0)
1428 Resources.limits.generalUniformIndexing = (value != 0);
1429 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1430 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1431 else if (strcmp(token, "generalVaryingIndexing") == 0)
1432 Resources.limits.generalVaryingIndexing = (value != 0);
1433 else if (strcmp(token, "generalSamplerIndexing") == 0)
1434 Resources.limits.generalSamplerIndexing = (value != 0);
1435 else if (strcmp(token, "generalVariableIndexing") == 0)
1436 Resources.limits.generalVariableIndexing = (value != 0);
1437 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1438 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1439 else
1440 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1441
1442 token = strtok(0, delims);
1443 }
1444 if (configStrings)
1445 FreeFileData(configStrings);
1446}
1447
Tony Barbour6918cd52015-04-09 12:58:51 -06001448void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001449{
1450 if (m_compile_options & EOptionRelaxedErrors)
1451 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1452 if (m_compile_options & EOptionIntermediate)
1453 messages = (EShMessages)(messages | EShMsgAST);
1454 if (m_compile_options & EOptionSuppressWarnings)
1455 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1456}
1457
1458//
1459// Malloc a string of sufficient size and read a string into it.
1460//
Tony Barbour6918cd52015-04-09 12:58:51 -06001461char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001462{
1463 FILE *in;
1464 #if defined(_WIN32) && defined(__GNUC__)
1465 in = fopen(fileName, "r");
1466 int errorCode = in ? 0 : 1;
1467 #else
1468 int errorCode = fopen_s(&in, fileName, "r");
1469 #endif
1470
1471 char *fdata;
1472 int count = 0;
1473 const int maxSourceStrings = 5;
1474 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1475
1476 if (errorCode) {
1477 printf("Error: unable to open input file: %s\n", fileName);
1478 return 0;
1479 }
1480
1481 while (fgetc(in) != EOF)
1482 count++;
1483
1484 fseek(in, 0, SEEK_SET);
1485
1486 if (!(fdata = (char*)malloc(count+2))) {
1487 printf("Error allocating memory\n");
1488 return 0;
1489 }
1490 if (fread(fdata,1,count, in)!=count) {
1491 printf("Error reading input file: %s\n", fileName);
1492 return 0;
1493 }
1494 fdata[count] = '\0';
1495 fclose(in);
1496 if (count == 0) {
1497 return_data[0]=(char*)malloc(count+2);
1498 return_data[0][0]='\0';
1499 m_num_shader_strings = 0;
1500 return return_data;
1501 } else
1502 m_num_shader_strings = 1;
1503
1504 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1505 int ptr_len=0,i=0;
1506 while(count>0){
1507 return_data[i]=(char*)malloc(len+2);
1508 memcpy(return_data[i],fdata+ptr_len,len);
1509 return_data[i][len]='\0';
1510 count-=(len);
1511 ptr_len+=(len);
1512 if(count<len){
1513 if(count==0){
1514 m_num_shader_strings=(i+1);
1515 break;
1516 }
1517 len = count;
1518 }
1519 ++i;
1520 }
1521 return return_data;
1522}
1523
Tony Barbour6918cd52015-04-09 12:58:51 -06001524void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001525{
1526 for(int i=0;i<m_num_shader_strings;i++)
1527 free(data[i]);
1528}
1529
1530//
1531// Deduce the language from the filename. Files must end in one of the
1532// following extensions:
1533//
1534// .vert = vertex
1535// .tesc = tessellation control
1536// .tese = tessellation evaluation
1537// .geom = geometry
1538// .frag = fragment
1539// .comp = compute
1540//
Tony Barbour6918cd52015-04-09 12:58:51 -06001541EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001542{
1543 size_t ext = name.rfind('.');
1544 if (ext == std::string::npos) {
1545 return EShLangVertex;
1546 }
1547
1548 std::string suffix = name.substr(ext + 1, std::string::npos);
1549 if (suffix == "vert")
1550 return EShLangVertex;
1551 else if (suffix == "tesc")
1552 return EShLangTessControl;
1553 else if (suffix == "tese")
1554 return EShLangTessEvaluation;
1555 else if (suffix == "geom")
1556 return EShLangGeometry;
1557 else if (suffix == "frag")
1558 return EShLangFragment;
1559 else if (suffix == "comp")
1560 return EShLangCompute;
1561
1562 return EShLangVertex;
1563}
1564
1565//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001566// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001567//
Tony Barbourd1c35722015-04-16 15:59:00 -06001568EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001569{
1570 switch (shader_type) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001571 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001572 return EShLangVertex;
1573
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001574 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001575 return EShLangTessControl;
1576
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001577 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001578 return EShLangTessEvaluation;
1579
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001580 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001581 return EShLangGeometry;
1582
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001583 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001584 return EShLangFragment;
1585
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001586 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001587 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001588
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001589 default:
1590 return EShLangVertex;
1591 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001592}
1593
1594
1595//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001596// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001597// Return value of false means an error was encountered.
1598//
Tony Barbourd1c35722015-04-16 15:59:00 -06001599bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001600 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001601 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001602{
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001603 glslang::TProgram program;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001604 const char *shaderStrings[1];
1605
1606 // TODO: Do we want to load a special config file depending on the
1607 // shader source? Optional name maybe?
1608 // SetConfigFile(fileName);
1609
1610 ProcessConfigFile();
1611
1612 EShMessages messages = EShMsgDefault;
1613 SetMessageOptions(messages);
1614
1615 EShLanguage stage = FindLanguage(shader_type);
1616 glslang::TShader* shader = new glslang::TShader(stage);
1617
1618 shaderStrings[0] = pshader;
1619 shader->setStrings(shaderStrings, 1);
1620
1621 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1622
Cody Northrop195d6622014-11-03 12:54:37 -07001623 if (! (m_compile_options & EOptionSuppressInfolog)) {
1624 puts(shader->getInfoLog());
1625 puts(shader->getInfoDebugLog());
1626 }
1627
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001628 return false; // something didn't work
1629 }
1630
1631 program.addShader(shader);
1632
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001633
1634 //
1635 // Program-level processing...
1636 //
1637
Cody Northrop195d6622014-11-03 12:54:37 -07001638 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001639
Cody Northrop195d6622014-11-03 12:54:37 -07001640 if (! (m_compile_options & EOptionSuppressInfolog)) {
1641 puts(shader->getInfoLog());
1642 puts(shader->getInfoDebugLog());
1643 }
1644
1645 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001646 }
1647
1648 if (m_compile_options & EOptionDumpReflection) {
1649 program.buildReflection();
1650 program.dumpReflection();
1651 }
1652
Cody Northrop5a95b472015-06-03 13:01:54 -06001653 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1654
1655 //
1656 // Test the different modes of SPIR-V modification
1657 //
1658 if (this->m_canonicalize_spv) {
1659 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1660 }
1661
1662 if (this->m_strip_spv) {
1663 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1664 }
1665
1666 if (this->m_do_everything_spv) {
1667 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1668 }
1669
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -06001670 delete shader;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001671
1672 return true;
1673}
1674
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001675
1676
Tony Barbour6918cd52015-04-09 12:58:51 -06001677VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001678 m_width( 0 ),
1679 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001680 m_data( NULL ),
1681 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001682{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001683}
1684
Tony Barbour6918cd52015-04-09 12:58:51 -06001685VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001686{
1687
1688}
1689
Tony Barbour6918cd52015-04-09 12:58:51 -06001690VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001691{
1692 m_title = copyin.m_title;
1693 m_width = copyin.m_width;
1694 m_height = copyin.m_height;
1695 m_data_size = copyin.m_data_size;
1696 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1697}
1698
Tony Barbour6918cd52015-04-09 12:58:51 -06001699ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001700{
Tony Barbour6918cd52015-04-09 12:58:51 -06001701 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1702 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001703 return output;
1704}
1705
Tony Barbour6918cd52015-04-09 12:58:51 -06001706VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001707{
1708 m_title = rhs.m_title;
1709 m_width = rhs.m_width;
1710 m_height = rhs.m_height;
1711 m_data_size = rhs.m_data_size;
1712 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001713 return *this;
1714}
1715
Tony Barbour6918cd52015-04-09 12:58:51 -06001716int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001717{
1718 if( this->m_data != rhs.m_data) return 0;
1719 return 1;
1720}
1721
1722// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001723int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001724{
1725 if( this->m_data_size < rhs.m_data_size ) return 1;
1726 return 0;
1727}
1728