blob: 205fbcbfb6ec279dd78aeba2dd74f4507e5d0191 [file] [log] [blame]
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001// VK tests
Courtney Goeltzenleuchterd0d7ccc2014-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 Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060023#include "vktestframework.h"
24#include "vkrenderframework.h"
Cody Northropeb9130e2015-06-03 13:01:54 -060025#include "SPIRV/GlslangToSpv.h"
26#include "SPIRV/SPVRemapper.h"
Tony Barbour772c5ef2014-12-10 17:00:20 -070027#include <limits.h>
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -060028#include <math.h>
Chia-I Wu3d9ebb22014-12-02 11:54:24 +080029#include <wand/MagickWand.h>
Tony Barboura26fb7d2015-09-21 15:17:33 -060030#ifndef _WIN32
Chia-I Wu5b66aa52015-04-16 22:02:10 +080031#include <xcb/xcb.h>
Tony Barboura26fb7d2015-09-21 15:17:33 -060032#endif
Ian Elliott338dedb2015-08-21 15:09:33 -060033#include "vk_ext_khr_swapchain.h"
34#include "vk_ext_khr_device_swapchain.h"
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -060035
Tony Barbour25e3b832015-05-20 16:53:31 -060036#if defined(PATH_MAX) && !defined(MAX_PATH)
37#define MAX_PATH PATH_MAX
38#endif
39
Tony Barbourb3744222015-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 Goeltzenleuchter94192032014-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 Northropacfb0492015-03-17 15:55:58 -060088 EOptionSpv = 0x800,
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -060089 EOptionDefaultDesktop = 0x1000,
90};
91
Ian Elliott338dedb2015-08-21 15:09:33 -060092typedef struct _SwapchainBuffers {
Tony Barbourb3744222015-07-23 10:36:18 -060093 VkImage image;
94 VkCmdBuffer cmd;
Courtney Goeltzenleuchter1856d6f2015-09-01 17:30:39 -060095 VkImageView view;
Ian Elliott338dedb2015-08-21 15:09:33 -060096} SwapchainBuffers;
Tony Barbourb3744222015-07-23 10:36:18 -060097
Chia-I Wu5b66aa52015-04-16 22:02:10 +080098class TestFrameworkVkPresent
99{
100public:
101 TestFrameworkVkPresent(vk_testing::Device &device);
102
103 void Run();
Jon Ashburncedc15f2015-05-21 18:13:33 -0600104 void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800105 void CreateMyWindow();
Ian Elliott338dedb2015-08-21 15:09:33 -0600106 void CreateSwapchain();
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800107 void TearDown();
Tony Barbour25e3b832015-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 Wu5b66aa52015-04-16 22:02:10 +0800112
113protected:
114 vk_testing::Device &m_device;
115 vk_testing::Queue &m_queue;
Dana Jansens6e2dda12015-07-30 13:04:16 -0700116 vk_testing::CmdPool m_cmdpool;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800117 vk_testing::CmdBuffer m_cmdbuf;
118
119private:
Tony Barbour25e3b832015-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 Wu5b66aa52015-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 Elliott338dedb2015-08-21 15:09:33 -0600129 VkPlatformHandleXcbKHR m_platform_handle_xcb;
Tony Barbour25e3b832015-05-20 16:53:31 -0600130#endif
Courtney Goeltzenleuchterec69b9c2015-04-22 10:09:35 -0600131 std::list<VkTestImageRecord> m_images;
Tony Barbourb3744222015-07-23 10:36:18 -0600132 uint32_t m_present_queue_node_index;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800133
Ian Elliott338dedb2015-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 Barbourb3744222015-07-23 10:36:18 -0600147 VkFormat m_format;
Ian Elliott338dedb2015-08-21 15:09:33 -0600148 VkColorSpaceKHR m_color_space;
Tony Barbourb3744222015-07-23 10:36:18 -0600149
150 uint32_t m_current_buffer;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800151
152 bool m_quit;
153 bool m_pause;
154
Tony Barbour8bef8ee2015-05-22 09:44:58 -0600155 int m_width;
156 int m_height;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800157
158 std::list<VkTestImageRecord>::iterator m_display_image;
159
160 void Display();
Tony Barboura26fb7d2015-09-21 15:17:33 -0600161#ifndef _WIN32
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800162 void HandleEvent(xcb_generic_event_t *event);
Tony Barboura26fb7d2015-09-21 15:17:33 -0600163#endif
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800164};
165
Courtney Goeltzenleuchter94192032014-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600194
Tony Barbour25e3b832015-05-20 16:53:31 -0600195
196
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600197// Set up environment for GLSL compiler
198// Must be done once per process
199void TestEnvironment::SetUp()
200{
Cody Northropacfb0492015-03-17 15:55:58 -0600201 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600202 glslang::InitializeProcess();
Chia-I Wu1c9869e2014-12-28 14:27:28 +0800203
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600204 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600205}
206
207void TestEnvironment::TearDown()
208{
209 glslang::FinalizeProcess();
210}
211
Tony Barbour01999182015-04-09 12:58:51 -0600212VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600213 m_compile_options( 0 ),
214 m_num_shader_strings( 0 )
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600215{
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600216
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600217}
218
Tony Barbour01999182015-04-09 12:58:51 -0600219VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600220{
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600221
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600222}
223
224// Define all the static elements
Cody Northropa392a292015-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 Northropeb9130e2015-06-03 13:01:54 -0600231bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour01999182015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600236int m_display_image_idx = 0;
237
Cody Northrop1cfbd172015-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 Barbour01999182015-04-09 12:58:51 -0600246void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600247{
248 int i, n;
249
Cody Northrop1cfbd172015-06-03 16:49:20 -0600250 for (i=1, n=1; i< *argc; i++) {
251 if (optionMatch("--show-images", argv[i]))
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600252 m_show_images = true;
Cody Northrop1cfbd172015-06-03 16:49:20 -0600253 else if (optionMatch("--save-images", argv[i]))
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600254 m_save_images = true;
Cody Northrop1cfbd172015-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 Barbour32f368c2014-10-30 14:29:04 -0600262 m_compare_images = true;
Tony Barbour32f368c2014-10-30 14:29:04 -0600263
Cody Northrop1cfbd172015-06-03 16:49:20 -0600264 else if (optionMatch("--help", argv[i]) ||
265 optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchterb7f26e02014-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 Barbour0e4235d2014-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 Goeltzenleuchterb7f26e02014-12-02 13:13:10 -0700278 "\t\tSignal test failure if different.\n");
Cody Northropacfb0492015-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 Northrop1cfbd172015-06-03 16:49:20 -0600281 printf("\t--strip-SPV\n"
Cody Northrop1e056dd2015-07-13 12:48:41 -0600282 "\t\tStrip SPIR-V debug information (line numbers, names, etc).\n");
Cody Northrop1cfbd172015-06-03 16:49:20 -0600283 printf("\t--canonicalize-SPV\n"
Cody Northrop1e056dd2015-07-13 12:48:41 -0600284 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
Cody Northrop1cfbd172015-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 Barbour772c5ef2014-12-10 17:00:20 -0700289 exit(0);
Courtney Goeltzenleuchterb7f26e02014-12-02 13:13:10 -0700290 }
291
Cody Northrop1cfbd172015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600297 argv[n] = argv[i];
298 n++;
299 }
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600300}
301
Tony Barbour01999182015-04-09 12:58:51 -0600302void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600303{
304 string filename;
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600305 VkResult err;
Tony Barbour8bef8ee2015-05-22 09:44:58 -0600306 uint32_t x, y;
Tony Barbour01999182015-04-09 12:58:51 -0600307 VkImageObj displayImage(image->device());
Tony Barbour94310562015-04-22 15:10:33 -0600308 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbouredc49d92015-04-02 14:02:33 -0600309
Tony Barboura7ec3ba2015-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 Barbouredc49d92015-04-02 14:02:33 -0600311 displayImage.CopyImage(*image);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600312
313 filename.append(basename);
314 filename.append(".ppm");
Tony Barbour25e3b832015-05-20 16:53:31 -0600315
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600316 const VkImageSubresource sr = {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600317 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600318 };
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600319 VkSubresourceLayout sr_layout;
Tony Barbour25e3b832015-05-20 16:53:31 -0600320
Tony Barbour426b9052015-06-24 16:06:58 -0600321 err = vkGetImageSubresourceLayout(image->device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600322 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600323
Tony Barbouredc49d92015-04-02 14:02:33 -0600324 char *ptr;
Chia-I Wuf4aed6c2015-07-03 13:44:34 +0800325 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600326 ptr += sr_layout.offset;
Tony Barbour25e3b832015-05-20 16:53:31 -0600327 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600328 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
329
330 file << "P6\n";
Tony Barboura26fb7d2015-09-21 15:17:33 -0600331 file << displayImage.width() << " ";
Tony Barbouredc49d92015-04-02 14:02:33 -0600332 file << displayImage.height() << "\n";
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600333 file << 255 << "\n";
334
Tony Barbouredc49d92015-04-02 14:02:33 -0600335 for (y = 0; y < displayImage.height(); y++) {
Tony Barboure2668672015-02-25 11:25:11 -0700336 const int *row = (const int *) ptr;
337 int swapped;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600338
Tony Barbour8205d902015-04-16 15:59:00 -0600339 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboure2668672015-02-25 11:25:11 -0700340 {
Tony Barbouredc49d92015-04-02 14:02:33 -0600341 for (x = 0; x < displayImage.width(); x++) {
Tony Barboure2668672015-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 Barbour8205d902015-04-16 15:59:00 -0600347 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboure2668672015-02-25 11:25:11 -0700348 {
Tony Barbouredc49d92015-04-02 14:02:33 -0600349 for (x = 0; x < displayImage.width(); x++) {
Tony Barboure2668672015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600357 }
358
359 ptr += sr_layout.rowPitch;
360 }
361
362 file.close();
Chia-I Wuf4aed6c2015-07-03 13:44:34 +0800363 displayImage.UnmapMemory();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600364}
365
Tony Barbour01999182015-04-09 12:58:51 -0600366void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour32f368c2014-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 Barbour25e3b832015-05-20 16:53:31 -0600373 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour32f368c2014-10-30 14:29:04 -0600374 double differenz;
375
Tony Barbour772c5ef2014-12-10 17:00:20 -0700376 if (getenv("RENDERTEST_GOLDEN_DIR"))
377 {
378 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
379 }
380
Tony Barbour32f368c2014-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 Barbour8bef8ee2015-05-22 09:44:58 -0600385 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour32f368c2014-10-30 14:29:04 -0600386
387
388 MagickWandGenesis();
389 magick_wand_2=NewMagickWand();
Tony Barbour772c5ef2014-12-10 17:00:20 -0700390 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour32f368c2014-10-30 14:29:04 -0600391 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour8bef8ee2015-05-22 09:44:58 -0600392 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour32f368c2014-10-30 14:29:04 -0600393
Tony Barbour32f368c2014-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 Goeltzenleuchterdfa97b82014-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 Barbour32f368c2014-10-30 14:29:04 -0600417}
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600418
Tony Barbour01999182015-04-09 12:58:51 -0600419void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600420{
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600421 VkResult err;
Courtney Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600422 VkSubresourceLayout sr_layout;
423 char *ptr;
424 VkTestImageRecord record;
Courtney Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600425 VkImageObj displayImage(image->device());
426 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
427
Cody Northrop025cbb12015-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 Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600430 displayImage.CopyImage(*image);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600431
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600432 const VkImageSubresource sr = {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600433 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600434 };
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600435
Tony Barbour426b9052015-06-24 16:06:58 -0600436 err = vkGetImageSubresourceLayout(displayImage.device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600437 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600438
Chia-I Wuf4aed6c2015-07-03 13:44:34 +0800439 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600440 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600441
442 ptr += sr_layout.offset;
443
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600444 record.m_title.append(comment);
Courtney Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600445 record.m_width = displayImage.width();
446 record.m_height = displayImage.height();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600447 // TODO: Need to make this more robust to handle different image formats
Tony-LunarGf05ba082015-05-19 14:08:26 -0600448 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchterd0d7ccc2014-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 Wuf4aed6c2015-07-03 13:44:34 +0800454 displayImage.UnmapMemory();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600455}
456
Tony Barbour01999182015-04-09 12:58:51 -0600457void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour32f368c2014-10-30 14:29:04 -0600458{
Courtney Goeltzenleuchtercd5ed1e2015-04-02 14:17:44 -0600459 for (int32_t i = 0; i < images.size(); i++) {
460 RecordImage(images[i]);
Tony Barbour32f368c2014-10-30 14:29:04 -0600461 }
462}
463
Tony Barbour01999182015-04-09 12:58:51 -0600464void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600465{
466 const ::testing::TestInfo* const test_info =
467 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour32f368c2014-10-30 14:29:04 -0600468 ostringstream filestream;
469 string filename;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600470
Tony Barbour32f368c2014-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 Barboura48b0812014-11-18 17:02:36 -0700476 m_frameNum = 2;
477 filename = filestream.str();
Tony Barbour32f368c2014-10-30 14:29:04 -0600478 }
479 else {
480 filestream << test_info->name() << "-" << m_frameNum;
481 m_frameNum++;
Tony Barboura48b0812014-11-18 17:02:36 -0700482 filename = filestream.str();
Tony Barbour32f368c2014-10-30 14:29:04 -0600483 }
484
Tony Barbour32f368c2014-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600492 }
493
494 if (m_show_images) {
Courtney Goeltzenleuchtere5409342014-10-08 14:26:40 -0600495 Show(test_info->name(), image);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600496 }
497}
498
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800499TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
500 m_device(device),
Courtney Goeltzenleuchterdd745fd2015-03-05 16:47:18 -0700501 m_queue(*m_device.graphics_queues()[0]),
Dana Jansens6e2dda12015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600504{
Tony Barbouref20d322015-02-25 12:28:39 -0700505 m_quit = false;
506 m_pause = false;
507 m_width = 0;
508 m_height = 0;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600509}
510
Tony Barbour01999182015-04-09 12:58:51 -0600511void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600512{
Tony Barbour22a30862015-04-22 09:02:32 -0600513 VkResult U_ASSERT_ONLY err;
Tony-LunarGf05ba082015-05-19 14:08:26 -0600514 vk_testing::Buffer buf;
515 void *dest_ptr;
516
Tony Barbourb3744222015-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 Elliott338dedb2015-08-21 15:09:33 -0600530 err = m_fpAcquireNextImageKHR(m_device.handle(), m_swap_chain,
Tony Barbourb3744222015-07-23 10:36:18 -0600531 UINT64_MAX,
532 presentCompleteSemaphore,
533 &m_current_buffer);
Ian Elliott338dedb2015-08-21 15:09:33 -0600534 // TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
Tony Barbourb3744222015-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 Barboure483fc02015-10-23 10:58:56 -0600543 vkDestroySemaphore(m_device.handle(), presentCompleteSemaphore);
Tony-LunarGf05ba082015-05-19 14:08:26 -0600544
545 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Cody Northropd0e7d222015-06-22 14:56:14 -0600546 buf.init_as_src(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
Chia-I Wuf4aed6c2015-07-03 13:44:34 +0800547 dest_ptr = buf.memory().map();
Tony-LunarGf05ba082015-05-19 14:08:26 -0600548 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
Chia-I Wuf4aed6c2015-07-03 13:44:34 +0800549 buf.memory().unmap();
Tony-LunarGf05ba082015-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 Wu78c2a352015-07-03 11:49:42 +0800558 vkCmdCopyBufferToImage(m_cmdbuf.handle(),
Chia-I Wuf4aed6c2015-07-03 13:44:34 +0800559 buf.handle(),
Tony Barbourb3744222015-07-23 10:36:18 -0600560 m_buffers[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
Tony-LunarGf05ba082015-05-19 14:08:26 -0600561 1, &region);
562 m_cmdbuf.end();
563
564 VkCmdBuffer cmdBufs[1];
Chia-I Wu78c2a352015-07-03 11:49:42 +0800565 cmdBufs[0] = m_cmdbuf.handle();
Tony-LunarGf05ba082015-05-19 14:08:26 -0600566
Tony Barboure84a8d62015-07-10 14:10:27 -0600567 VkFence nullFence = { VK_NULL_HANDLE };
568 vkQueueSubmit(m_queue.handle(), 1, cmdBufs, nullFence);
Tony-LunarGf05ba082015-05-19 14:08:26 -0600569 m_queue.wait();
Tony Barbouref20d322015-02-25 12:28:39 -0700570
Ian Elliott338dedb2015-08-21 15:09:33 -0600571 VkPresentInfoKHR present = {};
572 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
Tony Barbourb3744222015-07-23 10:36:18 -0600573 present.pNext = NULL;
Ian Elliott338dedb2015-08-21 15:09:33 -0600574 present.swapchainCount = 1;
575 present.swapchains = & m_swap_chain;
Tony Barbourb3744222015-07-23 10:36:18 -0600576 present.imageIndices = &m_current_buffer;
Tony Barbouref20d322015-02-25 12:28:39 -0700577
Tony Barbour25e3b832015-05-20 16:53:31 -0600578#ifndef _WIN32
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800579 xcb_change_property (m_connection,
Tony Barbouref20d322015-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 Barbour25e3b832015-05-20 16:53:31 -0600587#endif
Jon Ashburncedc15f2015-05-21 18:13:33 -0600588
Ian Elliott338dedb2015-08-21 15:09:33 -0600589 err = m_fpQueuePresentKHR(m_queue.handle(), &present);
Tony Barbouref20d322015-02-25 12:28:39 -0700590 assert(!err);
591
592 m_queue.wait();
Tony-LunarGf05ba082015-05-19 14:08:26 -0600593 m_current_buffer = (m_current_buffer + 1) % 2;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600594}
595
Tony Barbour25e3b832015-05-20 16:53:31 -0600596#ifdef _WIN32
Tony-LunarGf05ba082015-05-19 14:08:26 -0600597# define PREVIOUSLY_DOWN 1<<29
Tony Barbour25e3b832015-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-LunarGf05ba082015-05-19 14:08:26 -0600615 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour25e3b832015-05-20 16:53:31 -0600616 me->Display();
617 }
618 }
Tony-LunarGf05ba082015-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 Barbour25e3b832015-05-20 16:53:31 -0600656 }
657 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
658}
659
660void TestFrameworkVkPresent::Run()
661{
662 MSG msg; // message
Tony Barbour25e3b832015-05-20 16:53:31 -0600663
Tony Barbour25e3b832015-05-20 16:53:31 -0600664 /* main message loop*/
Tony-LunarGf05ba082015-05-19 14:08:26 -0600665 while(! m_quit) {
666 GetMessage(&msg, m_window, 0, 0);
Tony Barbour25e3b832015-05-20 16:53:31 -0600667 if (msg.message == WM_QUIT) {
Tony-LunarGf05ba082015-05-19 14:08:26 -0600668 m_quit = true; //if found, quit app
Tony Barbour25e3b832015-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 Barbour01999182015-04-09 12:58:51 -0600678void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600679{
Tony Barbour3a5cda02015-04-02 15:48:24 -0600680 uint8_t event_code = event->response_type & 0x7f;
Tony Barbouref20d322015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600689 }
690 break;
Tony Barbouref20d322015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600695
Tony Barbouref20d322015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600721 break;
722 }
Tony Barbouref20d322015-02-25 12:28:39 -0700723}
724
Tony Barbour01999182015-04-09 12:58:51 -0600725void TestFrameworkVkPresent::Run()
Tony Barbouref20d322015-02-25 12:28:39 -0700726{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800727 xcb_flush(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700728
729 while (! m_quit) {
730 xcb_generic_event_t *event;
731
732 if (m_pause) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800733 event = xcb_wait_for_event(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700734 } else {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800735 event = xcb_poll_for_event(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700736 }
737 if (event) {
738 HandleEvent(event);
739 free(event);
740 }
741 }
742}
Tony Barbour25e3b832015-05-20 16:53:31 -0600743#endif // _WIN32
Tony Barbouref20d322015-02-25 12:28:39 -0700744
Ian Elliott338dedb2015-08-21 15:09:33 -0600745void TestFrameworkVkPresent::CreateSwapchain()
Tony Barbouref20d322015-02-25 12:28:39 -0700746{
Tony Barbour22a30862015-04-22 09:02:32 -0600747 VkResult U_ASSERT_ONLY err;
Tony Barbouref20d322015-02-25 12:28:39 -0700748
Tony-LunarGf05ba082015-05-19 14:08:26 -0600749 m_display_image = m_images.begin();
750 m_current_buffer = 0;
751
Tony Barbourb3744222015-07-23 10:36:18 -0600752 // Construct the WSI surface description:
Ian Elliott338dedb2015-08-21 15:09:33 -0600753 m_surface_description.sType = VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_KHR;
Tony Barbourb3744222015-07-23 10:36:18 -0600754 m_surface_description.pNext = NULL;
Ian Elliott331f4e82015-07-06 14:33:04 -0600755#ifdef _WIN32
Ian Elliott338dedb2015-08-21 15:09:33 -0600756 m_surface_description.platform = VK_PLATFORM_WIN32_KHR;
Tony Barbourb3744222015-07-23 10:36:18 -0600757 m_surface_description.pPlatformHandle = m_connection;
758 m_surface_description.pPlatformWindow = m_window;
Ian Elliott331f4e82015-07-06 14:33:04 -0600759#else // _WIN32
Tony Barbourb3744222015-07-23 10:36:18 -0600760 m_platform_handle_xcb.connection = m_connection;
761 m_platform_handle_xcb.root = m_screen->root;
Ian Elliott338dedb2015-08-21 15:09:33 -0600762 m_surface_description.platform = VK_PLATFORM_XCB_KHR;
Tony Barbourb3744222015-07-23 10:36:18 -0600763 m_surface_description.pPlatformHandle = &m_platform_handle_xcb;
764 m_surface_description.pPlatformWindow = &m_window;
Ian Elliott331f4e82015-07-06 14:33:04 -0600765#endif // _WIN32
Tony Barbourb3744222015-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 Elliott338dedb2015-08-21 15:09:33 -0600774 m_fpGetPhysicalDeviceSurfaceSupportKHR(m_device.phy().handle(),
Tony Barbourb3744222015-07-23 10:36:18 -0600775 family_index,
Ian Elliott338dedb2015-08-21 15:09:33 -0600776 (VkSurfaceDescriptionKHR *) &m_surface_description,
Tony Barbourb3744222015-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 Elliottdad13202015-08-07 11:51:12 -0600787 uint32_t formatCount;
Ian Elliott338dedb2015-08-21 15:09:33 -0600788 err = m_fpGetSurfaceFormatsKHR(m_device.handle(),
789 (VkSurfaceDescriptionKHR *) &m_surface_description,
Ian Elliottdad13202015-08-07 11:51:12 -0600790 &formatCount, NULL);
Tony Barbourb3744222015-07-23 10:36:18 -0600791 assert(!err);
Ian Elliott338dedb2015-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 Elliottdad13202015-08-07 11:51:12 -0600796 &formatCount, surfFormats);
Tony Barbourb3744222015-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 Barbourb3744222015-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 Elliottdad13202015-08-07 11:51:12 -0600810 m_color_space = surfFormats[0].colorSpace;
Tony Barbourb3744222015-07-23 10:36:18 -0600811
812 // Check the surface proprties and formats
Ian Elliott338dedb2015-08-21 15:09:33 -0600813 VkSurfacePropertiesKHR surfProperties;
814 err = m_fpGetSurfacePropertiesKHR(m_device.handle(),
815 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliottdad13202015-08-07 11:51:12 -0600816 &surfProperties);
Tony Barbourb3744222015-07-23 10:36:18 -0600817 assert(!err);
818
Ian Elliottdad13202015-08-07 11:51:12 -0600819 uint32_t presentModeCount;
Ian Elliott338dedb2015-08-21 15:09:33 -0600820 err = m_fpGetSurfacePresentModesKHR(m_device.handle(),
821 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliottdad13202015-08-07 11:51:12 -0600822 &presentModeCount, NULL);
Tony Barbourb3744222015-07-23 10:36:18 -0600823 assert(!err);
Ian Elliott338dedb2015-08-21 15:09:33 -0600824 VkPresentModeKHR *presentModes =
825 (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
Ian Elliottdad13202015-08-07 11:51:12 -0600826 assert(presentModes);
Ian Elliott338dedb2015-08-21 15:09:33 -0600827 err = m_fpGetSurfacePresentModesKHR(m_device.handle(),
828 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliottdad13202015-08-07 11:51:12 -0600829 &presentModeCount, presentModes);
Tony Barbourb3744222015-07-23 10:36:18 -0600830 assert(!err);
831
Ian Elliott338dedb2015-08-21 15:09:33 -0600832 VkExtent2D swapchainExtent;
Tony Barbourb3744222015-07-23 10:36:18 -0600833 // width and height are either both -1, or both not -1.
Ian Elliottdad13202015-08-07 11:51:12 -0600834 if (surfProperties.currentExtent.width == -1)
Tony Barbourb3744222015-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 Elliott338dedb2015-08-21 15:09:33 -0600838 swapchainExtent.width = m_width;
839 swapchainExtent.height = m_height;
Tony Barbourb3744222015-07-23 10:36:18 -0600840 }
841 else
842 {
843 // If the surface size is defined, the swap chain size must match
Ian Elliott338dedb2015-08-21 15:09:33 -0600844 swapchainExtent = surfProperties.currentExtent;
Tony Barbourb3744222015-07-23 10:36:18 -0600845 }
846
847 // If mailbox mode is available, use it, as is the lowest-latency non-
Ian Elliotta96de0f2015-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 Elliott338dedb2015-08-21 15:09:33 -0600851 VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
Tony Barbourb3744222015-07-23 10:36:18 -0600852 for (size_t i = 0; i < presentModeCount; i++) {
Ian Elliott338dedb2015-08-21 15:09:33 -0600853 if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
854 swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
Tony Barbourb3744222015-07-23 10:36:18 -0600855 break;
856 }
Ian Elliott338dedb2015-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 Elliotta96de0f2015-08-10 13:20:49 -0600860 }
Tony Barbourb3744222015-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 Elliott338dedb2015-08-21 15:09:33 -0600866 uint32_t desiredNumberOfSwapchainImages = surfProperties.minImageCount + 1;
Ian Elliottdad13202015-08-07 11:51:12 -0600867 if ((surfProperties.maxImageCount > 0) &&
Ian Elliott338dedb2015-08-21 15:09:33 -0600868 (desiredNumberOfSwapchainImages > surfProperties.maxImageCount))
Tony Barbourb3744222015-07-23 10:36:18 -0600869 {
870 // Application must settle for fewer images than desired:
Ian Elliott338dedb2015-08-21 15:09:33 -0600871 desiredNumberOfSwapchainImages = surfProperties.maxImageCount;
Tony Barbourb3744222015-07-23 10:36:18 -0600872 }
873
Ian Elliott338dedb2015-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 Barbourb3744222015-07-23 10:36:18 -0600877 } else {
Ian Elliottdad13202015-08-07 11:51:12 -0600878 preTransform = surfProperties.currentTransform;
Tony Barbourb3744222015-07-23 10:36:18 -0600879 }
Ian Elliott331f4e82015-07-06 14:33:04 -0600880
Cody Northrop3b0a3ef2015-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 Elliott338dedb2015-08-21 15:09:33 -0600884 VkSwapchainCreateInfoKHR swap_chain = {};
Ian Elliott434d2222015-09-22 10:20:23 -0600885 swap_chain.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
Ian Elliott331f4e82015-07-06 14:33:04 -0600886 swap_chain.pNext = NULL;
Ian Elliott338dedb2015-08-21 15:09:33 -0600887 swap_chain.pSurfaceDescription = (const VkSurfaceDescriptionKHR *)&m_surface_description;
888 swap_chain.minImageCount = desiredNumberOfSwapchainImages;
Tony Barbourb3744222015-07-23 10:36:18 -0600889 swap_chain.imageFormat = m_format;
Ian Elliottdad13202015-08-07 11:51:12 -0600890 swap_chain.imageColorSpace = m_color_space;
Ian Elliott338dedb2015-08-21 15:09:33 -0600891 swap_chain.imageExtent.width = swapchainExtent.width;
892 swap_chain.imageExtent.height = swapchainExtent.height;
Cody Northrop7f815382015-08-05 15:38:39 -0600893 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT |
894 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
Tony Barbourb3744222015-07-23 10:36:18 -0600895 swap_chain.preTransform = preTransform;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800896 swap_chain.imageArraySize = 1;
Ian Elliottdad13202015-08-07 11:51:12 -0600897 swap_chain.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
898 swap_chain.queueFamilyCount = 0;
899 swap_chain.pQueueFamilyIndices = NULL;
Ian Elliott338dedb2015-08-21 15:09:33 -0600900 swap_chain.presentMode = swapchainPresentMode;
901 swap_chain.oldSwapchain.handle = 0;
Tony Barbourb3744222015-07-23 10:36:18 -0600902 swap_chain.clipped = true;
903
904 uint32_t i;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800905
Ian Elliott338dedb2015-08-21 15:09:33 -0600906 err = m_fpCreateSwapchainKHR(m_device.handle(), &swap_chain, &m_swap_chain);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800907 assert(!err);
908
Ian Elliott338dedb2015-08-21 15:09:33 -0600909 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
910 &m_swapchainImageCount, NULL);
Tony Barbourb3744222015-07-23 10:36:18 -0600911 assert(!err);
912
Ian Elliott338dedb2015-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 Barbourb3744222015-07-23 10:36:18 -0600917 assert(!err);
918
Ian Elliott338dedb2015-08-21 15:09:33 -0600919 m_buffers = (SwapchainBuffers*)malloc(sizeof(SwapchainBuffers)*m_swapchainImageCount);
Tony Barbourb3744222015-07-23 10:36:18 -0600920 assert(m_buffers);
921
Ian Elliott338dedb2015-08-21 15:09:33 -0600922 for (i = 0; i < m_swapchainImageCount; i++) {
Courtney Goeltzenleuchter1856d6f2015-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 Goeltzenleuchter065983e2015-09-11 15:22:06 -0600926 color_image_view.viewType = VK_IMAGE_VIEW_TYPE_2D;
Courtney Goeltzenleuchter1856d6f2015-09-01 17:30:39 -0600927 color_image_view.format = m_format;
Courtney Goeltzenleuchteraeffeae2015-09-10 17:58:54 -0600928 color_image_view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
Courtney Goeltzenleuchter1856d6f2015-09-01 17:30:39 -0600929 color_image_view.subresourceRange.baseMipLevel = 0;
930 color_image_view.subresourceRange.mipLevels = 1;
Courtney Goeltzenleuchter3dee8082015-09-10 16:38:41 -0600931 color_image_view.subresourceRange.baseArrayLayer = 0;
Courtney Goeltzenleuchter1856d6f2015-09-01 17:30:39 -0600932 color_image_view.subresourceRange.arraySize = 1;
Tony Barbourb3744222015-07-23 10:36:18 -0600933
Ian Elliott338dedb2015-08-21 15:09:33 -0600934 m_buffers[i].image = swapchainImages[i];
Tony Barbourb3744222015-07-23 10:36:18 -0600935
Courtney Goeltzenleuchter1856d6f2015-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 Barbourb3744222015-07-23 10:36:18 -0600939 assert(!err);
940 }
Tony Barbouref20d322015-02-25 12:28:39 -0700941}
942
Jon Ashburncedc15f2015-05-21 18:13:33 -0600943void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbouref20d322015-02-25 12:28:39 -0700944{
Ian Elliott338dedb2015-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 Ashburncedc15f2015-05-21 18:13:33 -0600955
Tony Barbouref20d322015-02-25 12:28:39 -0700956 m_images = imagesIn;
957}
958
Tony Barbour25e3b832015-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 Northropb746ee72015-08-05 15:39:31 -0600995 RECT wr = { 0, 0, m_width, m_height };
996 AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
Tony Barbour25e3b832015-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 Northropb746ee72015-08-05 15:39:31 -06001004 wr.right - wr.left, // width
1005 wr.bottom - wr.top, // height
Tony Barbour25e3b832015-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-LunarGf05ba082015-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 Barbour25e3b832015-05-20 16:53:31 -06001021}
1022#else
Tony Barbour01999182015-04-09 12:58:51 -06001023void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbouref20d322015-02-25 12:28:39 -07001024{
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001025 const xcb_setup_t *setup;
1026 xcb_screen_iterator_t iter;
1027 int scr;
Tony Barbouref20d322015-02-25 12:28:39 -07001028 uint32_t value_mask, value_list[32];
1029
Chia-I Wu5b66aa52015-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 Barbouref20d322015-02-25 12:28:39 -07001048
1049 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001050 value_list[0] = m_screen->black_pixel;
Tony Barbouref20d322015-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 Wu5b66aa52015-04-16 22:02:10 +08001055 xcb_create_window(m_connection,
Tony Barbouref20d322015-02-25 12:28:39 -07001056 XCB_COPY_FROM_PARENT,
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001057 m_window, m_screen->root,
Tony Barbouref20d322015-02-25 12:28:39 -07001058 0, 0, m_width, m_height, 0,
1059 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001060 m_screen->root_visual,
Tony Barbouref20d322015-02-25 12:28:39 -07001061 value_mask, value_list);
1062
1063 /* Magic code that will send notification when window is destroyed */
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001064 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbouref20d322015-02-25 12:28:39 -07001065 "WM_PROTOCOLS");
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001066 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbouref20d322015-02-25 12:28:39 -07001067
Chia-I Wu5b66aa52015-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 Barbouref20d322015-02-25 12:28:39 -07001070
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001071 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbouref20d322015-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 Wu5b66aa52015-04-16 22:02:10 +08001076 xcb_map_window(m_connection, m_window);
Tony Barbouref20d322015-02-25 12:28:39 -07001077}
Tony Barbour25e3b832015-05-20 16:53:31 -06001078#endif
Tony Barbouref20d322015-02-25 12:28:39 -07001079
Tony Barbour01999182015-04-09 12:58:51 -06001080void TestFrameworkVkPresent::TearDown()
Tony Barbouref20d322015-02-25 12:28:39 -07001081{
Ian Elliott338dedb2015-08-21 15:09:33 -06001082 m_fpDestroySwapchainKHR(m_device.handle(), m_swap_chain);
Tony Barboure483fc02015-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 Barbour25e3b832015-05-20 16:53:31 -06001087#ifndef _WIN32
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001088 xcb_destroy_window(m_connection, m_window);
1089 xcb_disconnect(m_connection);
Tony Barbour25e3b832015-05-20 16:53:31 -06001090#endif
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001091}
1092
Tony Barbour01999182015-04-09 12:58:51 -06001093void VkTestFramework::Finish()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001094{
1095 if (m_images.size() == 0) return;
1096
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001097 vk_testing::Environment env;
1098 env.SetUp();
Tony Barbouref20d322015-02-25 12:28:39 -07001099 {
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001100 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbouref20d322015-02-25 12:28:39 -07001101
Jon Ashburncedc15f2015-05-21 18:13:33 -06001102 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001103 vkPresent.CreateMyWindow();
Ian Elliott338dedb2015-08-21 15:09:33 -06001104 vkPresent.CreateSwapchain();
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001105 vkPresent.Run();
1106 vkPresent.TearDown();
Tony Barbouref20d322015-02-25 12:28:39 -07001107 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +08001108 env.TearDown();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001109}
1110
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001111//
Courtney Goeltzenleuchter94192032014-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 Barbour01999182015-04-09 12:58:51 -06001215bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter94192032014-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 Barbour01999182015-04-09 12:58:51 -06001231void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter94192032014-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 Goeltzenleuchter358c76e2015-09-24 17:05:05 -06001245 config = (char *) alloca(strlen(DefaultConfig) + 1);
Courtney Goeltzenleuchter94192032014-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 Barbour01999182015-04-09 12:58:51 -06001453void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter94192032014-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 Barbour01999182015-04-09 12:58:51 -06001466char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter94192032014-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 Barbour01999182015-04-09 12:58:51 -06001529void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter94192032014-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 Barbour01999182015-04-09 12:58:51 -06001546EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter94192032014-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 Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001571// Convert VK shader type to compiler's
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001572//
Tony Barbour8205d902015-04-16 15:59:00 -06001573EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001574{
1575 switch (shader_type) {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001576 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001577 return EShLangVertex;
1578
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001579 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001580 return EShLangTessControl;
1581
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001582 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001583 return EShLangTessEvaluation;
1584
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001585 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001586 return EShLangGeometry;
1587
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001588 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001589 return EShLangFragment;
1590
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001591 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001592 return EShLangCompute;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001593
Chia-I Wubbdeacc2014-12-15 23:50:11 +08001594 default:
1595 return EShLangVertex;
1596 }
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001597}
1598
1599
1600//
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001601// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001602// Return value of false means an error was encountered.
1603//
Tony Barbour8205d902015-04-16 15:59:00 -06001604bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001605 const char *pshader,
Cody Northropeb9130e2015-06-03 13:01:54 -06001606 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001607{
Courtney Goeltzenleuchter358c76e2015-09-24 17:05:05 -06001608 glslang::TProgram program;
Courtney Goeltzenleuchter94192032014-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 Northropad306f02014-11-03 12:54:37 -07001628 if (! (m_compile_options & EOptionSuppressInfolog)) {
1629 puts(shader->getInfoLog());
1630 puts(shader->getInfoDebugLog());
1631 }
1632
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001633 return false; // something didn't work
1634 }
1635
1636 program.addShader(shader);
1637
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001638
1639 //
1640 // Program-level processing...
1641 //
1642
Cody Northropad306f02014-11-03 12:54:37 -07001643 if (! program.link(messages)) {
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001644
Cody Northropad306f02014-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 Goeltzenleuchter94192032014-10-03 09:53:32 -06001651 }
1652
1653 if (m_compile_options & EOptionDumpReflection) {
1654 program.buildReflection();
1655 program.dumpReflection();
1656 }
1657
Cody Northropeb9130e2015-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 Goeltzenleuchter358c76e2015-09-24 17:05:05 -06001675 delete shader;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001676
1677 return true;
1678}
1679
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001680
1681
Tony Barbour01999182015-04-09 12:58:51 -06001682VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001683 m_width( 0 ),
1684 m_height( 0 ),
Chia-I Wub2c2dea2014-12-15 23:29:34 +08001685 m_data( NULL ),
1686 m_data_size( 0 )
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001687{
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001688}
1689
Tony Barbour01999182015-04-09 12:58:51 -06001690VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001691{
1692
1693}
1694
Tony Barbour01999182015-04-09 12:58:51 -06001695VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchterd0d7ccc2014-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 Barbour01999182015-04-09 12:58:51 -06001704ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001705{
Tony Barbour01999182015-04-09 12:58:51 -06001706 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1707 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001708 return output;
1709}
1710
Tony Barbour01999182015-04-09 12:58:51 -06001711VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchterd0d7ccc2014-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001718 return *this;
1719}
1720
Tony Barbour01999182015-04-09 12:58:51 -06001721int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchterd0d7ccc2014-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 Barbour01999182015-04-09 12:58:51 -06001728int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001729{
1730 if( this->m_data_size < rhs.m_data_size ) return 1;
1731 return 0;
1732}
1733