blob: ab8020cb869c125d74247ebff1e53a611c6b899f [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>
Chia-I Wuf8693382015-04-16 22:02:10 +080030#include <xcb/xcb.h>
Ian Elliott7e40db92015-08-21 15:09:33 -060031#include "vk_ext_khr_swapchain.h"
32#include "vk_ext_khr_device_swapchain.h"
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060033
Tony Barbour3d69c9e2015-05-20 16:53:31 -060034#if defined(PATH_MAX) && !defined(MAX_PATH)
35#define MAX_PATH PATH_MAX
36#endif
37
Tony Barbour6a3faf02015-07-23 10:36:18 -060038#ifdef _WIN32
39#define ERR_EXIT(err_msg, err_class) \
40 do { \
41 MessageBox(NULL, err_msg, err_class, MB_OK); \
42 exit(1); \
43 } while (0)
44#else // _WIN32
45
46#define ERR_EXIT(err_msg, err_class) \
47 do { \
48 printf(err_msg); \
49 fflush(stdout); \
50 exit(1); \
51 } while (0)
52#endif // _WIN32
53
54#define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \
55{ \
56 m_fp##entrypoint = (PFN_vk##entrypoint) vkGetInstanceProcAddr(inst, "vk"#entrypoint); \
57 if (m_fp##entrypoint == NULL) { \
58 ERR_EXIT("vkGetInstanceProcAddr failed to find vk"#entrypoint, \
59 "vkGetInstanceProcAddr Failure"); \
60 } \
61}
62
63#define GET_DEVICE_PROC_ADDR(dev, entrypoint) \
64{ \
65 m_fp##entrypoint = (PFN_vk##entrypoint) vkGetDeviceProcAddr(dev, "vk"#entrypoint); \
66 if (m_fp##entrypoint == NULL) { \
67 ERR_EXIT("vkGetDeviceProcAddr failed to find vk"#entrypoint, \
68 "vkGetDeviceProcAddr Failure"); \
69 } \
70}
71
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060072// Command-line options
73enum TOptions {
74 EOptionNone = 0x000,
75 EOptionIntermediate = 0x001,
76 EOptionSuppressInfolog = 0x002,
77 EOptionMemoryLeakMode = 0x004,
78 EOptionRelaxedErrors = 0x008,
79 EOptionGiveWarnings = 0x010,
80 EOptionLinkProgram = 0x020,
81 EOptionMultiThreaded = 0x040,
82 EOptionDumpConfig = 0x080,
83 EOptionDumpReflection = 0x100,
84 EOptionSuppressWarnings = 0x200,
85 EOptionDumpVersions = 0x400,
Cody Northrop3bfd27c2015-03-17 15:55:58 -060086 EOptionSpv = 0x800,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060087 EOptionDefaultDesktop = 0x1000,
88};
89
Ian Elliott7e40db92015-08-21 15:09:33 -060090typedef struct _SwapchainBuffers {
Tony Barbour6a3faf02015-07-23 10:36:18 -060091 VkImage image;
92 VkCmdBuffer cmd;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -060093 VkImageView view;
Ian Elliott7e40db92015-08-21 15:09:33 -060094} SwapchainBuffers;
Tony Barbour6a3faf02015-07-23 10:36:18 -060095
Chia-I Wuf8693382015-04-16 22:02:10 +080096class TestFrameworkVkPresent
97{
98public:
99 TestFrameworkVkPresent(vk_testing::Device &device);
100
101 void Run();
Jon Ashburn07daee72015-05-21 18:13:33 -0600102 void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst);
Chia-I Wuf8693382015-04-16 22:02:10 +0800103 void CreateMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -0600104 void CreateSwapchain();
Chia-I Wuf8693382015-04-16 22:02:10 +0800105 void TearDown();
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600106#ifdef _WIN32
107 static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
108#endif
109
Chia-I Wuf8693382015-04-16 22:02:10 +0800110
111protected:
112 vk_testing::Device &m_device;
113 vk_testing::Queue &m_queue;
Dana Jansens233a0ea2015-07-30 13:04:16 -0700114 vk_testing::CmdPool m_cmdpool;
Chia-I Wuf8693382015-04-16 22:02:10 +0800115 vk_testing::CmdBuffer m_cmdbuf;
116
117private:
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600118#ifdef _WIN32
119 HINSTANCE m_connection; // hInstance - Windows Instance
120 HWND m_window; // hWnd - window handle
121
122#else
Chia-I Wuf8693382015-04-16 22:02:10 +0800123 xcb_connection_t *m_connection;
124 xcb_screen_t *m_screen;
125 xcb_window_t m_window;
126 xcb_intern_atom_reply_t *m_atom_wm_delete_window;
Ian Elliott7e40db92015-08-21 15:09:33 -0600127 VkPlatformHandleXcbKHR m_platform_handle_xcb;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600128#endif
Courtney Goeltzenleuchterd6079ec2015-04-22 10:09:35 -0600129 std::list<VkTestImageRecord> m_images;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600130 uint32_t m_present_queue_node_index;
Chia-I Wuf8693382015-04-16 22:02:10 +0800131
Ian Elliott7e40db92015-08-21 15:09:33 -0600132 PFN_vkGetPhysicalDeviceSurfaceSupportKHR m_fpGetPhysicalDeviceSurfaceSupportKHR;
133 PFN_vkGetSurfacePropertiesKHR m_fpGetSurfacePropertiesKHR;
134 PFN_vkGetSurfaceFormatsKHR m_fpGetSurfaceFormatsKHR;
135 PFN_vkGetSurfacePresentModesKHR m_fpGetSurfacePresentModesKHR;
136 PFN_vkCreateSwapchainKHR m_fpCreateSwapchainKHR;
137 PFN_vkDestroySwapchainKHR m_fpDestroySwapchainKHR;
138 PFN_vkGetSwapchainImagesKHR m_fpGetSwapchainImagesKHR;
139 PFN_vkAcquireNextImageKHR m_fpAcquireNextImageKHR;
140 PFN_vkQueuePresentKHR m_fpQueuePresentKHR;
141 VkSurfaceDescriptionWindowKHR m_surface_description;
142 uint32_t m_swapchainImageCount;
143 VkSwapchainKHR m_swap_chain;
144 SwapchainBuffers *m_buffers;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600145 VkFormat m_format;
Ian Elliott7e40db92015-08-21 15:09:33 -0600146 VkColorSpaceKHR m_color_space;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600147
148 uint32_t m_current_buffer;
Chia-I Wuf8693382015-04-16 22:02:10 +0800149
150 bool m_quit;
151 bool m_pause;
152
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600153 int m_width;
154 int m_height;
Chia-I Wuf8693382015-04-16 22:02:10 +0800155
156 std::list<VkTestImageRecord>::iterator m_display_image;
157
158 void Display();
159 void HandleEvent(xcb_generic_event_t *event);
160};
161
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600162#ifndef _WIN32
163
164#include <errno.h>
165
166int fopen_s(
167 FILE** pFile,
168 const char* filename,
169 const char* mode
170)
171{
172 if (!pFile || !filename || !mode) {
173 return EINVAL;
174 }
175
176 FILE* f = fopen(filename, mode);
177 if (! f) {
178 if (errno != 0) {
179 return errno;
180 } else {
181 return ENOENT;
182 }
183 }
184 *pFile = f;
185
186 return 0;
187}
188
189#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600190
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600191
192
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600193// Set up environment for GLSL compiler
194// Must be done once per process
195void TestEnvironment::SetUp()
196{
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600197 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600198 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800199
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600200 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600201}
202
203void TestEnvironment::TearDown()
204{
205 glslang::FinalizeProcess();
206}
207
Tony Barbour6918cd52015-04-09 12:58:51 -0600208VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600209 m_compile_options( 0 ),
210 m_num_shader_strings( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600211{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600212
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600213}
214
Tony Barbour6918cd52015-04-09 12:58:51 -0600215VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600216{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600217
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600218}
219
220// Define all the static elements
Cody Northropa3673cf2015-06-09 13:00:45 -0600221bool VkTestFramework::m_show_images = false;
222bool VkTestFramework::m_save_images = false;
223bool VkTestFramework::m_compare_images = false;
224bool VkTestFramework::m_use_glsl = false;
225bool VkTestFramework::m_canonicalize_spv = false;
226bool VkTestFramework::m_strip_spv = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600227bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour6918cd52015-04-09 12:58:51 -0600228int VkTestFramework::m_width = 0;
229int VkTestFramework::m_height = 0;
230std::list<VkTestImageRecord> VkTestFramework::m_images;
231std::list<VkTestImageRecord>::iterator VkTestFramework::m_display_image;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600232int m_display_image_idx = 0;
233
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600234bool VkTestFramework::optionMatch(const char* option, char* optionLine)
235{
236 if (strncmp(option, optionLine, strlen(option)) == 0)
237 return true;
238 else
239 return false;
240}
241
Tony Barbour6918cd52015-04-09 12:58:51 -0600242void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600243{
244 int i, n;
245
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600246 for (i=1, n=1; i< *argc; i++) {
247 if (optionMatch("--show-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600248 m_show_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600249 else if (optionMatch("--save-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600250 m_save_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600251 else if (optionMatch("--no-SPV", argv[i]))
252 m_use_glsl = true;
253 else if (optionMatch("--strip-SPV", argv[i]))
254 m_strip_spv = true;
255 else if (optionMatch("--canonicalize-SPV", argv[i]))
256 m_canonicalize_spv = true;
257 else if (optionMatch("--compare-images", argv[i]))
Tony Barbour247bf372014-10-30 14:29:04 -0600258 m_compare_images = true;
Tony Barbour247bf372014-10-30 14:29:04 -0600259
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600260 else if (optionMatch("--help", argv[i]) ||
261 optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700262 printf("\nOther options:\n");
263 printf("\t--show-images\n"
264 "\t\tDisplay test images in viewer after tests complete.\n");
265 printf("\t--save-images\n"
266 "\t\tSave tests images as ppm files in current working directory.\n"
267 "\t\tUsed to generate golden images for compare-images.\n");
268 printf("\t--compare-images\n"
269 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barboura98d3932014-12-11 09:52:49 -0700270 "\t\tAlso saves the generated test image in current working\n"
271 "\t\t\tdirectory but only if the image is different from the golden\n"
272 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
273 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700274 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600275 printf("\t--no-SPV\n"
276 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600277 printf("\t--strip-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600278 "\t\tStrip SPIR-V debug information (line numbers, names, etc).\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600279 printf("\t--canonicalize-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600280 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600281 exit(0);
282 } else {
283 printf("\nUnrecognized option: %s\n", argv[i]);
284 printf("\nUse --help or -h for option list.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700285 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700286 }
287
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600288 /*
289 * Since the above "consume" inputs, update argv
290 * so that it contains the trimmed list of args for glutInit
291 */
292
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600293 argv[n] = argv[i];
294 n++;
295 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600296}
297
Tony Barbour6918cd52015-04-09 12:58:51 -0600298void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600299{
300 string filename;
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600301 VkResult err;
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600302 uint32_t x, y;
Tony Barbour6918cd52015-04-09 12:58:51 -0600303 VkImageObj displayImage(image->device());
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600304 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbour84d448c2015-04-02 14:02:33 -0600305
Tony Barboure65788f2015-07-21 17:01:42 -0600306 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 -0600307 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600308
309 filename.append(basename);
310 filename.append(".ppm");
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600311
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600312 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600313 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600314 };
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600315 VkSubresourceLayout sr_layout;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600316
Tony Barbour59a47322015-06-24 16:06:58 -0600317 err = vkGetImageSubresourceLayout(image->device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600318 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600319
Tony Barbour84d448c2015-04-02 14:02:33 -0600320 char *ptr;
Chia-I Wu681d7a02015-07-03 13:44:34 +0800321 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600322 ptr += sr_layout.offset;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600323 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600324 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
325
326 file << "P6\n";
Tony Barbour84d448c2015-04-02 14:02:33 -0600327 file << displayImage.width() << "\n";
328 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600329 file << 255 << "\n";
330
Tony Barbour84d448c2015-04-02 14:02:33 -0600331 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700332 const int *row = (const int *) ptr;
333 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600334
Tony Barbourd1c35722015-04-16 15:59:00 -0600335 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700336 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600337 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700338 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
339 file.write((char *) &swapped, 3);
340 row++;
341 }
342 }
Tony Barbourd1c35722015-04-16 15:59:00 -0600343 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700344 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600345 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700346 file.write((char *) row, 3);
347 row++;
348 }
349 }
350 else {
351 printf("Unrecognized image format - will not write image files");
352 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600353 }
354
355 ptr += sr_layout.rowPitch;
356 }
357
358 file.close();
Chia-I Wu681d7a02015-07-03 13:44:34 +0800359 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600360}
361
Tony Barbour6918cd52015-04-09 12:58:51 -0600362void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour247bf372014-10-30 14:29:04 -0600363{
364
365 MagickWand *magick_wand_1;
366 MagickWand *magick_wand_2;
367 MagickWand *compare_wand;
368 MagickBooleanType status;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600369 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600370 double differenz;
371
Tony Barbour4ab45422014-12-10 17:00:20 -0700372 if (getenv("RENDERTEST_GOLDEN_DIR"))
373 {
374 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
375 }
376
Tony Barbour247bf372014-10-30 14:29:04 -0600377 MagickWandGenesis();
378 magick_wand_1=NewMagickWand();
379 sprintf(testimage,"%s.ppm",basename);
380 status=MagickReadImage(magick_wand_1,testimage);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600381 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour247bf372014-10-30 14:29:04 -0600382
383
384 MagickWandGenesis();
385 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700386 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600387 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600388 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour247bf372014-10-30 14:29:04 -0600389
Tony Barbour247bf372014-10-30 14:29:04 -0600390 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
391 if (differenz != 0.0)
392 {
393 char difference[256];
394
395 sprintf(difference,"%s-diff.ppm",basename);
396 status = MagickWriteImage(compare_wand, difference);
397 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
398 }
399 DestroyMagickWand(compare_wand);
400
401 DestroyMagickWand(magick_wand_1);
402 DestroyMagickWand(magick_wand_2);
403 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700404
405 if (differenz == 0.0)
406 {
407 /*
408 * If test image and golden image match, we do not need to
409 * keep around the test image.
410 */
411 remove(testimage);
412 }
Tony Barbour247bf372014-10-30 14:29:04 -0600413}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600414
Tony Barbour6918cd52015-04-09 12:58:51 -0600415void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600416{
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600417 VkResult err;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600418 VkSubresourceLayout sr_layout;
419 char *ptr;
420 VkTestImageRecord record;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600421 VkImageObj displayImage(image->device());
422 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
423
Cody Northropc9a69912015-06-18 17:05:15 -0600424 displayImage.init(image->extent().width, image->extent().height, image->format(), VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT, VK_IMAGE_TILING_LINEAR, reqs);
425
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600426 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600427
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600428 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600429 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600430 };
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600431
Tony Barbour59a47322015-06-24 16:06:58 -0600432 err = vkGetImageSubresourceLayout(displayImage.device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600433 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600434
Chia-I Wu681d7a02015-07-03 13:44:34 +0800435 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600436 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600437
438 ptr += sr_layout.offset;
439
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600440 record.m_title.append(comment);
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600441 record.m_width = displayImage.width();
442 record.m_height = displayImage.height();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600443 // TODO: Need to make this more robust to handle different image formats
Tony-LunarG399dfca2015-05-19 14:08:26 -0600444 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600445 record.m_data = malloc(record.m_data_size);
446 memcpy(record.m_data, ptr, record.m_data_size);
447 m_images.push_back(record);
448 m_display_image = --m_images.end();
449
Chia-I Wu681d7a02015-07-03 13:44:34 +0800450 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600451}
452
Tony Barbour6918cd52015-04-09 12:58:51 -0600453void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600454{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600455 for (int32_t i = 0; i < images.size(); i++) {
456 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600457 }
458}
459
Tony Barbour6918cd52015-04-09 12:58:51 -0600460void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600461{
462 const ::testing::TestInfo* const test_info =
463 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600464 ostringstream filestream;
465 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600466
Tony Barbour247bf372014-10-30 14:29:04 -0600467 m_width = 40;
468
469 if (strcmp(test_info->name(), m_testName.c_str())) {
470 filestream << test_info->name();
471 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700472 m_frameNum = 2;
473 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600474 }
475 else {
476 filestream << test_info->name() << "-" << m_frameNum;
477 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700478 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600479 }
480
Tony Barbour247bf372014-10-30 14:29:04 -0600481 // ToDo - scrub string for bad characters
482
483 if (m_save_images || m_compare_images) {
484 WritePPM(filename.c_str(), image);
485 if (m_compare_images) {
486 Compare(filename.c_str(), image);
487 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600488 }
489
490 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600491 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600492 }
493}
494
Chia-I Wuf8693382015-04-16 22:02:10 +0800495TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
496 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700497 m_queue(*m_device.graphics_queues()[0]),
Dana Jansens233a0ea2015-07-30 13:04:16 -0700498 m_cmdpool(m_device, vk_testing::CmdPool::create_info(m_device.graphics_queue_node_index_)),
499 m_cmdbuf(m_device, vk_testing::CmdBuffer::create_info(m_cmdpool.handle()))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600500{
Tony Barbour96db8822015-02-25 12:28:39 -0700501 m_quit = false;
502 m_pause = false;
503 m_width = 0;
504 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600505}
506
Tony Barbour6918cd52015-04-09 12:58:51 -0600507void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600508{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600509 VkResult U_ASSERT_ONLY err;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600510 vk_testing::Buffer buf;
511 void *dest_ptr;
512
Tony Barbour6a3faf02015-07-23 10:36:18 -0600513 VkSemaphore presentCompleteSemaphore;
514 VkSemaphoreCreateInfo presentCompleteSemaphoreCreateInfo = {};
515 presentCompleteSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
516 presentCompleteSemaphoreCreateInfo.pNext = NULL;
517 presentCompleteSemaphoreCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
518
519
520 err = vkCreateSemaphore(m_device.handle(),
521 &presentCompleteSemaphoreCreateInfo,
522 &presentCompleteSemaphore);
523 assert(!err);
524
525 // Get the index of the next available swapchain image:
Ian Elliott7e40db92015-08-21 15:09:33 -0600526 err = m_fpAcquireNextImageKHR(m_device.handle(), m_swap_chain,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600527 UINT64_MAX,
528 presentCompleteSemaphore,
529 &m_current_buffer);
Ian Elliott7e40db92015-08-21 15:09:33 -0600530 // TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
Tony Barbour6a3faf02015-07-23 10:36:18 -0600531 // return codes
532 assert(!err);
533
534 // Wait for the present complete semaphore to be signaled to ensure
535 // that the image won't be rendered to until the presentation
536 // engine has fully released ownership to the application, and it is
537 // okay to render to the image.
538 vkQueueWaitSemaphore(m_queue.handle(), presentCompleteSemaphore);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600539
540 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Cody Northrop7fb43862015-06-22 14:56:14 -0600541 buf.init_as_src(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800542 dest_ptr = buf.memory().map();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600543 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800544 buf.memory().unmap();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600545
546 m_cmdbuf.begin();
547
548 VkBufferImageCopy region = {};
549 region.imageExtent.height = m_display_image->m_height;
550 region.imageExtent.width = m_display_image->m_width;
551 region.imageExtent.depth = 1;
552
Chia-I Wube2b9172015-07-03 11:49:42 +0800553 vkCmdCopyBufferToImage(m_cmdbuf.handle(),
Chia-I Wu681d7a02015-07-03 13:44:34 +0800554 buf.handle(),
Tony Barbour6a3faf02015-07-23 10:36:18 -0600555 m_buffers[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600556 1, &region);
557 m_cmdbuf.end();
558
559 VkCmdBuffer cmdBufs[1];
Chia-I Wube2b9172015-07-03 11:49:42 +0800560 cmdBufs[0] = m_cmdbuf.handle();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600561
Tony Barbour67e99152015-07-10 14:10:27 -0600562 VkFence nullFence = { VK_NULL_HANDLE };
563 vkQueueSubmit(m_queue.handle(), 1, cmdBufs, nullFence);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600564 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700565
Ian Elliott7e40db92015-08-21 15:09:33 -0600566 VkPresentInfoKHR present = {};
567 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600568 present.pNext = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600569 present.swapchainCount = 1;
570 present.swapchains = & m_swap_chain;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600571 present.imageIndices = &m_current_buffer;
Tony Barbour96db8822015-02-25 12:28:39 -0700572
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600573#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800574 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700575 XCB_PROP_MODE_REPLACE,
576 m_window,
577 XCB_ATOM_WM_NAME,
578 XCB_ATOM_STRING,
579 8,
580 m_display_image->m_title.size(),
581 m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600582#endif
Jon Ashburn07daee72015-05-21 18:13:33 -0600583
Ian Elliott7e40db92015-08-21 15:09:33 -0600584 err = m_fpQueuePresentKHR(m_queue.handle(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700585 assert(!err);
586
587 m_queue.wait();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600588 m_current_buffer = (m_current_buffer + 1) % 2;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600589}
590
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600591#ifdef _WIN32
Tony-LunarG399dfca2015-05-19 14:08:26 -0600592# define PREVIOUSLY_DOWN 1<<29
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600593// MS-Windows event handling function:
594LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
595 UINT uMsg,
596 WPARAM wParam,
597 LPARAM lParam)
598{
599
600 switch(uMsg)
601 {
602 case WM_CLOSE:
603 PostQuitMessage(0);
604 break;
605
606 case WM_PAINT:
607 {
608 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
609 if (me) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600610 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600611 me->Display();
612 }
613 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600614 break;
615
616 case WM_KEYDOWN:
617 {
618 if (lParam & (PREVIOUSLY_DOWN)){
619 break;
620 }
621 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
622 // the window, we put the this pointer into the window's user data so we could get it back now
623 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
624 switch (wParam)
625 {
626 case VK_ESCAPE: me->m_quit = true;
627 break;
628
629 case VK_LEFT: // left arrow key
630 if (me->m_display_image == me->m_images.begin()) {
631 me->m_display_image = --me->m_images.end();
632 }
633 else {
634 --me->m_display_image;
635 }
636 break;
637
638 case VK_RIGHT: // right arrow key
639 ++me->m_display_image;
640 if (me->m_display_image == me->m_images.end()) {
641 me->m_display_image = me->m_images.begin();
642 }
643 break;
644
645 default:
646 break;
647 }
648 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
649 me->Display();
650 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600651 }
652 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
653}
654
655void TestFrameworkVkPresent::Run()
656{
657 MSG msg; // message
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600658
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600659 /* main message loop*/
Tony-LunarG399dfca2015-05-19 14:08:26 -0600660 while(! m_quit) {
661 GetMessage(&msg, m_window, 0, 0);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600662 if (msg.message == WM_QUIT) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600663 m_quit = true; //if found, quit app
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600664 } else {
665 /* Translate and dispatch to event queue*/
666 TranslateMessage(&msg);
667 DispatchMessage(&msg);
668 }
669 }
670}
671
672#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600673void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600674{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600675 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700676 switch (event_code) {
677 case XCB_EXPOSE:
678 Display(); // TODO: handle resize
679 break;
680 case XCB_CLIENT_MESSAGE:
681 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
682 (m_atom_wm_delete_window)->atom) {
683 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600684 }
685 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700686 case XCB_KEY_RELEASE:
687 {
688 const xcb_key_release_event_t *key =
689 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600690
Tony Barbour96db8822015-02-25 12:28:39 -0700691 switch (key->detail) {
692 case 0x9: // Escape
693 m_quit = true;
694 break;
695 case 0x71: // left arrow key
696 if (m_display_image == m_images.begin()) {
697 m_display_image = --m_images.end();
698 } else {
699 --m_display_image;
700 }
701 break;
702 case 0x72: // right arrow key
703 ++m_display_image;
704 if (m_display_image == m_images.end()) {
705 m_display_image = m_images.begin();
706 }
707 break;
708 case 0x41:
709 m_pause = !m_pause;
710 break;
711 }
712 Display();
713 }
714 break;
715 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600716 break;
717 }
Tony Barbour96db8822015-02-25 12:28:39 -0700718}
719
Tony Barbour6918cd52015-04-09 12:58:51 -0600720void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700721{
Chia-I Wuf8693382015-04-16 22:02:10 +0800722 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700723
724 while (! m_quit) {
725 xcb_generic_event_t *event;
726
727 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800728 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700729 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800730 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700731 }
732 if (event) {
733 HandleEvent(event);
734 free(event);
735 }
736 }
737}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600738#endif // _WIN32
Tony Barbour96db8822015-02-25 12:28:39 -0700739
Ian Elliott7e40db92015-08-21 15:09:33 -0600740void TestFrameworkVkPresent::CreateSwapchain()
Tony Barbour96db8822015-02-25 12:28:39 -0700741{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600742 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700743
Tony-LunarG399dfca2015-05-19 14:08:26 -0600744 m_display_image = m_images.begin();
745 m_current_buffer = 0;
746
Tony Barbour6a3faf02015-07-23 10:36:18 -0600747 // Construct the WSI surface description:
Ian Elliott7e40db92015-08-21 15:09:33 -0600748 m_surface_description.sType = VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600749 m_surface_description.pNext = NULL;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600750#ifdef _WIN32
Ian Elliott7e40db92015-08-21 15:09:33 -0600751 m_surface_description.platform = VK_PLATFORM_WIN32_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600752 m_surface_description.pPlatformHandle = m_connection;
753 m_surface_description.pPlatformWindow = m_window;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600754#else // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -0600755 m_platform_handle_xcb.connection = m_connection;
756 m_platform_handle_xcb.root = m_screen->root;
Ian Elliott7e40db92015-08-21 15:09:33 -0600757 m_surface_description.platform = VK_PLATFORM_XCB_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600758 m_surface_description.pPlatformHandle = &m_platform_handle_xcb;
759 m_surface_description.pPlatformWindow = &m_window;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600760#endif // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -0600761
762 // Iterate over each queue to learn whether it supports presenting to WSI:
763 VkBool32 supportsPresent;
764 m_present_queue_node_index = UINT32_MAX;
765 std::vector<vk_testing::Queue *> queues = m_device.graphics_queues();
766 for (int i=0; i < queues.size(); i++)
767 {
768 int family_index = queues[i]->get_family_index();
Ian Elliott7e40db92015-08-21 15:09:33 -0600769 m_fpGetPhysicalDeviceSurfaceSupportKHR(m_device.phy().handle(),
Tony Barbour6a3faf02015-07-23 10:36:18 -0600770 family_index,
Ian Elliott7e40db92015-08-21 15:09:33 -0600771 (VkSurfaceDescriptionKHR *) &m_surface_description,
Tony Barbour6a3faf02015-07-23 10:36:18 -0600772 &supportsPresent);
773 if (supportsPresent) {
774 m_present_queue_node_index = family_index;
775 }
776 }
777
778 assert(m_present_queue_node_index != UINT32_MAX);
779
780
781 // Get the list of VkFormat's that are supported:
Ian Elliott8b139792015-08-07 11:51:12 -0600782 uint32_t formatCount;
Ian Elliott7e40db92015-08-21 15:09:33 -0600783 err = m_fpGetSurfaceFormatsKHR(m_device.handle(),
784 (VkSurfaceDescriptionKHR *) &m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600785 &formatCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600786 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600787 VkSurfaceFormatKHR *surfFormats =
788 (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
789 err = m_fpGetSurfaceFormatsKHR(m_device.handle(),
790 (VkSurfaceDescriptionKHR *) &m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600791 &formatCount, surfFormats);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600792 assert(!err);
793 // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
794 // the surface has no preferred format. Otherwise, at least one
795 // supported format will be returned.
Tony Barbour6a3faf02015-07-23 10:36:18 -0600796 if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED)
797 {
798 m_format = VK_FORMAT_B8G8R8A8_UNORM;
799 }
800 else
801 {
802 assert(formatCount >= 1);
803 m_format = surfFormats[0].format;
804 }
Ian Elliott8b139792015-08-07 11:51:12 -0600805 m_color_space = surfFormats[0].colorSpace;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600806
807 // Check the surface proprties and formats
Ian Elliott7e40db92015-08-21 15:09:33 -0600808 VkSurfacePropertiesKHR surfProperties;
809 err = m_fpGetSurfacePropertiesKHR(m_device.handle(),
810 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600811 &surfProperties);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600812 assert(!err);
813
Ian Elliott8b139792015-08-07 11:51:12 -0600814 uint32_t presentModeCount;
Ian Elliott7e40db92015-08-21 15:09:33 -0600815 err = m_fpGetSurfacePresentModesKHR(m_device.handle(),
816 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600817 &presentModeCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600818 assert(!err);
Ian Elliott7e40db92015-08-21 15:09:33 -0600819 VkPresentModeKHR *presentModes =
820 (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
Ian Elliott8b139792015-08-07 11:51:12 -0600821 assert(presentModes);
Ian Elliott7e40db92015-08-21 15:09:33 -0600822 err = m_fpGetSurfacePresentModesKHR(m_device.handle(),
823 (const VkSurfaceDescriptionKHR *)&m_surface_description,
Ian Elliott8b139792015-08-07 11:51:12 -0600824 &presentModeCount, presentModes);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600825 assert(!err);
826
Ian Elliott7e40db92015-08-21 15:09:33 -0600827 VkExtent2D swapchainExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600828 // width and height are either both -1, or both not -1.
Ian Elliott8b139792015-08-07 11:51:12 -0600829 if (surfProperties.currentExtent.width == -1)
Tony Barbour6a3faf02015-07-23 10:36:18 -0600830 {
831 // If the surface size is undefined, the size is set to
832 // the size of the images requested.
Ian Elliott7e40db92015-08-21 15:09:33 -0600833 swapchainExtent.width = m_width;
834 swapchainExtent.height = m_height;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600835 }
836 else
837 {
838 // If the surface size is defined, the swap chain size must match
Ian Elliott7e40db92015-08-21 15:09:33 -0600839 swapchainExtent = surfProperties.currentExtent;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600840 }
841
842 // If mailbox mode is available, use it, as is the lowest-latency non-
Ian Elliottae0e8242015-08-10 13:20:49 -0600843 // tearing mode. If not, try IMMEDIATE which will usually be available,
844 // and is fastest (though it tears). If not, fall back to FIFO which is
845 // always available.
Ian Elliott7e40db92015-08-21 15:09:33 -0600846 VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600847 for (size_t i = 0; i < presentModeCount; i++) {
Ian Elliott7e40db92015-08-21 15:09:33 -0600848 if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
849 swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600850 break;
851 }
Ian Elliott7e40db92015-08-21 15:09:33 -0600852 if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) &&
853 (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
854 swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
Ian Elliottae0e8242015-08-10 13:20:49 -0600855 }
Tony Barbour6a3faf02015-07-23 10:36:18 -0600856 }
857
858 // Determine the number of VkImage's to use in the swap chain (we desire to
859 // own only 1 image at a time, besides the images being displayed and
860 // queued for display):
Ian Elliott7e40db92015-08-21 15:09:33 -0600861 uint32_t desiredNumberOfSwapchainImages = surfProperties.minImageCount + 1;
Ian Elliott8b139792015-08-07 11:51:12 -0600862 if ((surfProperties.maxImageCount > 0) &&
Ian Elliott7e40db92015-08-21 15:09:33 -0600863 (desiredNumberOfSwapchainImages > surfProperties.maxImageCount))
Tony Barbour6a3faf02015-07-23 10:36:18 -0600864 {
865 // Application must settle for fewer images than desired:
Ian Elliott7e40db92015-08-21 15:09:33 -0600866 desiredNumberOfSwapchainImages = surfProperties.maxImageCount;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600867 }
868
Ian Elliott7e40db92015-08-21 15:09:33 -0600869 VkSurfaceTransformKHR preTransform;
870 if (surfProperties.supportedTransforms & VK_SURFACE_TRANSFORM_NONE_BIT_KHR) {
871 preTransform = VK_SURFACE_TRANSFORM_NONE_KHR;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600872 } else {
Ian Elliott8b139792015-08-07 11:51:12 -0600873 preTransform = surfProperties.currentTransform;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600874 }
Ian Elliott1a3845b2015-07-06 14:33:04 -0600875
Cody Northropdf5b0922015-08-28 16:22:48 -0600876 // We want to blit to the swap chain, ensure the driver supports it. Color is always supported, per WSI spec.
877 assert((surfProperties.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT) != 0);
878
Ian Elliott7e40db92015-08-21 15:09:33 -0600879 VkSwapchainCreateInfoKHR swap_chain = {};
880 swap_chain.sType = VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_KHR;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600881 swap_chain.pNext = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600882 swap_chain.pSurfaceDescription = (const VkSurfaceDescriptionKHR *)&m_surface_description;
883 swap_chain.minImageCount = desiredNumberOfSwapchainImages;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600884 swap_chain.imageFormat = m_format;
Ian Elliott8b139792015-08-07 11:51:12 -0600885 swap_chain.imageColorSpace = m_color_space;
Ian Elliott7e40db92015-08-21 15:09:33 -0600886 swap_chain.imageExtent.width = swapchainExtent.width;
887 swap_chain.imageExtent.height = swapchainExtent.height;
Cody Northropdf8f42a2015-08-05 15:38:39 -0600888 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT |
889 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600890 swap_chain.preTransform = preTransform;
Chia-I Wuf8693382015-04-16 22:02:10 +0800891 swap_chain.imageArraySize = 1;
Ian Elliott8b139792015-08-07 11:51:12 -0600892 swap_chain.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
893 swap_chain.queueFamilyCount = 0;
894 swap_chain.pQueueFamilyIndices = NULL;
Ian Elliott7e40db92015-08-21 15:09:33 -0600895 swap_chain.presentMode = swapchainPresentMode;
896 swap_chain.oldSwapchain.handle = 0;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600897 swap_chain.clipped = true;
898
899 uint32_t i;
Chia-I Wuf8693382015-04-16 22:02:10 +0800900
Ian Elliott7e40db92015-08-21 15:09:33 -0600901 err = m_fpCreateSwapchainKHR(m_device.handle(), &swap_chain, &m_swap_chain);
Chia-I Wuf8693382015-04-16 22:02:10 +0800902 assert(!err);
903
Ian Elliott7e40db92015-08-21 15:09:33 -0600904 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
905 &m_swapchainImageCount, NULL);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600906 assert(!err);
907
Ian Elliott7e40db92015-08-21 15:09:33 -0600908 VkImage* swapchainImages = (VkImage*)malloc(m_swapchainImageCount * sizeof(VkImage));
909 assert(swapchainImages);
910 err = m_fpGetSwapchainImagesKHR(m_device.handle(), m_swap_chain,
911 &m_swapchainImageCount, swapchainImages);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600912 assert(!err);
913
Ian Elliott7e40db92015-08-21 15:09:33 -0600914 m_buffers = (SwapchainBuffers*)malloc(sizeof(SwapchainBuffers)*m_swapchainImageCount);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600915 assert(m_buffers);
916
Ian Elliott7e40db92015-08-21 15:09:33 -0600917 for (i = 0; i < m_swapchainImageCount; i++) {
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600918 VkImageViewCreateInfo color_image_view = {};
919 color_image_view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
920 color_image_view.pNext = NULL;
921 color_image_view.format = m_format;
Courtney Goeltzenleuchterda894a22015-09-02 12:56:41 -0600922 color_image_view.subresourceRange.aspect = VK_IMAGE_ASPECT_COLOR;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600923 color_image_view.subresourceRange.baseMipLevel = 0;
924 color_image_view.subresourceRange.mipLevels = 1;
Courtney Goeltzenleuchter4a261892015-09-10 16:38:41 -0600925 color_image_view.subresourceRange.baseArrayLayer = 0;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600926 color_image_view.subresourceRange.arraySize = 1;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600927
Ian Elliott7e40db92015-08-21 15:09:33 -0600928 m_buffers[i].image = swapchainImages[i];
Tony Barbour6a3faf02015-07-23 10:36:18 -0600929
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600930 color_image_view.image = m_buffers[i].image;
931 err = vkCreateImageView(m_device.handle(),
932 &color_image_view, &m_buffers[i].view);
Tony Barbour6a3faf02015-07-23 10:36:18 -0600933 assert(!err);
934 }
Tony Barbour96db8822015-02-25 12:28:39 -0700935}
936
Jon Ashburn07daee72015-05-21 18:13:33 -0600937void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -0700938{
Ian Elliott7e40db92015-08-21 15:09:33 -0600939 GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfaceSupportKHR);
940 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfacePropertiesKHR);
941 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfaceFormatsKHR);
942 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSurfacePresentModesKHR);
943 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
944 GET_DEVICE_PROC_ADDR(m_device.handle(), CreateSwapchainKHR);
945 GET_DEVICE_PROC_ADDR(m_device.handle(), DestroySwapchainKHR);
946 GET_DEVICE_PROC_ADDR(m_device.handle(), GetSwapchainImagesKHR);
947 GET_DEVICE_PROC_ADDR(m_device.handle(), AcquireNextImageKHR);
948 GET_DEVICE_PROC_ADDR(m_device.handle(), QueuePresentKHR);
Jon Ashburn07daee72015-05-21 18:13:33 -0600949
Tony Barbour96db8822015-02-25 12:28:39 -0700950 m_images = imagesIn;
951}
952
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600953#ifdef _WIN32
954void TestFrameworkVkPresent::CreateMyWindow()
955{
956 WNDCLASSEX win_class;
957 // const ::testing::TestInfo* const test_info =
958 // ::testing::UnitTest::GetInstance()->current_test_info();
959 m_connection = GetModuleHandle(NULL);
960
961 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
962 it != m_images.end(); it++) {
963 if (m_width < it->m_width)
964 m_width = it->m_width;
965 if (m_height < it->m_height)
966 m_height = it->m_height;
967 }
968 // Initialize the window class structure:
969 win_class.cbSize = sizeof(WNDCLASSEX);
970 win_class.style = CS_HREDRAW | CS_VREDRAW;
971 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
972 win_class.cbClsExtra = 0;
973 win_class.cbWndExtra = 0;
974 win_class.hInstance = m_connection; // hInstance
975 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
976 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
977 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
978 win_class.lpszMenuName = NULL;
979 win_class.lpszClassName = "Test";
980 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
981 // Register window class:
982 if (!RegisterClassEx(&win_class)) {
983 // It didn't work, so try to give a useful error:
984 printf("Unexpected error trying to start the application!\n");
985 fflush(stdout);
986 exit(1);
987 }
988 // Create window with the registered class:
Cody Northrop39582252015-08-05 15:39:31 -0600989 RECT wr = { 0, 0, m_width, m_height };
990 AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600991 m_window = CreateWindowEx(0,
992 "Test", // class name
993 "Test", // app name
994 WS_OVERLAPPEDWINDOW | // window style
995 WS_VISIBLE |
996 WS_SYSMENU,
997 100,100, // x/y coords
Cody Northrop39582252015-08-05 15:39:31 -0600998 wr.right - wr.left, // width
999 wr.bottom - wr.top, // height
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001000 NULL, // handle to parent
1001 NULL, // handle to menu
1002 m_connection, // hInstance
1003 NULL); // no extra parameters
1004
1005 if (!m_window) {
1006 // It didn't work, so try to give a useful error:
1007 DWORD error = GetLastError();
1008 char message[120];
1009 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
1010 MessageBox(NULL, message, "Error", MB_OK);
1011 exit(1);
1012 }
Tony-LunarG399dfca2015-05-19 14:08:26 -06001013 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
1014 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001015}
1016#else
Tony Barbour6918cd52015-04-09 12:58:51 -06001017void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -07001018{
Chia-I Wuf8693382015-04-16 22:02:10 +08001019 const xcb_setup_t *setup;
1020 xcb_screen_iterator_t iter;
1021 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -07001022 uint32_t value_mask, value_list[32];
1023
Chia-I Wuf8693382015-04-16 22:02:10 +08001024 m_connection = xcb_connect(NULL, &scr);
1025
1026 setup = xcb_get_setup(m_connection);
1027 iter = xcb_setup_roots_iterator(setup);
1028 while (scr-- > 0)
1029 xcb_screen_next(&iter);
1030
1031 m_screen = iter.data;
1032
1033 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
1034 it != m_images.end(); it++) {
1035 if (m_width < it->m_width)
1036 m_width = it->m_width;
1037 if (m_height < it->m_height)
1038 m_height = it->m_height;
1039 }
1040
1041 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -07001042
1043 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +08001044 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -07001045 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
1046 XCB_EVENT_MASK_EXPOSURE |
1047 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
1048
Chia-I Wuf8693382015-04-16 22:02:10 +08001049 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -07001050 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001051 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -07001052 0, 0, m_width, m_height, 0,
1053 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +08001054 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -07001055 value_mask, value_list);
1056
1057 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +08001058 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -07001059 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +08001060 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001061
Chia-I Wuf8693382015-04-16 22:02:10 +08001062 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
1063 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -07001064
Chia-I Wuf8693382015-04-16 22:02:10 +08001065 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -07001066 m_window, (*reply).atom, 4, 32, 1,
1067 &(*m_atom_wm_delete_window).atom);
1068 free(reply);
1069
Chia-I Wuf8693382015-04-16 22:02:10 +08001070 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -07001071}
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001072#endif
Tony Barbour96db8822015-02-25 12:28:39 -07001073
Tony Barbour6918cd52015-04-09 12:58:51 -06001074void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -07001075{
Ian Elliott7e40db92015-08-21 15:09:33 -06001076 m_fpDestroySwapchainKHR(m_device.handle(), m_swap_chain);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001077#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +08001078 xcb_destroy_window(m_connection, m_window);
1079 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -06001080#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001081}
1082
Tony Barbour6918cd52015-04-09 12:58:51 -06001083void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001084{
1085 if (m_images.size() == 0) return;
1086
Chia-I Wuf8693382015-04-16 22:02:10 +08001087 vk_testing::Environment env;
1088 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -07001089 {
Chia-I Wuf8693382015-04-16 22:02:10 +08001090 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -07001091
Jon Ashburn07daee72015-05-21 18:13:33 -06001092 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001093 vkPresent.CreateMyWindow();
Ian Elliott7e40db92015-08-21 15:09:33 -06001094 vkPresent.CreateSwapchain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001095 vkPresent.Run();
1096 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -07001097 }
Chia-I Wuf8693382015-04-16 22:02:10 +08001098 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001099}
1100
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001101//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001102// These are the default resources for TBuiltInResources, used for both
1103// - parsing this string for the case where the user didn't supply one
1104// - dumping out a template for user construction of a config file
1105//
1106static const char* DefaultConfig =
1107 "MaxLights 32\n"
1108 "MaxClipPlanes 6\n"
1109 "MaxTextureUnits 32\n"
1110 "MaxTextureCoords 32\n"
1111 "MaxVertexAttribs 64\n"
1112 "MaxVertexUniformComponents 4096\n"
1113 "MaxVaryingFloats 64\n"
1114 "MaxVertexTextureImageUnits 32\n"
1115 "MaxCombinedTextureImageUnits 80\n"
1116 "MaxTextureImageUnits 32\n"
1117 "MaxFragmentUniformComponents 4096\n"
1118 "MaxDrawBuffers 32\n"
1119 "MaxVertexUniformVectors 128\n"
1120 "MaxVaryingVectors 8\n"
1121 "MaxFragmentUniformVectors 16\n"
1122 "MaxVertexOutputVectors 16\n"
1123 "MaxFragmentInputVectors 15\n"
1124 "MinProgramTexelOffset -8\n"
1125 "MaxProgramTexelOffset 7\n"
1126 "MaxClipDistances 8\n"
1127 "MaxComputeWorkGroupCountX 65535\n"
1128 "MaxComputeWorkGroupCountY 65535\n"
1129 "MaxComputeWorkGroupCountZ 65535\n"
1130 "MaxComputeWorkGroupSizeX 1024\n"
1131 "MaxComputeWorkGroupSizeY 1024\n"
1132 "MaxComputeWorkGroupSizeZ 64\n"
1133 "MaxComputeUniformComponents 1024\n"
1134 "MaxComputeTextureImageUnits 16\n"
1135 "MaxComputeImageUniforms 8\n"
1136 "MaxComputeAtomicCounters 8\n"
1137 "MaxComputeAtomicCounterBuffers 1\n"
1138 "MaxVaryingComponents 60\n"
1139 "MaxVertexOutputComponents 64\n"
1140 "MaxGeometryInputComponents 64\n"
1141 "MaxGeometryOutputComponents 128\n"
1142 "MaxFragmentInputComponents 128\n"
1143 "MaxImageUnits 8\n"
1144 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
1145 "MaxCombinedShaderOutputResources 8\n"
1146 "MaxImageSamples 0\n"
1147 "MaxVertexImageUniforms 0\n"
1148 "MaxTessControlImageUniforms 0\n"
1149 "MaxTessEvaluationImageUniforms 0\n"
1150 "MaxGeometryImageUniforms 0\n"
1151 "MaxFragmentImageUniforms 8\n"
1152 "MaxCombinedImageUniforms 8\n"
1153 "MaxGeometryTextureImageUnits 16\n"
1154 "MaxGeometryOutputVertices 256\n"
1155 "MaxGeometryTotalOutputComponents 1024\n"
1156 "MaxGeometryUniformComponents 1024\n"
1157 "MaxGeometryVaryingComponents 64\n"
1158 "MaxTessControlInputComponents 128\n"
1159 "MaxTessControlOutputComponents 128\n"
1160 "MaxTessControlTextureImageUnits 16\n"
1161 "MaxTessControlUniformComponents 1024\n"
1162 "MaxTessControlTotalOutputComponents 4096\n"
1163 "MaxTessEvaluationInputComponents 128\n"
1164 "MaxTessEvaluationOutputComponents 128\n"
1165 "MaxTessEvaluationTextureImageUnits 16\n"
1166 "MaxTessEvaluationUniformComponents 1024\n"
1167 "MaxTessPatchComponents 120\n"
1168 "MaxPatchVertices 32\n"
1169 "MaxTessGenLevel 64\n"
1170 "MaxViewports 16\n"
1171 "MaxVertexAtomicCounters 0\n"
1172 "MaxTessControlAtomicCounters 0\n"
1173 "MaxTessEvaluationAtomicCounters 0\n"
1174 "MaxGeometryAtomicCounters 0\n"
1175 "MaxFragmentAtomicCounters 8\n"
1176 "MaxCombinedAtomicCounters 8\n"
1177 "MaxAtomicCounterBindings 1\n"
1178 "MaxVertexAtomicCounterBuffers 0\n"
1179 "MaxTessControlAtomicCounterBuffers 0\n"
1180 "MaxTessEvaluationAtomicCounterBuffers 0\n"
1181 "MaxGeometryAtomicCounterBuffers 0\n"
1182 "MaxFragmentAtomicCounterBuffers 1\n"
1183 "MaxCombinedAtomicCounterBuffers 1\n"
1184 "MaxAtomicCounterBufferSize 16384\n"
1185 "MaxTransformFeedbackBuffers 4\n"
1186 "MaxTransformFeedbackInterleavedComponents 64\n"
1187 "MaxCullDistances 8\n"
1188 "MaxCombinedClipAndCullDistances 8\n"
1189 "MaxSamples 4\n"
1190
1191 "nonInductiveForLoops 1\n"
1192 "whileLoops 1\n"
1193 "doWhileLoops 1\n"
1194 "generalUniformIndexing 1\n"
1195 "generalAttributeMatrixVectorIndexing 1\n"
1196 "generalVaryingIndexing 1\n"
1197 "generalSamplerIndexing 1\n"
1198 "generalVariableIndexing 1\n"
1199 "generalConstantMatrixVectorIndexing 1\n"
1200 ;
1201
1202//
1203// *.conf => this is a config file that can set limits/resources
1204//
Tony Barbour6918cd52015-04-09 12:58:51 -06001205bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001206{
1207 if (name.size() < 5)
1208 return false;
1209
1210 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
1211 ConfigFile = name;
1212 return true;
1213 }
1214
1215 return false;
1216}
1217
1218//
1219// Parse either a .conf file provided by the user or the default string above.
1220//
Tony Barbour6918cd52015-04-09 12:58:51 -06001221void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001222{
1223 char** configStrings = 0;
1224 char* config = 0;
1225 if (ConfigFile.size() > 0) {
1226 configStrings = ReadFileData(ConfigFile.c_str());
1227 if (configStrings)
1228 config = *configStrings;
1229 else {
1230 printf("Error opening configuration file; will instead use the default configuration\n");
1231 }
1232 }
1233
1234 if (config == 0) {
1235 config = new char[strlen(DefaultConfig) + 1];
1236 strcpy(config, DefaultConfig);
1237 }
1238
1239 const char* delims = " \t\n\r";
1240 const char* token = strtok(config, delims);
1241 while (token) {
1242 const char* valueStr = strtok(0, delims);
1243 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1244 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1245 return;
1246 }
1247 int value = atoi(valueStr);
1248
1249 if (strcmp(token, "MaxLights") == 0)
1250 Resources.maxLights = value;
1251 else if (strcmp(token, "MaxClipPlanes") == 0)
1252 Resources.maxClipPlanes = value;
1253 else if (strcmp(token, "MaxTextureUnits") == 0)
1254 Resources.maxTextureUnits = value;
1255 else if (strcmp(token, "MaxTextureCoords") == 0)
1256 Resources.maxTextureCoords = value;
1257 else if (strcmp(token, "MaxVertexAttribs") == 0)
1258 Resources.maxVertexAttribs = value;
1259 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1260 Resources.maxVertexUniformComponents = value;
1261 else if (strcmp(token, "MaxVaryingFloats") == 0)
1262 Resources.maxVaryingFloats = value;
1263 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1264 Resources.maxVertexTextureImageUnits = value;
1265 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1266 Resources.maxCombinedTextureImageUnits = value;
1267 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1268 Resources.maxTextureImageUnits = value;
1269 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1270 Resources.maxFragmentUniformComponents = value;
1271 else if (strcmp(token, "MaxDrawBuffers") == 0)
1272 Resources.maxDrawBuffers = value;
1273 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1274 Resources.maxVertexUniformVectors = value;
1275 else if (strcmp(token, "MaxVaryingVectors") == 0)
1276 Resources.maxVaryingVectors = value;
1277 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1278 Resources.maxFragmentUniformVectors = value;
1279 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1280 Resources.maxVertexOutputVectors = value;
1281 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1282 Resources.maxFragmentInputVectors = value;
1283 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1284 Resources.minProgramTexelOffset = value;
1285 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1286 Resources.maxProgramTexelOffset = value;
1287 else if (strcmp(token, "MaxClipDistances") == 0)
1288 Resources.maxClipDistances = value;
1289 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1290 Resources.maxComputeWorkGroupCountX = value;
1291 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1292 Resources.maxComputeWorkGroupCountY = value;
1293 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1294 Resources.maxComputeWorkGroupCountZ = value;
1295 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1296 Resources.maxComputeWorkGroupSizeX = value;
1297 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1298 Resources.maxComputeWorkGroupSizeY = value;
1299 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1300 Resources.maxComputeWorkGroupSizeZ = value;
1301 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1302 Resources.maxComputeUniformComponents = value;
1303 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1304 Resources.maxComputeTextureImageUnits = value;
1305 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1306 Resources.maxComputeImageUniforms = value;
1307 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1308 Resources.maxComputeAtomicCounters = value;
1309 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1310 Resources.maxComputeAtomicCounterBuffers = value;
1311 else if (strcmp(token, "MaxVaryingComponents") == 0)
1312 Resources.maxVaryingComponents = value;
1313 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1314 Resources.maxVertexOutputComponents = value;
1315 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1316 Resources.maxGeometryInputComponents = value;
1317 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1318 Resources.maxGeometryOutputComponents = value;
1319 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1320 Resources.maxFragmentInputComponents = value;
1321 else if (strcmp(token, "MaxImageUnits") == 0)
1322 Resources.maxImageUnits = value;
1323 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1324 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1325 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1326 Resources.maxCombinedShaderOutputResources = value;
1327 else if (strcmp(token, "MaxImageSamples") == 0)
1328 Resources.maxImageSamples = value;
1329 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1330 Resources.maxVertexImageUniforms = value;
1331 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1332 Resources.maxTessControlImageUniforms = value;
1333 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1334 Resources.maxTessEvaluationImageUniforms = value;
1335 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1336 Resources.maxGeometryImageUniforms = value;
1337 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1338 Resources.maxFragmentImageUniforms = value;
1339 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1340 Resources.maxCombinedImageUniforms = value;
1341 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1342 Resources.maxGeometryTextureImageUnits = value;
1343 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1344 Resources.maxGeometryOutputVertices = value;
1345 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1346 Resources.maxGeometryTotalOutputComponents = value;
1347 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1348 Resources.maxGeometryUniformComponents = value;
1349 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1350 Resources.maxGeometryVaryingComponents = value;
1351 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1352 Resources.maxTessControlInputComponents = value;
1353 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1354 Resources.maxTessControlOutputComponents = value;
1355 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1356 Resources.maxTessControlTextureImageUnits = value;
1357 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1358 Resources.maxTessControlUniformComponents = value;
1359 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1360 Resources.maxTessControlTotalOutputComponents = value;
1361 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1362 Resources.maxTessEvaluationInputComponents = value;
1363 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1364 Resources.maxTessEvaluationOutputComponents = value;
1365 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1366 Resources.maxTessEvaluationTextureImageUnits = value;
1367 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1368 Resources.maxTessEvaluationUniformComponents = value;
1369 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1370 Resources.maxTessPatchComponents = value;
1371 else if (strcmp(token, "MaxPatchVertices") == 0)
1372 Resources.maxPatchVertices = value;
1373 else if (strcmp(token, "MaxTessGenLevel") == 0)
1374 Resources.maxTessGenLevel = value;
1375 else if (strcmp(token, "MaxViewports") == 0)
1376 Resources.maxViewports = value;
1377 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1378 Resources.maxVertexAtomicCounters = value;
1379 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1380 Resources.maxTessControlAtomicCounters = value;
1381 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1382 Resources.maxTessEvaluationAtomicCounters = value;
1383 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1384 Resources.maxGeometryAtomicCounters = value;
1385 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1386 Resources.maxFragmentAtomicCounters = value;
1387 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1388 Resources.maxCombinedAtomicCounters = value;
1389 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1390 Resources.maxAtomicCounterBindings = value;
1391 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1392 Resources.maxVertexAtomicCounterBuffers = value;
1393 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1394 Resources.maxTessControlAtomicCounterBuffers = value;
1395 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1396 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1397 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1398 Resources.maxGeometryAtomicCounterBuffers = value;
1399 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1400 Resources.maxFragmentAtomicCounterBuffers = value;
1401 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1402 Resources.maxCombinedAtomicCounterBuffers = value;
1403 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1404 Resources.maxAtomicCounterBufferSize = value;
1405 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1406 Resources.maxTransformFeedbackBuffers = value;
1407 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1408 Resources.maxTransformFeedbackInterleavedComponents = value;
1409 else if (strcmp(token, "MaxCullDistances") == 0)
1410 Resources.maxCullDistances = value;
1411 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1412 Resources.maxCombinedClipAndCullDistances = value;
1413 else if (strcmp(token, "MaxSamples") == 0)
1414 Resources.maxSamples = value;
1415
1416 else if (strcmp(token, "nonInductiveForLoops") == 0)
1417 Resources.limits.nonInductiveForLoops = (value != 0);
1418 else if (strcmp(token, "whileLoops") == 0)
1419 Resources.limits.whileLoops = (value != 0);
1420 else if (strcmp(token, "doWhileLoops") == 0)
1421 Resources.limits.doWhileLoops = (value != 0);
1422 else if (strcmp(token, "generalUniformIndexing") == 0)
1423 Resources.limits.generalUniformIndexing = (value != 0);
1424 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1425 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1426 else if (strcmp(token, "generalVaryingIndexing") == 0)
1427 Resources.limits.generalVaryingIndexing = (value != 0);
1428 else if (strcmp(token, "generalSamplerIndexing") == 0)
1429 Resources.limits.generalSamplerIndexing = (value != 0);
1430 else if (strcmp(token, "generalVariableIndexing") == 0)
1431 Resources.limits.generalVariableIndexing = (value != 0);
1432 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1433 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1434 else
1435 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1436
1437 token = strtok(0, delims);
1438 }
1439 if (configStrings)
1440 FreeFileData(configStrings);
1441}
1442
Tony Barbour6918cd52015-04-09 12:58:51 -06001443void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001444{
1445 if (m_compile_options & EOptionRelaxedErrors)
1446 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1447 if (m_compile_options & EOptionIntermediate)
1448 messages = (EShMessages)(messages | EShMsgAST);
1449 if (m_compile_options & EOptionSuppressWarnings)
1450 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1451}
1452
1453//
1454// Malloc a string of sufficient size and read a string into it.
1455//
Tony Barbour6918cd52015-04-09 12:58:51 -06001456char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001457{
1458 FILE *in;
1459 #if defined(_WIN32) && defined(__GNUC__)
1460 in = fopen(fileName, "r");
1461 int errorCode = in ? 0 : 1;
1462 #else
1463 int errorCode = fopen_s(&in, fileName, "r");
1464 #endif
1465
1466 char *fdata;
1467 int count = 0;
1468 const int maxSourceStrings = 5;
1469 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1470
1471 if (errorCode) {
1472 printf("Error: unable to open input file: %s\n", fileName);
1473 return 0;
1474 }
1475
1476 while (fgetc(in) != EOF)
1477 count++;
1478
1479 fseek(in, 0, SEEK_SET);
1480
1481 if (!(fdata = (char*)malloc(count+2))) {
1482 printf("Error allocating memory\n");
1483 return 0;
1484 }
1485 if (fread(fdata,1,count, in)!=count) {
1486 printf("Error reading input file: %s\n", fileName);
1487 return 0;
1488 }
1489 fdata[count] = '\0';
1490 fclose(in);
1491 if (count == 0) {
1492 return_data[0]=(char*)malloc(count+2);
1493 return_data[0][0]='\0';
1494 m_num_shader_strings = 0;
1495 return return_data;
1496 } else
1497 m_num_shader_strings = 1;
1498
1499 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1500 int ptr_len=0,i=0;
1501 while(count>0){
1502 return_data[i]=(char*)malloc(len+2);
1503 memcpy(return_data[i],fdata+ptr_len,len);
1504 return_data[i][len]='\0';
1505 count-=(len);
1506 ptr_len+=(len);
1507 if(count<len){
1508 if(count==0){
1509 m_num_shader_strings=(i+1);
1510 break;
1511 }
1512 len = count;
1513 }
1514 ++i;
1515 }
1516 return return_data;
1517}
1518
Tony Barbour6918cd52015-04-09 12:58:51 -06001519void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001520{
1521 for(int i=0;i<m_num_shader_strings;i++)
1522 free(data[i]);
1523}
1524
1525//
1526// Deduce the language from the filename. Files must end in one of the
1527// following extensions:
1528//
1529// .vert = vertex
1530// .tesc = tessellation control
1531// .tese = tessellation evaluation
1532// .geom = geometry
1533// .frag = fragment
1534// .comp = compute
1535//
Tony Barbour6918cd52015-04-09 12:58:51 -06001536EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001537{
1538 size_t ext = name.rfind('.');
1539 if (ext == std::string::npos) {
1540 return EShLangVertex;
1541 }
1542
1543 std::string suffix = name.substr(ext + 1, std::string::npos);
1544 if (suffix == "vert")
1545 return EShLangVertex;
1546 else if (suffix == "tesc")
1547 return EShLangTessControl;
1548 else if (suffix == "tese")
1549 return EShLangTessEvaluation;
1550 else if (suffix == "geom")
1551 return EShLangGeometry;
1552 else if (suffix == "frag")
1553 return EShLangFragment;
1554 else if (suffix == "comp")
1555 return EShLangCompute;
1556
1557 return EShLangVertex;
1558}
1559
1560//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001561// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001562//
Tony Barbourd1c35722015-04-16 15:59:00 -06001563EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001564{
1565 switch (shader_type) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001566 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001567 return EShLangVertex;
1568
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001569 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001570 return EShLangTessControl;
1571
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001572 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001573 return EShLangTessEvaluation;
1574
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001575 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001576 return EShLangGeometry;
1577
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001578 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001579 return EShLangFragment;
1580
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001581 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001582 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001583
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001584 default:
1585 return EShLangVertex;
1586 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001587}
1588
1589
1590//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001591// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001592// Return value of false means an error was encountered.
1593//
Tony Barbourd1c35722015-04-16 15:59:00 -06001594bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001595 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001596 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001597{
1598 glslang::TProgram& program = *new glslang::TProgram;
1599 const char *shaderStrings[1];
1600
1601 // TODO: Do we want to load a special config file depending on the
1602 // shader source? Optional name maybe?
1603 // SetConfigFile(fileName);
1604
1605 ProcessConfigFile();
1606
1607 EShMessages messages = EShMsgDefault;
1608 SetMessageOptions(messages);
1609
1610 EShLanguage stage = FindLanguage(shader_type);
1611 glslang::TShader* shader = new glslang::TShader(stage);
1612
1613 shaderStrings[0] = pshader;
1614 shader->setStrings(shaderStrings, 1);
1615
1616 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1617
Cody Northrop195d6622014-11-03 12:54:37 -07001618 if (! (m_compile_options & EOptionSuppressInfolog)) {
1619 puts(shader->getInfoLog());
1620 puts(shader->getInfoDebugLog());
1621 }
1622
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001623 return false; // something didn't work
1624 }
1625
1626 program.addShader(shader);
1627
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001628
1629 //
1630 // Program-level processing...
1631 //
1632
Cody Northrop195d6622014-11-03 12:54:37 -07001633 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001634
Cody Northrop195d6622014-11-03 12:54:37 -07001635 if (! (m_compile_options & EOptionSuppressInfolog)) {
1636 puts(shader->getInfoLog());
1637 puts(shader->getInfoDebugLog());
1638 }
1639
1640 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001641 }
1642
1643 if (m_compile_options & EOptionDumpReflection) {
1644 program.buildReflection();
1645 program.dumpReflection();
1646 }
1647
Cody Northrop5a95b472015-06-03 13:01:54 -06001648 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1649
1650 //
1651 // Test the different modes of SPIR-V modification
1652 //
1653 if (this->m_canonicalize_spv) {
1654 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1655 }
1656
1657 if (this->m_strip_spv) {
1658 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1659 }
1660
1661 if (this->m_do_everything_spv) {
1662 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1663 }
1664
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001665
1666 return true;
1667}
1668
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001669
1670
Tony Barbour6918cd52015-04-09 12:58:51 -06001671VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001672 m_width( 0 ),
1673 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001674 m_data( NULL ),
1675 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001676{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001677}
1678
Tony Barbour6918cd52015-04-09 12:58:51 -06001679VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001680{
1681
1682}
1683
Tony Barbour6918cd52015-04-09 12:58:51 -06001684VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001685{
1686 m_title = copyin.m_title;
1687 m_width = copyin.m_width;
1688 m_height = copyin.m_height;
1689 m_data_size = copyin.m_data_size;
1690 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1691}
1692
Tony Barbour6918cd52015-04-09 12:58:51 -06001693ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001694{
Tony Barbour6918cd52015-04-09 12:58:51 -06001695 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1696 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001697 return output;
1698}
1699
Tony Barbour6918cd52015-04-09 12:58:51 -06001700VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001701{
1702 m_title = rhs.m_title;
1703 m_width = rhs.m_width;
1704 m_height = rhs.m_height;
1705 m_data_size = rhs.m_data_size;
1706 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001707 return *this;
1708}
1709
Tony Barbour6918cd52015-04-09 12:58:51 -06001710int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001711{
1712 if( this->m_data != rhs.m_data) return 0;
1713 return 1;
1714}
1715
1716// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001717int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001718{
1719 if( this->m_data_size < rhs.m_data_size ) return 1;
1720 return 0;
1721}
1722