blob: ecb192fd672867573fa7d7bc72a217c66bb3cce2 [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>
31#include <vk_wsi_lunarg.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060032
Tony Barbour3d69c9e2015-05-20 16:53:31 -060033#if defined(PATH_MAX) && !defined(MAX_PATH)
34#define MAX_PATH PATH_MAX
35#endif
36
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060037// Command-line options
38enum TOptions {
39 EOptionNone = 0x000,
40 EOptionIntermediate = 0x001,
41 EOptionSuppressInfolog = 0x002,
42 EOptionMemoryLeakMode = 0x004,
43 EOptionRelaxedErrors = 0x008,
44 EOptionGiveWarnings = 0x010,
45 EOptionLinkProgram = 0x020,
46 EOptionMultiThreaded = 0x040,
47 EOptionDumpConfig = 0x080,
48 EOptionDumpReflection = 0x100,
49 EOptionSuppressWarnings = 0x200,
50 EOptionDumpVersions = 0x400,
Cody Northrop3bfd27c2015-03-17 15:55:58 -060051 EOptionSpv = 0x800,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060052 EOptionDefaultDesktop = 0x1000,
53};
54
Chia-I Wuf8693382015-04-16 22:02:10 +080055class TestFrameworkVkPresent
56{
57public:
58 TestFrameworkVkPresent(vk_testing::Device &device);
59
60 void Run();
Jon Ashburn07daee72015-05-21 18:13:33 -060061 void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst);
Chia-I Wuf8693382015-04-16 22:02:10 +080062 void CreateMyWindow();
63 void CreateSwapChain();
64 void TearDown();
Tony Barbour3d69c9e2015-05-20 16:53:31 -060065#ifdef _WIN32
66 static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
67#endif
68
Chia-I Wuf8693382015-04-16 22:02:10 +080069
70protected:
71 vk_testing::Device &m_device;
72 vk_testing::Queue &m_queue;
73 vk_testing::CmdBuffer m_cmdbuf;
74
75private:
Tony Barbour3d69c9e2015-05-20 16:53:31 -060076#ifdef _WIN32
77 HINSTANCE m_connection; // hInstance - Windows Instance
78 HWND m_window; // hWnd - window handle
79
80#else
Chia-I Wuf8693382015-04-16 22:02:10 +080081 xcb_connection_t *m_connection;
82 xcb_screen_t *m_screen;
83 xcb_window_t m_window;
84 xcb_intern_atom_reply_t *m_atom_wm_delete_window;
Tony Barbour3d69c9e2015-05-20 16:53:31 -060085#endif
Courtney Goeltzenleuchterd6079ec2015-04-22 10:09:35 -060086 std::list<VkTestImageRecord> m_images;
Chia-I Wuf8693382015-04-16 22:02:10 +080087
Jon Ashburn07daee72015-05-21 18:13:33 -060088 PFN_vkCreateSwapChainWSI m_fpCreateSwapChainWSI;
89 PFN_vkDestroySwapChainWSI m_fpDestroySwapChainWSI;
90 PFN_vkGetSwapChainInfoWSI m_fpGetSwapChainInfoWSI;
91 PFN_vkQueuePresentWSI m_fpQueuePresentWSI;
92
Chia-I Wuf8693382015-04-16 22:02:10 +080093 VkSwapChainWSI m_swap_chain;
Tony-LunarG399dfca2015-05-19 14:08:26 -060094 std::vector<VkSwapChainImageInfoWSI> m_persistent_images;
95 int m_current_buffer;
Chia-I Wuf8693382015-04-16 22:02:10 +080096
97 bool m_quit;
98 bool m_pause;
99
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600100 int m_width;
101 int m_height;
Chia-I Wuf8693382015-04-16 22:02:10 +0800102
103 std::list<VkTestImageRecord>::iterator m_display_image;
104
105 void Display();
106 void HandleEvent(xcb_generic_event_t *event);
107};
108
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600109#ifndef _WIN32
110
111#include <errno.h>
112
113int fopen_s(
114 FILE** pFile,
115 const char* filename,
116 const char* mode
117)
118{
119 if (!pFile || !filename || !mode) {
120 return EINVAL;
121 }
122
123 FILE* f = fopen(filename, mode);
124 if (! f) {
125 if (errno != 0) {
126 return errno;
127 } else {
128 return ENOENT;
129 }
130 }
131 *pFile = f;
132
133 return 0;
134}
135
136#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600137
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600138
139
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600140// Set up environment for GLSL compiler
141// Must be done once per process
142void TestEnvironment::SetUp()
143{
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600144 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600145 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800146
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600147 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600148}
149
150void TestEnvironment::TearDown()
151{
152 glslang::FinalizeProcess();
153}
154
Tony Barbour6918cd52015-04-09 12:58:51 -0600155VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600156 m_compile_options( 0 ),
157 m_num_shader_strings( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600158{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600159
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600160}
161
Tony Barbour6918cd52015-04-09 12:58:51 -0600162VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600163{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600164
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600165}
166
167// Define all the static elements
Tony Barbour6918cd52015-04-09 12:58:51 -0600168bool VkTestFramework::m_show_images = false;
169bool VkTestFramework::m_save_images = false;
170bool VkTestFramework::m_compare_images = false;
Tony Barbour0dd968a2015-04-02 15:48:24 -0600171#ifdef _WIN32
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600172bool VkTestFramework::m_use_glsl = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600173bool VkTestFramework::m_canonicalize_spv = false;
174bool VkTestFramework::m_strip_spv = false;
175bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour0dd968a2015-04-02 15:48:24 -0600176#else
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600177bool VkTestFramework::m_use_glsl = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600178bool VkTestFramework::m_canonicalize_spv = false;
179bool VkTestFramework::m_strip_spv = false;
180bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour0dd968a2015-04-02 15:48:24 -0600181#endif
Tony Barbour6918cd52015-04-09 12:58:51 -0600182int VkTestFramework::m_width = 0;
183int VkTestFramework::m_height = 0;
184std::list<VkTestImageRecord> VkTestFramework::m_images;
185std::list<VkTestImageRecord>::iterator VkTestFramework::m_display_image;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600186int m_display_image_idx = 0;
187
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600188bool VkTestFramework::optionMatch(const char* option, char* optionLine)
189{
190 if (strncmp(option, optionLine, strlen(option)) == 0)
191 return true;
192 else
193 return false;
194}
195
Tony Barbour6918cd52015-04-09 12:58:51 -0600196void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600197{
198 int i, n;
199
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600200 for (i=1, n=1; i< *argc; i++) {
201 if (optionMatch("--show-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600202 m_show_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600203 else if (optionMatch("--save-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600204 m_save_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600205 else if (optionMatch("--no-SPV", argv[i]))
206 m_use_glsl = true;
207 else if (optionMatch("--strip-SPV", argv[i]))
208 m_strip_spv = true;
209 else if (optionMatch("--canonicalize-SPV", argv[i]))
210 m_canonicalize_spv = true;
211 else if (optionMatch("--compare-images", argv[i]))
Tony Barbour247bf372014-10-30 14:29:04 -0600212 m_compare_images = true;
Tony Barbour247bf372014-10-30 14:29:04 -0600213
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600214 else if (optionMatch("--help", argv[i]) ||
215 optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700216 printf("\nOther options:\n");
217 printf("\t--show-images\n"
218 "\t\tDisplay test images in viewer after tests complete.\n");
219 printf("\t--save-images\n"
220 "\t\tSave tests images as ppm files in current working directory.\n"
221 "\t\tUsed to generate golden images for compare-images.\n");
222 printf("\t--compare-images\n"
223 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barboura98d3932014-12-11 09:52:49 -0700224 "\t\tAlso saves the generated test image in current working\n"
225 "\t\t\tdirectory but only if the image is different from the golden\n"
226 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
227 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700228 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600229 printf("\t--no-SPV\n"
230 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600231 printf("\t--strip-SPV\n"
232 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
233 printf("\t--canonicalize-SPV\n"
234 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
235 exit(0);
236 } else {
237 printf("\nUnrecognized option: %s\n", argv[i]);
238 printf("\nUse --help or -h for option list.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700239 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700240 }
241
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600242 /*
243 * Since the above "consume" inputs, update argv
244 * so that it contains the trimmed list of args for glutInit
245 */
246
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600247 argv[n] = argv[i];
248 n++;
249 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600250}
251
Tony Barbour6918cd52015-04-09 12:58:51 -0600252void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600253{
254 string filename;
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600255 VkResult err;
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600256 uint32_t x, y;
Tony Barbour6918cd52015-04-09 12:58:51 -0600257 VkImageObj displayImage(image->device());
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600258 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbour84d448c2015-04-02 14:02:33 -0600259
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600260 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, VK_IMAGE_TILING_LINEAR, reqs);
Tony Barbour84d448c2015-04-02 14:02:33 -0600261 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600262
263 filename.append(basename);
264 filename.append(".ppm");
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600265
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600266 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600267 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600268 };
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600269 VkSubresourceLayout sr_layout;
Chia-I Wu99ff89d2014-12-27 14:14:50 +0800270 size_t data_size = sizeof(sr_layout);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600271
272 err = vkGetImageSubresourceInfo(image->device()->device(), displayImage.image(), &sr,
Tony Barbourd1c35722015-04-16 15:59:00 -0600273 VK_SUBRESOURCE_INFO_TYPE_LAYOUT,
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600274 &data_size, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600275 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600276 ASSERT_EQ(data_size, sizeof(sr_layout));
277
Tony Barbour84d448c2015-04-02 14:02:33 -0600278 char *ptr;
279 ptr = (char *) displayImage.map();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600280 ptr += sr_layout.offset;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600281 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600282 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
283
284 file << "P6\n";
Tony Barbour84d448c2015-04-02 14:02:33 -0600285 file << displayImage.width() << "\n";
286 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600287 file << 255 << "\n";
288
Tony Barbour84d448c2015-04-02 14:02:33 -0600289 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700290 const int *row = (const int *) ptr;
291 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600292
Tony Barbourd1c35722015-04-16 15:59:00 -0600293 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700294 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600295 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700296 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
297 file.write((char *) &swapped, 3);
298 row++;
299 }
300 }
Tony Barbourd1c35722015-04-16 15:59:00 -0600301 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700302 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600303 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700304 file.write((char *) row, 3);
305 row++;
306 }
307 }
308 else {
309 printf("Unrecognized image format - will not write image files");
310 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600311 }
312
313 ptr += sr_layout.rowPitch;
314 }
315
316 file.close();
Tony Barbour84d448c2015-04-02 14:02:33 -0600317 displayImage.unmap();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600318}
319
Tony Barbour6918cd52015-04-09 12:58:51 -0600320void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour247bf372014-10-30 14:29:04 -0600321{
322
323 MagickWand *magick_wand_1;
324 MagickWand *magick_wand_2;
325 MagickWand *compare_wand;
326 MagickBooleanType status;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600327 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600328 double differenz;
329
Tony Barbour4ab45422014-12-10 17:00:20 -0700330 if (getenv("RENDERTEST_GOLDEN_DIR"))
331 {
332 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
333 }
334
Tony Barbour247bf372014-10-30 14:29:04 -0600335 MagickWandGenesis();
336 magick_wand_1=NewMagickWand();
337 sprintf(testimage,"%s.ppm",basename);
338 status=MagickReadImage(magick_wand_1,testimage);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600339 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour247bf372014-10-30 14:29:04 -0600340
341
342 MagickWandGenesis();
343 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700344 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600345 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600346 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour247bf372014-10-30 14:29:04 -0600347
Tony Barbour247bf372014-10-30 14:29:04 -0600348 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
349 if (differenz != 0.0)
350 {
351 char difference[256];
352
353 sprintf(difference,"%s-diff.ppm",basename);
354 status = MagickWriteImage(compare_wand, difference);
355 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
356 }
357 DestroyMagickWand(compare_wand);
358
359 DestroyMagickWand(magick_wand_1);
360 DestroyMagickWand(magick_wand_2);
361 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700362
363 if (differenz == 0.0)
364 {
365 /*
366 * If test image and golden image match, we do not need to
367 * keep around the test image.
368 */
369 remove(testimage);
370 }
Tony Barbour247bf372014-10-30 14:29:04 -0600371}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600372
Tony Barbour6918cd52015-04-09 12:58:51 -0600373void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600374{
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600375 VkResult err;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600376 VkSubresourceLayout sr_layout;
377 char *ptr;
378 VkTestImageRecord record;
379 size_t data_size = sizeof(sr_layout);
380 VkImageObj displayImage(image->device());
381 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
382
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600383 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, VK_IMAGE_TILING_LINEAR, reqs);
384 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600385
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600386 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600387 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600388 };
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600389
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600390 err = vkGetImageSubresourceInfo(displayImage.device()->device(), displayImage.image(), &sr,
391 VK_SUBRESOURCE_INFO_TYPE_LAYOUT,
392 &data_size, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600393 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600394 ASSERT_EQ(data_size, sizeof(sr_layout));
395
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600396 err = displayImage.MapMemory( (void **) &ptr );
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600397 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600398
399 ptr += sr_layout.offset;
400
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600401 record.m_title.append(comment);
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600402 record.m_width = displayImage.width();
403 record.m_height = displayImage.height();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600404 // TODO: Need to make this more robust to handle different image formats
Tony-LunarG399dfca2015-05-19 14:08:26 -0600405 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600406 record.m_data = malloc(record.m_data_size);
407 memcpy(record.m_data, ptr, record.m_data_size);
408 m_images.push_back(record);
409 m_display_image = --m_images.end();
410
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600411 err = displayImage.UnmapMemory();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600412 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600413}
414
Tony Barbour6918cd52015-04-09 12:58:51 -0600415void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600416{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600417 for (int32_t i = 0; i < images.size(); i++) {
418 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600419 }
420}
421
Tony Barbour6918cd52015-04-09 12:58:51 -0600422void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600423{
424 const ::testing::TestInfo* const test_info =
425 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600426 ostringstream filestream;
427 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600428
Tony Barbour247bf372014-10-30 14:29:04 -0600429 m_width = 40;
430
431 if (strcmp(test_info->name(), m_testName.c_str())) {
432 filestream << test_info->name();
433 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700434 m_frameNum = 2;
435 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600436 }
437 else {
438 filestream << test_info->name() << "-" << m_frameNum;
439 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700440 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600441 }
442
Tony Barbour247bf372014-10-30 14:29:04 -0600443 // ToDo - scrub string for bad characters
444
445 if (m_save_images || m_compare_images) {
446 WritePPM(filename.c_str(), image);
447 if (m_compare_images) {
448 Compare(filename.c_str(), image);
449 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600450 }
451
452 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600453 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600454 }
455}
456
Chia-I Wuf8693382015-04-16 22:02:10 +0800457TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
458 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700459 m_queue(*m_device.graphics_queues()[0]),
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600460 m_cmdbuf(m_device, vk_testing::CmdBuffer::create_info(m_device.graphics_queue_node_index_))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600461{
Tony Barbour96db8822015-02-25 12:28:39 -0700462 m_quit = false;
463 m_pause = false;
464 m_width = 0;
465 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600466}
467
Tony Barbour6918cd52015-04-09 12:58:51 -0600468void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600469{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600470 VkResult U_ASSERT_ONLY err;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600471 vk_testing::Buffer buf;
472 void *dest_ptr;
473
474 if (m_persistent_images.size() != 2) {
475 return;
476 }
477
478 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
479 buf.init(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
480 dest_ptr = buf.map();
481 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
482 buf.unmap();
483
484 m_cmdbuf.begin();
485
486 VkBufferImageCopy region = {};
487 region.imageExtent.height = m_display_image->m_height;
488 region.imageExtent.width = m_display_image->m_width;
489 region.imageExtent.depth = 1;
490
491 vkCmdCopyBufferToImage(m_cmdbuf.obj(),
492 buf.obj(),
493 m_persistent_images[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
494 1, &region);
495 m_cmdbuf.end();
496
497 VkCmdBuffer cmdBufs[1];
498 cmdBufs[0] = m_cmdbuf.obj();
499
500 vkQueueSubmit(m_queue.obj(), 1, cmdBufs, NULL);
501 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700502
Chia-I Wuf8693382015-04-16 22:02:10 +0800503 VkPresentInfoWSI present = {};
504 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_WSI;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600505 present.image = m_persistent_images[m_current_buffer].image;
Chia-I Wuf8693382015-04-16 22:02:10 +0800506 present.flipInterval = 1;
Tony Barbour96db8822015-02-25 12:28:39 -0700507
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600508#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800509 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700510 XCB_PROP_MODE_REPLACE,
511 m_window,
512 XCB_ATOM_WM_NAME,
513 XCB_ATOM_STRING,
514 8,
515 m_display_image->m_title.size(),
516 m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600517#endif
Jon Ashburn07daee72015-05-21 18:13:33 -0600518
519 err = m_fpQueuePresentWSI(m_queue.obj(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700520 assert(!err);
521
522 m_queue.wait();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600523 m_current_buffer = (m_current_buffer + 1) % 2;
Tony Barbour96db8822015-02-25 12:28:39 -0700524
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600525}
526
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600527#ifdef _WIN32
Tony-LunarG399dfca2015-05-19 14:08:26 -0600528# define PREVIOUSLY_DOWN 1<<29
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600529// MS-Windows event handling function:
530LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
531 UINT uMsg,
532 WPARAM wParam,
533 LPARAM lParam)
534{
535
536 switch(uMsg)
537 {
538 case WM_CLOSE:
539 PostQuitMessage(0);
540 break;
541
542 case WM_PAINT:
543 {
544 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
545 if (me) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600546 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600547 me->Display();
548 }
549 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600550 break;
551
552 case WM_KEYDOWN:
553 {
554 if (lParam & (PREVIOUSLY_DOWN)){
555 break;
556 }
557 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
558 // the window, we put the this pointer into the window's user data so we could get it back now
559 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
560 switch (wParam)
561 {
562 case VK_ESCAPE: me->m_quit = true;
563 break;
564
565 case VK_LEFT: // left arrow key
566 if (me->m_display_image == me->m_images.begin()) {
567 me->m_display_image = --me->m_images.end();
568 }
569 else {
570 --me->m_display_image;
571 }
572 break;
573
574 case VK_RIGHT: // right arrow key
575 ++me->m_display_image;
576 if (me->m_display_image == me->m_images.end()) {
577 me->m_display_image = me->m_images.begin();
578 }
579 break;
580
581 default:
582 break;
583 }
584 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
585 me->Display();
586 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600587 }
588 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
589}
590
591void TestFrameworkVkPresent::Run()
592{
593 MSG msg; // message
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600594
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600595 /* main message loop*/
Tony-LunarG399dfca2015-05-19 14:08:26 -0600596 while(! m_quit) {
597 GetMessage(&msg, m_window, 0, 0);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600598 if (msg.message == WM_QUIT) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600599 m_quit = true; //if found, quit app
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600600 } else {
601 /* Translate and dispatch to event queue*/
602 TranslateMessage(&msg);
603 DispatchMessage(&msg);
604 }
605 }
606}
607
608#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600609void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600610{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600611 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700612 switch (event_code) {
613 case XCB_EXPOSE:
614 Display(); // TODO: handle resize
615 break;
616 case XCB_CLIENT_MESSAGE:
617 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
618 (m_atom_wm_delete_window)->atom) {
619 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600620 }
621 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700622 case XCB_KEY_RELEASE:
623 {
624 const xcb_key_release_event_t *key =
625 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600626
Tony Barbour96db8822015-02-25 12:28:39 -0700627 switch (key->detail) {
628 case 0x9: // Escape
629 m_quit = true;
630 break;
631 case 0x71: // left arrow key
632 if (m_display_image == m_images.begin()) {
633 m_display_image = --m_images.end();
634 } else {
635 --m_display_image;
636 }
637 break;
638 case 0x72: // right arrow key
639 ++m_display_image;
640 if (m_display_image == m_images.end()) {
641 m_display_image = m_images.begin();
642 }
643 break;
644 case 0x41:
645 m_pause = !m_pause;
646 break;
647 }
648 Display();
649 }
650 break;
651 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600652 break;
653 }
Tony Barbour96db8822015-02-25 12:28:39 -0700654}
655
Tony Barbour6918cd52015-04-09 12:58:51 -0600656void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700657{
Chia-I Wuf8693382015-04-16 22:02:10 +0800658 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700659
660 while (! m_quit) {
661 xcb_generic_event_t *event;
662
663 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800664 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700665 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800666 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700667 }
668 if (event) {
669 HandleEvent(event);
670 free(event);
671 }
672 }
673}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600674#endif // _WIN32
Tony Barbour96db8822015-02-25 12:28:39 -0700675
Chia-I Wuf8693382015-04-16 22:02:10 +0800676void TestFrameworkVkPresent::CreateSwapChain()
Tony Barbour96db8822015-02-25 12:28:39 -0700677{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600678 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700679
Tony-LunarG399dfca2015-05-19 14:08:26 -0600680 m_display_image = m_images.begin();
681 m_current_buffer = 0;
682
Chia-I Wuf8693382015-04-16 22:02:10 +0800683 VkSwapChainCreateInfoWSI swap_chain = {};
684 swap_chain.sType = VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI;
685 swap_chain.pNativeWindowSystemHandle = (void *) m_connection;
686 swap_chain.pNativeWindowHandle = (void *) (intptr_t) m_window;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600687 swap_chain.imageCount = 2;
Chia-I Wuf8693382015-04-16 22:02:10 +0800688 swap_chain.imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
689 swap_chain.imageExtent.width = m_width;
690 swap_chain.imageExtent.height = m_height;
691 swap_chain.imageArraySize = 1;
692 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT;
693 swap_chain.swapModeFlags = VK_SWAP_MODE_FLIP_BIT_WSI |
694 VK_SWAP_MODE_BLIT_BIT_WSI;
695
Jon Ashburn07daee72015-05-21 18:13:33 -0600696 err = m_fpCreateSwapChainWSI(m_device.obj(), &swap_chain, &m_swap_chain);
Chia-I Wuf8693382015-04-16 22:02:10 +0800697 assert(!err);
698
Tony-LunarG399dfca2015-05-19 14:08:26 -0600699 VkSwapChainImageInfoWSI infos[2];
Jon Ashburn07daee72015-05-21 18:13:33 -0600700 size_t size = sizeof(VkSwapChainImageInfoWSI) * m_images.size();
701 std::vector<VkSwapChainImageInfoWSI> persistent_images;
702 persistent_images.resize(m_images.size());
703 err = m_fpGetSwapChainInfoWSI(m_swap_chain,
Chia-I Wuf8693382015-04-16 22:02:10 +0800704 VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600705 &size, &infos);
706 assert(!err && size == sizeof(VkSwapChainImageInfoWSI) * 2);
707 m_persistent_images.push_back(infos[0]);
708 m_persistent_images.push_back(infos[1]);
Tony Barbour96db8822015-02-25 12:28:39 -0700709}
710
Jon Ashburn07daee72015-05-21 18:13:33 -0600711void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -0700712{
Jon Ashburn07daee72015-05-21 18:13:33 -0600713 m_fpCreateSwapChainWSI = (PFN_vkCreateSwapChainWSI) vkGetInstanceProcAddr(inst, "vkCreateSwapChainWSI");
714 ASSERT_TRUE(m_fpCreateSwapChainWSI != NULL) << "vkGetInstanceProcAddr failed to find vkCreateSwapChainWSI";
715
716 m_fpDestroySwapChainWSI = (PFN_vkDestroySwapChainWSI) vkGetInstanceProcAddr(inst, "vkDestroySwapChainWSI");
717 ASSERT_TRUE(m_fpDestroySwapChainWSI != NULL) << "vkGetInstanceProcAddr failed to find vkDestroySwapChainWSI";
718
719 m_fpGetSwapChainInfoWSI = (PFN_vkGetSwapChainInfoWSI) vkGetInstanceProcAddr(inst, "vkGetSwapChainInfoWSI");
720 ASSERT_TRUE(m_fpGetSwapChainInfoWSI != NULL) << "vkGetInstanceProcAddr failed to find vkGetSwapChainInfoWSI";
721
722 m_fpQueuePresentWSI = (PFN_vkQueuePresentWSI) vkGetInstanceProcAddr(inst, "vkQueuePresentWSI");
723 ASSERT_TRUE(m_fpQueuePresentWSI != NULL) << "vkGetInstanceProcAddr failed to find vkQueuePresentWSI";
724
Tony Barbour96db8822015-02-25 12:28:39 -0700725 m_images = imagesIn;
726}
727
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600728#ifdef _WIN32
729void TestFrameworkVkPresent::CreateMyWindow()
730{
731 WNDCLASSEX win_class;
732 // const ::testing::TestInfo* const test_info =
733 // ::testing::UnitTest::GetInstance()->current_test_info();
734 m_connection = GetModuleHandle(NULL);
735
736 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
737 it != m_images.end(); it++) {
738 if (m_width < it->m_width)
739 m_width = it->m_width;
740 if (m_height < it->m_height)
741 m_height = it->m_height;
742 }
743 // Initialize the window class structure:
744 win_class.cbSize = sizeof(WNDCLASSEX);
745 win_class.style = CS_HREDRAW | CS_VREDRAW;
746 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
747 win_class.cbClsExtra = 0;
748 win_class.cbWndExtra = 0;
749 win_class.hInstance = m_connection; // hInstance
750 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
751 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
752 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
753 win_class.lpszMenuName = NULL;
754 win_class.lpszClassName = "Test";
755 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
756 // Register window class:
757 if (!RegisterClassEx(&win_class)) {
758 // It didn't work, so try to give a useful error:
759 printf("Unexpected error trying to start the application!\n");
760 fflush(stdout);
761 exit(1);
762 }
763 // Create window with the registered class:
764 m_window = CreateWindowEx(0,
765 "Test", // class name
766 "Test", // app name
767 WS_OVERLAPPEDWINDOW | // window style
768 WS_VISIBLE |
769 WS_SYSMENU,
770 100,100, // x/y coords
771 m_width, // width
772 m_height, // height
773 NULL, // handle to parent
774 NULL, // handle to menu
775 m_connection, // hInstance
776 NULL); // no extra parameters
777
778 if (!m_window) {
779 // It didn't work, so try to give a useful error:
780 DWORD error = GetLastError();
781 char message[120];
782 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
783 MessageBox(NULL, message, "Error", MB_OK);
784 exit(1);
785 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600786 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
787 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600788}
789#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600790void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -0700791{
Chia-I Wuf8693382015-04-16 22:02:10 +0800792 const xcb_setup_t *setup;
793 xcb_screen_iterator_t iter;
794 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -0700795 uint32_t value_mask, value_list[32];
796
Chia-I Wuf8693382015-04-16 22:02:10 +0800797 m_connection = xcb_connect(NULL, &scr);
798
799 setup = xcb_get_setup(m_connection);
800 iter = xcb_setup_roots_iterator(setup);
801 while (scr-- > 0)
802 xcb_screen_next(&iter);
803
804 m_screen = iter.data;
805
806 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
807 it != m_images.end(); it++) {
808 if (m_width < it->m_width)
809 m_width = it->m_width;
810 if (m_height < it->m_height)
811 m_height = it->m_height;
812 }
813
814 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700815
816 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +0800817 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -0700818 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
819 XCB_EVENT_MASK_EXPOSURE |
820 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
821
Chia-I Wuf8693382015-04-16 22:02:10 +0800822 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700823 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800824 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -0700825 0, 0, m_width, m_height, 0,
826 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800827 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -0700828 value_mask, value_list);
829
830 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +0800831 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -0700832 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +0800833 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -0700834
Chia-I Wuf8693382015-04-16 22:02:10 +0800835 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
836 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -0700837
Chia-I Wuf8693382015-04-16 22:02:10 +0800838 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -0700839 m_window, (*reply).atom, 4, 32, 1,
840 &(*m_atom_wm_delete_window).atom);
841 free(reply);
842
Chia-I Wuf8693382015-04-16 22:02:10 +0800843 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -0700844}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600845#endif
Tony Barbour96db8822015-02-25 12:28:39 -0700846
Tony Barbour6918cd52015-04-09 12:58:51 -0600847void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -0700848{
Jon Ashburn07daee72015-05-21 18:13:33 -0600849 m_fpDestroySwapChainWSI(m_swap_chain);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600850#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800851 xcb_destroy_window(m_connection, m_window);
852 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600853#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600854}
855
Tony Barbour6918cd52015-04-09 12:58:51 -0600856void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600857{
858 if (m_images.size() == 0) return;
859
Chia-I Wuf8693382015-04-16 22:02:10 +0800860 vk_testing::Environment env;
861 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -0700862 {
Chia-I Wuf8693382015-04-16 22:02:10 +0800863 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -0700864
Jon Ashburn07daee72015-05-21 18:13:33 -0600865 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600866 vkPresent.CreateMyWindow();
Chia-I Wuf8693382015-04-16 22:02:10 +0800867 vkPresent.CreateSwapChain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600868 vkPresent.Run();
869 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -0700870 }
Chia-I Wuf8693382015-04-16 22:02:10 +0800871 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600872}
873
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600874//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600875// These are the default resources for TBuiltInResources, used for both
876// - parsing this string for the case where the user didn't supply one
877// - dumping out a template for user construction of a config file
878//
879static const char* DefaultConfig =
880 "MaxLights 32\n"
881 "MaxClipPlanes 6\n"
882 "MaxTextureUnits 32\n"
883 "MaxTextureCoords 32\n"
884 "MaxVertexAttribs 64\n"
885 "MaxVertexUniformComponents 4096\n"
886 "MaxVaryingFloats 64\n"
887 "MaxVertexTextureImageUnits 32\n"
888 "MaxCombinedTextureImageUnits 80\n"
889 "MaxTextureImageUnits 32\n"
890 "MaxFragmentUniformComponents 4096\n"
891 "MaxDrawBuffers 32\n"
892 "MaxVertexUniformVectors 128\n"
893 "MaxVaryingVectors 8\n"
894 "MaxFragmentUniformVectors 16\n"
895 "MaxVertexOutputVectors 16\n"
896 "MaxFragmentInputVectors 15\n"
897 "MinProgramTexelOffset -8\n"
898 "MaxProgramTexelOffset 7\n"
899 "MaxClipDistances 8\n"
900 "MaxComputeWorkGroupCountX 65535\n"
901 "MaxComputeWorkGroupCountY 65535\n"
902 "MaxComputeWorkGroupCountZ 65535\n"
903 "MaxComputeWorkGroupSizeX 1024\n"
904 "MaxComputeWorkGroupSizeY 1024\n"
905 "MaxComputeWorkGroupSizeZ 64\n"
906 "MaxComputeUniformComponents 1024\n"
907 "MaxComputeTextureImageUnits 16\n"
908 "MaxComputeImageUniforms 8\n"
909 "MaxComputeAtomicCounters 8\n"
910 "MaxComputeAtomicCounterBuffers 1\n"
911 "MaxVaryingComponents 60\n"
912 "MaxVertexOutputComponents 64\n"
913 "MaxGeometryInputComponents 64\n"
914 "MaxGeometryOutputComponents 128\n"
915 "MaxFragmentInputComponents 128\n"
916 "MaxImageUnits 8\n"
917 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
918 "MaxCombinedShaderOutputResources 8\n"
919 "MaxImageSamples 0\n"
920 "MaxVertexImageUniforms 0\n"
921 "MaxTessControlImageUniforms 0\n"
922 "MaxTessEvaluationImageUniforms 0\n"
923 "MaxGeometryImageUniforms 0\n"
924 "MaxFragmentImageUniforms 8\n"
925 "MaxCombinedImageUniforms 8\n"
926 "MaxGeometryTextureImageUnits 16\n"
927 "MaxGeometryOutputVertices 256\n"
928 "MaxGeometryTotalOutputComponents 1024\n"
929 "MaxGeometryUniformComponents 1024\n"
930 "MaxGeometryVaryingComponents 64\n"
931 "MaxTessControlInputComponents 128\n"
932 "MaxTessControlOutputComponents 128\n"
933 "MaxTessControlTextureImageUnits 16\n"
934 "MaxTessControlUniformComponents 1024\n"
935 "MaxTessControlTotalOutputComponents 4096\n"
936 "MaxTessEvaluationInputComponents 128\n"
937 "MaxTessEvaluationOutputComponents 128\n"
938 "MaxTessEvaluationTextureImageUnits 16\n"
939 "MaxTessEvaluationUniformComponents 1024\n"
940 "MaxTessPatchComponents 120\n"
941 "MaxPatchVertices 32\n"
942 "MaxTessGenLevel 64\n"
943 "MaxViewports 16\n"
944 "MaxVertexAtomicCounters 0\n"
945 "MaxTessControlAtomicCounters 0\n"
946 "MaxTessEvaluationAtomicCounters 0\n"
947 "MaxGeometryAtomicCounters 0\n"
948 "MaxFragmentAtomicCounters 8\n"
949 "MaxCombinedAtomicCounters 8\n"
950 "MaxAtomicCounterBindings 1\n"
951 "MaxVertexAtomicCounterBuffers 0\n"
952 "MaxTessControlAtomicCounterBuffers 0\n"
953 "MaxTessEvaluationAtomicCounterBuffers 0\n"
954 "MaxGeometryAtomicCounterBuffers 0\n"
955 "MaxFragmentAtomicCounterBuffers 1\n"
956 "MaxCombinedAtomicCounterBuffers 1\n"
957 "MaxAtomicCounterBufferSize 16384\n"
958 "MaxTransformFeedbackBuffers 4\n"
959 "MaxTransformFeedbackInterleavedComponents 64\n"
960 "MaxCullDistances 8\n"
961 "MaxCombinedClipAndCullDistances 8\n"
962 "MaxSamples 4\n"
963
964 "nonInductiveForLoops 1\n"
965 "whileLoops 1\n"
966 "doWhileLoops 1\n"
967 "generalUniformIndexing 1\n"
968 "generalAttributeMatrixVectorIndexing 1\n"
969 "generalVaryingIndexing 1\n"
970 "generalSamplerIndexing 1\n"
971 "generalVariableIndexing 1\n"
972 "generalConstantMatrixVectorIndexing 1\n"
973 ;
974
975//
976// *.conf => this is a config file that can set limits/resources
977//
Tony Barbour6918cd52015-04-09 12:58:51 -0600978bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600979{
980 if (name.size() < 5)
981 return false;
982
983 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
984 ConfigFile = name;
985 return true;
986 }
987
988 return false;
989}
990
991//
992// Parse either a .conf file provided by the user or the default string above.
993//
Tony Barbour6918cd52015-04-09 12:58:51 -0600994void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600995{
996 char** configStrings = 0;
997 char* config = 0;
998 if (ConfigFile.size() > 0) {
999 configStrings = ReadFileData(ConfigFile.c_str());
1000 if (configStrings)
1001 config = *configStrings;
1002 else {
1003 printf("Error opening configuration file; will instead use the default configuration\n");
1004 }
1005 }
1006
1007 if (config == 0) {
1008 config = new char[strlen(DefaultConfig) + 1];
1009 strcpy(config, DefaultConfig);
1010 }
1011
1012 const char* delims = " \t\n\r";
1013 const char* token = strtok(config, delims);
1014 while (token) {
1015 const char* valueStr = strtok(0, delims);
1016 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1017 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1018 return;
1019 }
1020 int value = atoi(valueStr);
1021
1022 if (strcmp(token, "MaxLights") == 0)
1023 Resources.maxLights = value;
1024 else if (strcmp(token, "MaxClipPlanes") == 0)
1025 Resources.maxClipPlanes = value;
1026 else if (strcmp(token, "MaxTextureUnits") == 0)
1027 Resources.maxTextureUnits = value;
1028 else if (strcmp(token, "MaxTextureCoords") == 0)
1029 Resources.maxTextureCoords = value;
1030 else if (strcmp(token, "MaxVertexAttribs") == 0)
1031 Resources.maxVertexAttribs = value;
1032 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1033 Resources.maxVertexUniformComponents = value;
1034 else if (strcmp(token, "MaxVaryingFloats") == 0)
1035 Resources.maxVaryingFloats = value;
1036 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1037 Resources.maxVertexTextureImageUnits = value;
1038 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1039 Resources.maxCombinedTextureImageUnits = value;
1040 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1041 Resources.maxTextureImageUnits = value;
1042 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1043 Resources.maxFragmentUniformComponents = value;
1044 else if (strcmp(token, "MaxDrawBuffers") == 0)
1045 Resources.maxDrawBuffers = value;
1046 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1047 Resources.maxVertexUniformVectors = value;
1048 else if (strcmp(token, "MaxVaryingVectors") == 0)
1049 Resources.maxVaryingVectors = value;
1050 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1051 Resources.maxFragmentUniformVectors = value;
1052 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1053 Resources.maxVertexOutputVectors = value;
1054 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1055 Resources.maxFragmentInputVectors = value;
1056 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1057 Resources.minProgramTexelOffset = value;
1058 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1059 Resources.maxProgramTexelOffset = value;
1060 else if (strcmp(token, "MaxClipDistances") == 0)
1061 Resources.maxClipDistances = value;
1062 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1063 Resources.maxComputeWorkGroupCountX = value;
1064 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1065 Resources.maxComputeWorkGroupCountY = value;
1066 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1067 Resources.maxComputeWorkGroupCountZ = value;
1068 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1069 Resources.maxComputeWorkGroupSizeX = value;
1070 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1071 Resources.maxComputeWorkGroupSizeY = value;
1072 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1073 Resources.maxComputeWorkGroupSizeZ = value;
1074 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1075 Resources.maxComputeUniformComponents = value;
1076 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1077 Resources.maxComputeTextureImageUnits = value;
1078 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1079 Resources.maxComputeImageUniforms = value;
1080 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1081 Resources.maxComputeAtomicCounters = value;
1082 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1083 Resources.maxComputeAtomicCounterBuffers = value;
1084 else if (strcmp(token, "MaxVaryingComponents") == 0)
1085 Resources.maxVaryingComponents = value;
1086 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1087 Resources.maxVertexOutputComponents = value;
1088 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1089 Resources.maxGeometryInputComponents = value;
1090 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1091 Resources.maxGeometryOutputComponents = value;
1092 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1093 Resources.maxFragmentInputComponents = value;
1094 else if (strcmp(token, "MaxImageUnits") == 0)
1095 Resources.maxImageUnits = value;
1096 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1097 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1098 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1099 Resources.maxCombinedShaderOutputResources = value;
1100 else if (strcmp(token, "MaxImageSamples") == 0)
1101 Resources.maxImageSamples = value;
1102 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1103 Resources.maxVertexImageUniforms = value;
1104 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1105 Resources.maxTessControlImageUniforms = value;
1106 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1107 Resources.maxTessEvaluationImageUniforms = value;
1108 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1109 Resources.maxGeometryImageUniforms = value;
1110 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1111 Resources.maxFragmentImageUniforms = value;
1112 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1113 Resources.maxCombinedImageUniforms = value;
1114 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1115 Resources.maxGeometryTextureImageUnits = value;
1116 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1117 Resources.maxGeometryOutputVertices = value;
1118 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1119 Resources.maxGeometryTotalOutputComponents = value;
1120 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1121 Resources.maxGeometryUniformComponents = value;
1122 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1123 Resources.maxGeometryVaryingComponents = value;
1124 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1125 Resources.maxTessControlInputComponents = value;
1126 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1127 Resources.maxTessControlOutputComponents = value;
1128 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1129 Resources.maxTessControlTextureImageUnits = value;
1130 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1131 Resources.maxTessControlUniformComponents = value;
1132 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1133 Resources.maxTessControlTotalOutputComponents = value;
1134 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1135 Resources.maxTessEvaluationInputComponents = value;
1136 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1137 Resources.maxTessEvaluationOutputComponents = value;
1138 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1139 Resources.maxTessEvaluationTextureImageUnits = value;
1140 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1141 Resources.maxTessEvaluationUniformComponents = value;
1142 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1143 Resources.maxTessPatchComponents = value;
1144 else if (strcmp(token, "MaxPatchVertices") == 0)
1145 Resources.maxPatchVertices = value;
1146 else if (strcmp(token, "MaxTessGenLevel") == 0)
1147 Resources.maxTessGenLevel = value;
1148 else if (strcmp(token, "MaxViewports") == 0)
1149 Resources.maxViewports = value;
1150 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1151 Resources.maxVertexAtomicCounters = value;
1152 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1153 Resources.maxTessControlAtomicCounters = value;
1154 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1155 Resources.maxTessEvaluationAtomicCounters = value;
1156 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1157 Resources.maxGeometryAtomicCounters = value;
1158 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1159 Resources.maxFragmentAtomicCounters = value;
1160 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1161 Resources.maxCombinedAtomicCounters = value;
1162 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1163 Resources.maxAtomicCounterBindings = value;
1164 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1165 Resources.maxVertexAtomicCounterBuffers = value;
1166 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1167 Resources.maxTessControlAtomicCounterBuffers = value;
1168 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1169 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1170 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1171 Resources.maxGeometryAtomicCounterBuffers = value;
1172 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1173 Resources.maxFragmentAtomicCounterBuffers = value;
1174 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1175 Resources.maxCombinedAtomicCounterBuffers = value;
1176 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1177 Resources.maxAtomicCounterBufferSize = value;
1178 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1179 Resources.maxTransformFeedbackBuffers = value;
1180 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1181 Resources.maxTransformFeedbackInterleavedComponents = value;
1182 else if (strcmp(token, "MaxCullDistances") == 0)
1183 Resources.maxCullDistances = value;
1184 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1185 Resources.maxCombinedClipAndCullDistances = value;
1186 else if (strcmp(token, "MaxSamples") == 0)
1187 Resources.maxSamples = value;
1188
1189 else if (strcmp(token, "nonInductiveForLoops") == 0)
1190 Resources.limits.nonInductiveForLoops = (value != 0);
1191 else if (strcmp(token, "whileLoops") == 0)
1192 Resources.limits.whileLoops = (value != 0);
1193 else if (strcmp(token, "doWhileLoops") == 0)
1194 Resources.limits.doWhileLoops = (value != 0);
1195 else if (strcmp(token, "generalUniformIndexing") == 0)
1196 Resources.limits.generalUniformIndexing = (value != 0);
1197 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1198 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1199 else if (strcmp(token, "generalVaryingIndexing") == 0)
1200 Resources.limits.generalVaryingIndexing = (value != 0);
1201 else if (strcmp(token, "generalSamplerIndexing") == 0)
1202 Resources.limits.generalSamplerIndexing = (value != 0);
1203 else if (strcmp(token, "generalVariableIndexing") == 0)
1204 Resources.limits.generalVariableIndexing = (value != 0);
1205 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1206 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1207 else
1208 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1209
1210 token = strtok(0, delims);
1211 }
1212 if (configStrings)
1213 FreeFileData(configStrings);
1214}
1215
Tony Barbour6918cd52015-04-09 12:58:51 -06001216void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001217{
1218 if (m_compile_options & EOptionRelaxedErrors)
1219 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1220 if (m_compile_options & EOptionIntermediate)
1221 messages = (EShMessages)(messages | EShMsgAST);
1222 if (m_compile_options & EOptionSuppressWarnings)
1223 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1224}
1225
1226//
1227// Malloc a string of sufficient size and read a string into it.
1228//
Tony Barbour6918cd52015-04-09 12:58:51 -06001229char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001230{
1231 FILE *in;
1232 #if defined(_WIN32) && defined(__GNUC__)
1233 in = fopen(fileName, "r");
1234 int errorCode = in ? 0 : 1;
1235 #else
1236 int errorCode = fopen_s(&in, fileName, "r");
1237 #endif
1238
1239 char *fdata;
1240 int count = 0;
1241 const int maxSourceStrings = 5;
1242 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1243
1244 if (errorCode) {
1245 printf("Error: unable to open input file: %s\n", fileName);
1246 return 0;
1247 }
1248
1249 while (fgetc(in) != EOF)
1250 count++;
1251
1252 fseek(in, 0, SEEK_SET);
1253
1254 if (!(fdata = (char*)malloc(count+2))) {
1255 printf("Error allocating memory\n");
1256 return 0;
1257 }
1258 if (fread(fdata,1,count, in)!=count) {
1259 printf("Error reading input file: %s\n", fileName);
1260 return 0;
1261 }
1262 fdata[count] = '\0';
1263 fclose(in);
1264 if (count == 0) {
1265 return_data[0]=(char*)malloc(count+2);
1266 return_data[0][0]='\0';
1267 m_num_shader_strings = 0;
1268 return return_data;
1269 } else
1270 m_num_shader_strings = 1;
1271
1272 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1273 int ptr_len=0,i=0;
1274 while(count>0){
1275 return_data[i]=(char*)malloc(len+2);
1276 memcpy(return_data[i],fdata+ptr_len,len);
1277 return_data[i][len]='\0';
1278 count-=(len);
1279 ptr_len+=(len);
1280 if(count<len){
1281 if(count==0){
1282 m_num_shader_strings=(i+1);
1283 break;
1284 }
1285 len = count;
1286 }
1287 ++i;
1288 }
1289 return return_data;
1290}
1291
Tony Barbour6918cd52015-04-09 12:58:51 -06001292void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001293{
1294 for(int i=0;i<m_num_shader_strings;i++)
1295 free(data[i]);
1296}
1297
1298//
1299// Deduce the language from the filename. Files must end in one of the
1300// following extensions:
1301//
1302// .vert = vertex
1303// .tesc = tessellation control
1304// .tese = tessellation evaluation
1305// .geom = geometry
1306// .frag = fragment
1307// .comp = compute
1308//
Tony Barbour6918cd52015-04-09 12:58:51 -06001309EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001310{
1311 size_t ext = name.rfind('.');
1312 if (ext == std::string::npos) {
1313 return EShLangVertex;
1314 }
1315
1316 std::string suffix = name.substr(ext + 1, std::string::npos);
1317 if (suffix == "vert")
1318 return EShLangVertex;
1319 else if (suffix == "tesc")
1320 return EShLangTessControl;
1321 else if (suffix == "tese")
1322 return EShLangTessEvaluation;
1323 else if (suffix == "geom")
1324 return EShLangGeometry;
1325 else if (suffix == "frag")
1326 return EShLangFragment;
1327 else if (suffix == "comp")
1328 return EShLangCompute;
1329
1330 return EShLangVertex;
1331}
1332
1333//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001334// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001335//
Tony Barbourd1c35722015-04-16 15:59:00 -06001336EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001337{
1338 switch (shader_type) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001339 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001340 return EShLangVertex;
1341
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001342 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001343 return EShLangTessControl;
1344
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001345 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001346 return EShLangTessEvaluation;
1347
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001348 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001349 return EShLangGeometry;
1350
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001351 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001352 return EShLangFragment;
1353
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001354 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001355 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001356
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001357 default:
1358 return EShLangVertex;
1359 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001360}
1361
1362
1363//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001364// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001365// Return value of false means an error was encountered.
1366//
Tony Barbourd1c35722015-04-16 15:59:00 -06001367bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001368 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001369 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001370{
1371 glslang::TProgram& program = *new glslang::TProgram;
1372 const char *shaderStrings[1];
1373
1374 // TODO: Do we want to load a special config file depending on the
1375 // shader source? Optional name maybe?
1376 // SetConfigFile(fileName);
1377
1378 ProcessConfigFile();
1379
1380 EShMessages messages = EShMsgDefault;
1381 SetMessageOptions(messages);
1382
1383 EShLanguage stage = FindLanguage(shader_type);
1384 glslang::TShader* shader = new glslang::TShader(stage);
1385
1386 shaderStrings[0] = pshader;
1387 shader->setStrings(shaderStrings, 1);
1388
1389 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1390
Cody Northrop195d6622014-11-03 12:54:37 -07001391 if (! (m_compile_options & EOptionSuppressInfolog)) {
1392 puts(shader->getInfoLog());
1393 puts(shader->getInfoDebugLog());
1394 }
1395
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001396 return false; // something didn't work
1397 }
1398
1399 program.addShader(shader);
1400
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001401
1402 //
1403 // Program-level processing...
1404 //
1405
Cody Northrop195d6622014-11-03 12:54:37 -07001406 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001407
Cody Northrop195d6622014-11-03 12:54:37 -07001408 if (! (m_compile_options & EOptionSuppressInfolog)) {
1409 puts(shader->getInfoLog());
1410 puts(shader->getInfoDebugLog());
1411 }
1412
1413 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001414 }
1415
1416 if (m_compile_options & EOptionDumpReflection) {
1417 program.buildReflection();
1418 program.dumpReflection();
1419 }
1420
Cody Northrop5a95b472015-06-03 13:01:54 -06001421 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1422
1423 //
1424 // Test the different modes of SPIR-V modification
1425 //
1426 if (this->m_canonicalize_spv) {
1427 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1428 }
1429
1430 if (this->m_strip_spv) {
1431 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1432 }
1433
1434 if (this->m_do_everything_spv) {
1435 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1436 }
1437
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001438
1439 return true;
1440}
1441
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001442
1443
Tony Barbour6918cd52015-04-09 12:58:51 -06001444VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001445 m_width( 0 ),
1446 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001447 m_data( NULL ),
1448 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001449{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001450}
1451
Tony Barbour6918cd52015-04-09 12:58:51 -06001452VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001453{
1454
1455}
1456
Tony Barbour6918cd52015-04-09 12:58:51 -06001457VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001458{
1459 m_title = copyin.m_title;
1460 m_width = copyin.m_width;
1461 m_height = copyin.m_height;
1462 m_data_size = copyin.m_data_size;
1463 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1464}
1465
Tony Barbour6918cd52015-04-09 12:58:51 -06001466ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001467{
Tony Barbour6918cd52015-04-09 12:58:51 -06001468 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1469 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001470 return output;
1471}
1472
Tony Barbour6918cd52015-04-09 12:58:51 -06001473VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001474{
1475 m_title = rhs.m_title;
1476 m_width = rhs.m_width;
1477 m_height = rhs.m_height;
1478 m_data_size = rhs.m_data_size;
1479 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001480 return *this;
1481}
1482
Tony Barbour6918cd52015-04-09 12:58:51 -06001483int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001484{
1485 if( this->m_data != rhs.m_data) return 0;
1486 return 1;
1487}
1488
1489// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001490int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001491{
1492 if( this->m_data_size < rhs.m_data_size ) return 1;
1493 return 0;
1494}
1495