blob: 9f4966aa532e8531dfad4dbf8508b32810de9748 [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 Elliott1a3845b2015-07-06 14:33:04 -060031#include "vk_wsi_swapchain.h"
32#include "vk_wsi_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
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060038// Command-line options
39enum TOptions {
40 EOptionNone = 0x000,
41 EOptionIntermediate = 0x001,
42 EOptionSuppressInfolog = 0x002,
43 EOptionMemoryLeakMode = 0x004,
44 EOptionRelaxedErrors = 0x008,
45 EOptionGiveWarnings = 0x010,
46 EOptionLinkProgram = 0x020,
47 EOptionMultiThreaded = 0x040,
48 EOptionDumpConfig = 0x080,
49 EOptionDumpReflection = 0x100,
50 EOptionSuppressWarnings = 0x200,
51 EOptionDumpVersions = 0x400,
Cody Northrop3bfd27c2015-03-17 15:55:58 -060052 EOptionSpv = 0x800,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060053 EOptionDefaultDesktop = 0x1000,
54};
55
Chia-I Wuf8693382015-04-16 22:02:10 +080056class TestFrameworkVkPresent
57{
58public:
59 TestFrameworkVkPresent(vk_testing::Device &device);
60
61 void Run();
Jon Ashburn07daee72015-05-21 18:13:33 -060062 void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst);
Chia-I Wuf8693382015-04-16 22:02:10 +080063 void CreateMyWindow();
64 void CreateSwapChain();
65 void TearDown();
Tony Barbour3d69c9e2015-05-20 16:53:31 -060066#ifdef _WIN32
67 static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
68#endif
69
Chia-I Wuf8693382015-04-16 22:02:10 +080070
71protected:
72 vk_testing::Device &m_device;
73 vk_testing::Queue &m_queue;
Dana Jansens233a0ea2015-07-30 13:04:16 -070074 vk_testing::CmdPool m_cmdpool;
Chia-I Wuf8693382015-04-16 22:02:10 +080075 vk_testing::CmdBuffer m_cmdbuf;
76
77private:
Tony Barbour3d69c9e2015-05-20 16:53:31 -060078#ifdef _WIN32
79 HINSTANCE m_connection; // hInstance - Windows Instance
80 HWND m_window; // hWnd - window handle
81
82#else
Chia-I Wuf8693382015-04-16 22:02:10 +080083 xcb_connection_t *m_connection;
84 xcb_screen_t *m_screen;
85 xcb_window_t m_window;
86 xcb_intern_atom_reply_t *m_atom_wm_delete_window;
Tony Barbour3d69c9e2015-05-20 16:53:31 -060087#endif
Courtney Goeltzenleuchterd6079ec2015-04-22 10:09:35 -060088 std::list<VkTestImageRecord> m_images;
Chia-I Wuf8693382015-04-16 22:02:10 +080089
Jon Ashburn07daee72015-05-21 18:13:33 -060090 PFN_vkCreateSwapChainWSI m_fpCreateSwapChainWSI;
91 PFN_vkDestroySwapChainWSI m_fpDestroySwapChainWSI;
92 PFN_vkGetSwapChainInfoWSI m_fpGetSwapChainInfoWSI;
93 PFN_vkQueuePresentWSI m_fpQueuePresentWSI;
94
Chia-I Wuf8693382015-04-16 22:02:10 +080095 VkSwapChainWSI m_swap_chain;
Ian Elliott1a3845b2015-07-06 14:33:04 -060096 std::vector<VkSwapChainImagePropertiesWSI> m_persistent_images;
Tony-LunarG399dfca2015-05-19 14:08:26 -060097 int m_current_buffer;
Chia-I Wuf8693382015-04-16 22:02:10 +080098
99 bool m_quit;
100 bool m_pause;
101
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600102 int m_width;
103 int m_height;
Chia-I Wuf8693382015-04-16 22:02:10 +0800104
105 std::list<VkTestImageRecord>::iterator m_display_image;
106
107 void Display();
108 void HandleEvent(xcb_generic_event_t *event);
109};
110
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600111#ifndef _WIN32
112
113#include <errno.h>
114
115int fopen_s(
116 FILE** pFile,
117 const char* filename,
118 const char* mode
119)
120{
121 if (!pFile || !filename || !mode) {
122 return EINVAL;
123 }
124
125 FILE* f = fopen(filename, mode);
126 if (! f) {
127 if (errno != 0) {
128 return errno;
129 } else {
130 return ENOENT;
131 }
132 }
133 *pFile = f;
134
135 return 0;
136}
137
138#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600139
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600140
141
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600142// Set up environment for GLSL compiler
143// Must be done once per process
144void TestEnvironment::SetUp()
145{
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600146 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600147 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800148
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600149 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600150}
151
152void TestEnvironment::TearDown()
153{
154 glslang::FinalizeProcess();
155}
156
Tony Barbour6918cd52015-04-09 12:58:51 -0600157VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600158 m_compile_options( 0 ),
159 m_num_shader_strings( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600160{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600161
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600162}
163
Tony Barbour6918cd52015-04-09 12:58:51 -0600164VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600165{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600166
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600167}
168
169// Define all the static elements
Cody Northropa3673cf2015-06-09 13:00:45 -0600170bool VkTestFramework::m_show_images = false;
171bool VkTestFramework::m_save_images = false;
172bool VkTestFramework::m_compare_images = false;
173bool VkTestFramework::m_use_glsl = false;
174bool VkTestFramework::m_canonicalize_spv = false;
175bool VkTestFramework::m_strip_spv = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600176bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour6918cd52015-04-09 12:58:51 -0600177int VkTestFramework::m_width = 0;
178int VkTestFramework::m_height = 0;
179std::list<VkTestImageRecord> VkTestFramework::m_images;
180std::list<VkTestImageRecord>::iterator VkTestFramework::m_display_image;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600181int m_display_image_idx = 0;
182
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600183bool VkTestFramework::optionMatch(const char* option, char* optionLine)
184{
185 if (strncmp(option, optionLine, strlen(option)) == 0)
186 return true;
187 else
188 return false;
189}
190
Tony Barbour6918cd52015-04-09 12:58:51 -0600191void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600192{
193 int i, n;
194
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600195 for (i=1, n=1; i< *argc; i++) {
196 if (optionMatch("--show-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600197 m_show_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600198 else if (optionMatch("--save-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600199 m_save_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600200 else if (optionMatch("--no-SPV", argv[i]))
201 m_use_glsl = true;
202 else if (optionMatch("--strip-SPV", argv[i]))
203 m_strip_spv = true;
204 else if (optionMatch("--canonicalize-SPV", argv[i]))
205 m_canonicalize_spv = true;
206 else if (optionMatch("--compare-images", argv[i]))
Tony Barbour247bf372014-10-30 14:29:04 -0600207 m_compare_images = true;
Tony Barbour247bf372014-10-30 14:29:04 -0600208
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600209 else if (optionMatch("--help", argv[i]) ||
210 optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700211 printf("\nOther options:\n");
212 printf("\t--show-images\n"
213 "\t\tDisplay test images in viewer after tests complete.\n");
214 printf("\t--save-images\n"
215 "\t\tSave tests images as ppm files in current working directory.\n"
216 "\t\tUsed to generate golden images for compare-images.\n");
217 printf("\t--compare-images\n"
218 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barboura98d3932014-12-11 09:52:49 -0700219 "\t\tAlso saves the generated test image in current working\n"
220 "\t\t\tdirectory but only if the image is different from the golden\n"
221 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
222 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700223 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600224 printf("\t--no-SPV\n"
225 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600226 printf("\t--strip-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600227 "\t\tStrip SPIR-V debug information (line numbers, names, etc).\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600228 printf("\t--canonicalize-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600229 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600230 exit(0);
231 } else {
232 printf("\nUnrecognized option: %s\n", argv[i]);
233 printf("\nUse --help or -h for option list.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700234 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700235 }
236
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600237 /*
238 * Since the above "consume" inputs, update argv
239 * so that it contains the trimmed list of args for glutInit
240 */
241
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600242 argv[n] = argv[i];
243 n++;
244 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600245}
246
Tony Barbour6918cd52015-04-09 12:58:51 -0600247void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600248{
249 string filename;
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600250 VkResult err;
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600251 uint32_t x, y;
Tony Barbour6918cd52015-04-09 12:58:51 -0600252 VkImageObj displayImage(image->device());
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600253 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbour84d448c2015-04-02 14:02:33 -0600254
Tony Barboure65788f2015-07-21 17:01:42 -0600255 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 -0600256 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600257
258 filename.append(basename);
259 filename.append(".ppm");
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600260
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600261 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600262 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600263 };
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600264 VkSubresourceLayout sr_layout;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600265
Tony Barbour59a47322015-06-24 16:06:58 -0600266 err = vkGetImageSubresourceLayout(image->device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600267 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600268
Tony Barbour84d448c2015-04-02 14:02:33 -0600269 char *ptr;
Chia-I Wu681d7a02015-07-03 13:44:34 +0800270 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600271 ptr += sr_layout.offset;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600272 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600273 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
274
275 file << "P6\n";
Tony Barbour84d448c2015-04-02 14:02:33 -0600276 file << displayImage.width() << "\n";
277 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600278 file << 255 << "\n";
279
Tony Barbour84d448c2015-04-02 14:02:33 -0600280 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700281 const int *row = (const int *) ptr;
282 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600283
Tony Barbourd1c35722015-04-16 15:59:00 -0600284 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700285 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600286 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700287 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
288 file.write((char *) &swapped, 3);
289 row++;
290 }
291 }
Tony Barbourd1c35722015-04-16 15:59:00 -0600292 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700293 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600294 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700295 file.write((char *) row, 3);
296 row++;
297 }
298 }
299 else {
300 printf("Unrecognized image format - will not write image files");
301 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600302 }
303
304 ptr += sr_layout.rowPitch;
305 }
306
307 file.close();
Chia-I Wu681d7a02015-07-03 13:44:34 +0800308 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600309}
310
Tony Barbour6918cd52015-04-09 12:58:51 -0600311void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour247bf372014-10-30 14:29:04 -0600312{
313
314 MagickWand *magick_wand_1;
315 MagickWand *magick_wand_2;
316 MagickWand *compare_wand;
317 MagickBooleanType status;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600318 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600319 double differenz;
320
Tony Barbour4ab45422014-12-10 17:00:20 -0700321 if (getenv("RENDERTEST_GOLDEN_DIR"))
322 {
323 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
324 }
325
Tony Barbour247bf372014-10-30 14:29:04 -0600326 MagickWandGenesis();
327 magick_wand_1=NewMagickWand();
328 sprintf(testimage,"%s.ppm",basename);
329 status=MagickReadImage(magick_wand_1,testimage);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600330 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour247bf372014-10-30 14:29:04 -0600331
332
333 MagickWandGenesis();
334 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700335 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600336 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600337 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour247bf372014-10-30 14:29:04 -0600338
Tony Barbour247bf372014-10-30 14:29:04 -0600339 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
340 if (differenz != 0.0)
341 {
342 char difference[256];
343
344 sprintf(difference,"%s-diff.ppm",basename);
345 status = MagickWriteImage(compare_wand, difference);
346 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
347 }
348 DestroyMagickWand(compare_wand);
349
350 DestroyMagickWand(magick_wand_1);
351 DestroyMagickWand(magick_wand_2);
352 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700353
354 if (differenz == 0.0)
355 {
356 /*
357 * If test image and golden image match, we do not need to
358 * keep around the test image.
359 */
360 remove(testimage);
361 }
Tony Barbour247bf372014-10-30 14:29:04 -0600362}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600363
Tony Barbour6918cd52015-04-09 12:58:51 -0600364void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600365{
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600366 VkResult err;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600367 VkSubresourceLayout sr_layout;
368 char *ptr;
369 VkTestImageRecord record;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600370 VkImageObj displayImage(image->device());
371 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
372
Cody Northropc9a69912015-06-18 17:05:15 -0600373 displayImage.init(image->extent().width, image->extent().height, image->format(), VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT, VK_IMAGE_TILING_LINEAR, reqs);
374
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600375 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600376
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600377 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600378 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600379 };
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600380
Tony Barbour59a47322015-06-24 16:06:58 -0600381 err = vkGetImageSubresourceLayout(displayImage.device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600382 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600383
Chia-I Wu681d7a02015-07-03 13:44:34 +0800384 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600385 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600386
387 ptr += sr_layout.offset;
388
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600389 record.m_title.append(comment);
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600390 record.m_width = displayImage.width();
391 record.m_height = displayImage.height();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600392 // TODO: Need to make this more robust to handle different image formats
Tony-LunarG399dfca2015-05-19 14:08:26 -0600393 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600394 record.m_data = malloc(record.m_data_size);
395 memcpy(record.m_data, ptr, record.m_data_size);
396 m_images.push_back(record);
397 m_display_image = --m_images.end();
398
Chia-I Wu681d7a02015-07-03 13:44:34 +0800399 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600400}
401
Tony Barbour6918cd52015-04-09 12:58:51 -0600402void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600403{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600404 for (int32_t i = 0; i < images.size(); i++) {
405 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600406 }
407}
408
Tony Barbour6918cd52015-04-09 12:58:51 -0600409void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600410{
411 const ::testing::TestInfo* const test_info =
412 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600413 ostringstream filestream;
414 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600415
Tony Barbour247bf372014-10-30 14:29:04 -0600416 m_width = 40;
417
418 if (strcmp(test_info->name(), m_testName.c_str())) {
419 filestream << test_info->name();
420 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700421 m_frameNum = 2;
422 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600423 }
424 else {
425 filestream << test_info->name() << "-" << m_frameNum;
426 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700427 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600428 }
429
Tony Barbour247bf372014-10-30 14:29:04 -0600430 // ToDo - scrub string for bad characters
431
432 if (m_save_images || m_compare_images) {
433 WritePPM(filename.c_str(), image);
434 if (m_compare_images) {
435 Compare(filename.c_str(), image);
436 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600437 }
438
439 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600440 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600441 }
442}
443
Chia-I Wuf8693382015-04-16 22:02:10 +0800444TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
445 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700446 m_queue(*m_device.graphics_queues()[0]),
Dana Jansens233a0ea2015-07-30 13:04:16 -0700447 m_cmdpool(m_device, vk_testing::CmdPool::create_info(m_device.graphics_queue_node_index_)),
448 m_cmdbuf(m_device, vk_testing::CmdBuffer::create_info(m_cmdpool.handle()))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600449{
Tony Barbour96db8822015-02-25 12:28:39 -0700450 m_quit = false;
451 m_pause = false;
452 m_width = 0;
453 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600454}
455
Tony Barbour6918cd52015-04-09 12:58:51 -0600456void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600457{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600458 VkResult U_ASSERT_ONLY err;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600459 vk_testing::Buffer buf;
460 void *dest_ptr;
461
462 if (m_persistent_images.size() != 2) {
463 return;
464 }
465
466 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Cody Northrop7fb43862015-06-22 14:56:14 -0600467 buf.init_as_src(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800468 dest_ptr = buf.memory().map();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600469 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800470 buf.memory().unmap();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600471
472 m_cmdbuf.begin();
473
474 VkBufferImageCopy region = {};
475 region.imageExtent.height = m_display_image->m_height;
476 region.imageExtent.width = m_display_image->m_width;
477 region.imageExtent.depth = 1;
478
Chia-I Wube2b9172015-07-03 11:49:42 +0800479 vkCmdCopyBufferToImage(m_cmdbuf.handle(),
Chia-I Wu681d7a02015-07-03 13:44:34 +0800480 buf.handle(),
Tony-LunarG399dfca2015-05-19 14:08:26 -0600481 m_persistent_images[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
482 1, &region);
483 m_cmdbuf.end();
484
485 VkCmdBuffer cmdBufs[1];
Chia-I Wube2b9172015-07-03 11:49:42 +0800486 cmdBufs[0] = m_cmdbuf.handle();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600487
Tony Barbour67e99152015-07-10 14:10:27 -0600488 VkFence nullFence = { VK_NULL_HANDLE };
489 vkQueueSubmit(m_queue.handle(), 1, cmdBufs, nullFence);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600490 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700491
Chia-I Wuf8693382015-04-16 22:02:10 +0800492 VkPresentInfoWSI present = {};
Ian Elliott1a3845b2015-07-06 14:33:04 -0600493 // FIXME: WRITE THE REAL CODE!!!
494 // FIXME: WRITE THE REAL CODE!!!
495 // FIXME: WRITE THE REAL CODE!!!
496 // FIXME: WRITE THE REAL CODE!!!
497 present.sType = VK_STRUCTURE_TYPE_QUEUE_PRESENT_INFO_WSI;
Tony Barbour96db8822015-02-25 12:28:39 -0700498
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600499#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800500 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700501 XCB_PROP_MODE_REPLACE,
502 m_window,
503 XCB_ATOM_WM_NAME,
504 XCB_ATOM_STRING,
505 8,
506 m_display_image->m_title.size(),
507 m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600508#endif
Jon Ashburn07daee72015-05-21 18:13:33 -0600509
Chia-I Wudf12ffd2015-07-03 10:53:18 +0800510 err = m_fpQueuePresentWSI(m_queue.handle(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700511 assert(!err);
512
513 m_queue.wait();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600514 m_current_buffer = (m_current_buffer + 1) % 2;
Tony Barbour96db8822015-02-25 12:28:39 -0700515
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600516}
517
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600518#ifdef _WIN32
Tony-LunarG399dfca2015-05-19 14:08:26 -0600519# define PREVIOUSLY_DOWN 1<<29
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600520// MS-Windows event handling function:
521LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
522 UINT uMsg,
523 WPARAM wParam,
524 LPARAM lParam)
525{
526
527 switch(uMsg)
528 {
529 case WM_CLOSE:
530 PostQuitMessage(0);
531 break;
532
533 case WM_PAINT:
534 {
535 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
536 if (me) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600537 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600538 me->Display();
539 }
540 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600541 break;
542
543 case WM_KEYDOWN:
544 {
545 if (lParam & (PREVIOUSLY_DOWN)){
546 break;
547 }
548 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
549 // the window, we put the this pointer into the window's user data so we could get it back now
550 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
551 switch (wParam)
552 {
553 case VK_ESCAPE: me->m_quit = true;
554 break;
555
556 case VK_LEFT: // left arrow key
557 if (me->m_display_image == me->m_images.begin()) {
558 me->m_display_image = --me->m_images.end();
559 }
560 else {
561 --me->m_display_image;
562 }
563 break;
564
565 case VK_RIGHT: // right arrow key
566 ++me->m_display_image;
567 if (me->m_display_image == me->m_images.end()) {
568 me->m_display_image = me->m_images.begin();
569 }
570 break;
571
572 default:
573 break;
574 }
575 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
576 me->Display();
577 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600578 }
579 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
580}
581
582void TestFrameworkVkPresent::Run()
583{
584 MSG msg; // message
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600585
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600586 /* main message loop*/
Tony-LunarG399dfca2015-05-19 14:08:26 -0600587 while(! m_quit) {
588 GetMessage(&msg, m_window, 0, 0);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600589 if (msg.message == WM_QUIT) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600590 m_quit = true; //if found, quit app
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600591 } else {
592 /* Translate and dispatch to event queue*/
593 TranslateMessage(&msg);
594 DispatchMessage(&msg);
595 }
596 }
597}
598
599#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600600void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600601{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600602 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700603 switch (event_code) {
604 case XCB_EXPOSE:
605 Display(); // TODO: handle resize
606 break;
607 case XCB_CLIENT_MESSAGE:
608 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
609 (m_atom_wm_delete_window)->atom) {
610 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600611 }
612 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700613 case XCB_KEY_RELEASE:
614 {
615 const xcb_key_release_event_t *key =
616 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600617
Tony Barbour96db8822015-02-25 12:28:39 -0700618 switch (key->detail) {
619 case 0x9: // Escape
620 m_quit = true;
621 break;
622 case 0x71: // left arrow key
623 if (m_display_image == m_images.begin()) {
624 m_display_image = --m_images.end();
625 } else {
626 --m_display_image;
627 }
628 break;
629 case 0x72: // right arrow key
630 ++m_display_image;
631 if (m_display_image == m_images.end()) {
632 m_display_image = m_images.begin();
633 }
634 break;
635 case 0x41:
636 m_pause = !m_pause;
637 break;
638 }
639 Display();
640 }
641 break;
642 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600643 break;
644 }
Tony Barbour96db8822015-02-25 12:28:39 -0700645}
646
Tony Barbour6918cd52015-04-09 12:58:51 -0600647void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700648{
Chia-I Wuf8693382015-04-16 22:02:10 +0800649 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700650
651 while (! m_quit) {
652 xcb_generic_event_t *event;
653
654 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800655 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700656 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800657 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700658 }
659 if (event) {
660 HandleEvent(event);
661 free(event);
662 }
663 }
664}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600665#endif // _WIN32
Tony Barbour96db8822015-02-25 12:28:39 -0700666
Chia-I Wuf8693382015-04-16 22:02:10 +0800667void TestFrameworkVkPresent::CreateSwapChain()
Tony Barbour96db8822015-02-25 12:28:39 -0700668{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600669 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700670
Tony-LunarG399dfca2015-05-19 14:08:26 -0600671 m_display_image = m_images.begin();
672 m_current_buffer = 0;
673
Ian Elliott1a3845b2015-07-06 14:33:04 -0600674 // FIXME: WRITE THE REAL CODE!!!
675 // FIXME: WRITE THE REAL CODE!!!
676 // FIXME: WRITE THE REAL CODE!!!
677 // FIXME: WRITE THE REAL CODE!!!
678 VkSurfaceDescriptionWindowWSI surface_description;
Tony Barbour3d83f492015-07-28 10:23:02 -0600679
Ian Elliott1a3845b2015-07-06 14:33:04 -0600680 surface_description.sType = VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_WSI;
681 surface_description.pNext = NULL;
682#ifdef _WIN32
683 surface_description.platform = VK_PLATFORM_WIN32_WSI;
684 surface_description.pPlatformHandle = m_connection;
685#else // _WIN32
Tony Barbour3d83f492015-07-28 10:23:02 -0600686 VkPlatformHandleXcbWSI platform_handle_xcb;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600687 platform_handle_xcb.connection = m_connection;
688 platform_handle_xcb.root = m_screen->root;
689 surface_description.platform = VK_PLATFORM_XCB_WSI;
690 surface_description.pPlatformHandle = &platform_handle_xcb;
691#endif // _WIN32
692 surface_description.pPlatformWindow = (void *) (intptr_t) m_window;
693
Chia-I Wuf8693382015-04-16 22:02:10 +0800694 VkSwapChainCreateInfoWSI swap_chain = {};
695 swap_chain.sType = VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600696 swap_chain.pNext = NULL;
697 // FIXME: WRITE THE REAL CODE!!!
698 // FIXME: WRITE THE REAL CODE!!!
699 // FIXME: WRITE THE REAL CODE!!!
700 // FIXME: WRITE THE REAL CODE!!!
701 swap_chain.pSurfaceDescription =
702 (VkSurfaceDescriptionWSI*) &surface_description;
Chia-I Wuf8693382015-04-16 22:02:10 +0800703 swap_chain.imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
704 swap_chain.imageExtent.width = m_width;
705 swap_chain.imageExtent.height = m_height;
706 swap_chain.imageArraySize = 1;
Cody Northrope2baad22015-06-09 15:56:56 -0600707 // Note: Addition of color attachment is a workaround needed for some implementations
708 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT |
709 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
Chia-I Wuf8693382015-04-16 22:02:10 +0800710
Chia-I Wuf368b602015-07-03 10:41:20 +0800711 err = m_fpCreateSwapChainWSI(m_device.handle(), &swap_chain, &m_swap_chain);
Chia-I Wuf8693382015-04-16 22:02:10 +0800712 assert(!err);
713
Ian Elliott1a3845b2015-07-06 14:33:04 -0600714 VkSwapChainImagePropertiesWSI infos[2];
715 size_t size = sizeof(VkSwapChainImagePropertiesWSI) * m_images.size() * 2;
716 std::vector<VkSwapChainImagePropertiesWSI> persistent_images;
Jon Ashburn07daee72015-05-21 18:13:33 -0600717 persistent_images.resize(m_images.size());
Ian Elliott1a3845b2015-07-06 14:33:04 -0600718 err = m_fpGetSwapChainInfoWSI(m_device.handle(), m_swap_chain,
719 VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600720 &size, &infos);
Ian Elliott1a3845b2015-07-06 14:33:04 -0600721 assert(!err && size == sizeof(VkSwapChainImagePropertiesWSI) * 2);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600722 m_persistent_images.push_back(infos[0]);
723 m_persistent_images.push_back(infos[1]);
Tony Barbour96db8822015-02-25 12:28:39 -0700724}
725
Jon Ashburn07daee72015-05-21 18:13:33 -0600726void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -0700727{
Jon Ashburn07daee72015-05-21 18:13:33 -0600728 m_fpCreateSwapChainWSI = (PFN_vkCreateSwapChainWSI) vkGetInstanceProcAddr(inst, "vkCreateSwapChainWSI");
729 ASSERT_TRUE(m_fpCreateSwapChainWSI != NULL) << "vkGetInstanceProcAddr failed to find vkCreateSwapChainWSI";
730
731 m_fpDestroySwapChainWSI = (PFN_vkDestroySwapChainWSI) vkGetInstanceProcAddr(inst, "vkDestroySwapChainWSI");
732 ASSERT_TRUE(m_fpDestroySwapChainWSI != NULL) << "vkGetInstanceProcAddr failed to find vkDestroySwapChainWSI";
733
734 m_fpGetSwapChainInfoWSI = (PFN_vkGetSwapChainInfoWSI) vkGetInstanceProcAddr(inst, "vkGetSwapChainInfoWSI");
735 ASSERT_TRUE(m_fpGetSwapChainInfoWSI != NULL) << "vkGetInstanceProcAddr failed to find vkGetSwapChainInfoWSI";
736
737 m_fpQueuePresentWSI = (PFN_vkQueuePresentWSI) vkGetInstanceProcAddr(inst, "vkQueuePresentWSI");
738 ASSERT_TRUE(m_fpQueuePresentWSI != NULL) << "vkGetInstanceProcAddr failed to find vkQueuePresentWSI";
739
Tony Barbour96db8822015-02-25 12:28:39 -0700740 m_images = imagesIn;
741}
742
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600743#ifdef _WIN32
744void TestFrameworkVkPresent::CreateMyWindow()
745{
746 WNDCLASSEX win_class;
747 // const ::testing::TestInfo* const test_info =
748 // ::testing::UnitTest::GetInstance()->current_test_info();
749 m_connection = GetModuleHandle(NULL);
750
751 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
752 it != m_images.end(); it++) {
753 if (m_width < it->m_width)
754 m_width = it->m_width;
755 if (m_height < it->m_height)
756 m_height = it->m_height;
757 }
758 // Initialize the window class structure:
759 win_class.cbSize = sizeof(WNDCLASSEX);
760 win_class.style = CS_HREDRAW | CS_VREDRAW;
761 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
762 win_class.cbClsExtra = 0;
763 win_class.cbWndExtra = 0;
764 win_class.hInstance = m_connection; // hInstance
765 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
766 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
767 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
768 win_class.lpszMenuName = NULL;
769 win_class.lpszClassName = "Test";
770 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
771 // Register window class:
772 if (!RegisterClassEx(&win_class)) {
773 // It didn't work, so try to give a useful error:
774 printf("Unexpected error trying to start the application!\n");
775 fflush(stdout);
776 exit(1);
777 }
778 // Create window with the registered class:
779 m_window = CreateWindowEx(0,
780 "Test", // class name
781 "Test", // app name
782 WS_OVERLAPPEDWINDOW | // window style
783 WS_VISIBLE |
784 WS_SYSMENU,
785 100,100, // x/y coords
786 m_width, // width
787 m_height, // height
788 NULL, // handle to parent
789 NULL, // handle to menu
790 m_connection, // hInstance
791 NULL); // no extra parameters
792
793 if (!m_window) {
794 // It didn't work, so try to give a useful error:
795 DWORD error = GetLastError();
796 char message[120];
797 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
798 MessageBox(NULL, message, "Error", MB_OK);
799 exit(1);
800 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600801 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
802 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600803}
804#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600805void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -0700806{
Chia-I Wuf8693382015-04-16 22:02:10 +0800807 const xcb_setup_t *setup;
808 xcb_screen_iterator_t iter;
809 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -0700810 uint32_t value_mask, value_list[32];
811
Chia-I Wuf8693382015-04-16 22:02:10 +0800812 m_connection = xcb_connect(NULL, &scr);
813
814 setup = xcb_get_setup(m_connection);
815 iter = xcb_setup_roots_iterator(setup);
816 while (scr-- > 0)
817 xcb_screen_next(&iter);
818
819 m_screen = iter.data;
820
821 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
822 it != m_images.end(); it++) {
823 if (m_width < it->m_width)
824 m_width = it->m_width;
825 if (m_height < it->m_height)
826 m_height = it->m_height;
827 }
828
829 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700830
831 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +0800832 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -0700833 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
834 XCB_EVENT_MASK_EXPOSURE |
835 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
836
Chia-I Wuf8693382015-04-16 22:02:10 +0800837 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700838 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800839 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -0700840 0, 0, m_width, m_height, 0,
841 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800842 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -0700843 value_mask, value_list);
844
845 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +0800846 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -0700847 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +0800848 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -0700849
Chia-I Wuf8693382015-04-16 22:02:10 +0800850 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
851 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -0700852
Chia-I Wuf8693382015-04-16 22:02:10 +0800853 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -0700854 m_window, (*reply).atom, 4, 32, 1,
855 &(*m_atom_wm_delete_window).atom);
856 free(reply);
857
Chia-I Wuf8693382015-04-16 22:02:10 +0800858 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -0700859}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600860#endif
Tony Barbour96db8822015-02-25 12:28:39 -0700861
Tony Barbour6918cd52015-04-09 12:58:51 -0600862void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -0700863{
Ian Elliott1a3845b2015-07-06 14:33:04 -0600864 m_fpDestroySwapChainWSI(m_device.handle(), m_swap_chain);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600865#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800866 xcb_destroy_window(m_connection, m_window);
867 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600868#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600869}
870
Tony Barbour6918cd52015-04-09 12:58:51 -0600871void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600872{
873 if (m_images.size() == 0) return;
874
Chia-I Wuf8693382015-04-16 22:02:10 +0800875 vk_testing::Environment env;
876 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -0700877 {
Chia-I Wuf8693382015-04-16 22:02:10 +0800878 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -0700879
Jon Ashburn07daee72015-05-21 18:13:33 -0600880 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600881 vkPresent.CreateMyWindow();
Chia-I Wuf8693382015-04-16 22:02:10 +0800882 vkPresent.CreateSwapChain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600883 vkPresent.Run();
884 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -0700885 }
Chia-I Wuf8693382015-04-16 22:02:10 +0800886 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600887}
888
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600889//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600890// These are the default resources for TBuiltInResources, used for both
891// - parsing this string for the case where the user didn't supply one
892// - dumping out a template for user construction of a config file
893//
894static const char* DefaultConfig =
895 "MaxLights 32\n"
896 "MaxClipPlanes 6\n"
897 "MaxTextureUnits 32\n"
898 "MaxTextureCoords 32\n"
899 "MaxVertexAttribs 64\n"
900 "MaxVertexUniformComponents 4096\n"
901 "MaxVaryingFloats 64\n"
902 "MaxVertexTextureImageUnits 32\n"
903 "MaxCombinedTextureImageUnits 80\n"
904 "MaxTextureImageUnits 32\n"
905 "MaxFragmentUniformComponents 4096\n"
906 "MaxDrawBuffers 32\n"
907 "MaxVertexUniformVectors 128\n"
908 "MaxVaryingVectors 8\n"
909 "MaxFragmentUniformVectors 16\n"
910 "MaxVertexOutputVectors 16\n"
911 "MaxFragmentInputVectors 15\n"
912 "MinProgramTexelOffset -8\n"
913 "MaxProgramTexelOffset 7\n"
914 "MaxClipDistances 8\n"
915 "MaxComputeWorkGroupCountX 65535\n"
916 "MaxComputeWorkGroupCountY 65535\n"
917 "MaxComputeWorkGroupCountZ 65535\n"
918 "MaxComputeWorkGroupSizeX 1024\n"
919 "MaxComputeWorkGroupSizeY 1024\n"
920 "MaxComputeWorkGroupSizeZ 64\n"
921 "MaxComputeUniformComponents 1024\n"
922 "MaxComputeTextureImageUnits 16\n"
923 "MaxComputeImageUniforms 8\n"
924 "MaxComputeAtomicCounters 8\n"
925 "MaxComputeAtomicCounterBuffers 1\n"
926 "MaxVaryingComponents 60\n"
927 "MaxVertexOutputComponents 64\n"
928 "MaxGeometryInputComponents 64\n"
929 "MaxGeometryOutputComponents 128\n"
930 "MaxFragmentInputComponents 128\n"
931 "MaxImageUnits 8\n"
932 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
933 "MaxCombinedShaderOutputResources 8\n"
934 "MaxImageSamples 0\n"
935 "MaxVertexImageUniforms 0\n"
936 "MaxTessControlImageUniforms 0\n"
937 "MaxTessEvaluationImageUniforms 0\n"
938 "MaxGeometryImageUniforms 0\n"
939 "MaxFragmentImageUniforms 8\n"
940 "MaxCombinedImageUniforms 8\n"
941 "MaxGeometryTextureImageUnits 16\n"
942 "MaxGeometryOutputVertices 256\n"
943 "MaxGeometryTotalOutputComponents 1024\n"
944 "MaxGeometryUniformComponents 1024\n"
945 "MaxGeometryVaryingComponents 64\n"
946 "MaxTessControlInputComponents 128\n"
947 "MaxTessControlOutputComponents 128\n"
948 "MaxTessControlTextureImageUnits 16\n"
949 "MaxTessControlUniformComponents 1024\n"
950 "MaxTessControlTotalOutputComponents 4096\n"
951 "MaxTessEvaluationInputComponents 128\n"
952 "MaxTessEvaluationOutputComponents 128\n"
953 "MaxTessEvaluationTextureImageUnits 16\n"
954 "MaxTessEvaluationUniformComponents 1024\n"
955 "MaxTessPatchComponents 120\n"
956 "MaxPatchVertices 32\n"
957 "MaxTessGenLevel 64\n"
958 "MaxViewports 16\n"
959 "MaxVertexAtomicCounters 0\n"
960 "MaxTessControlAtomicCounters 0\n"
961 "MaxTessEvaluationAtomicCounters 0\n"
962 "MaxGeometryAtomicCounters 0\n"
963 "MaxFragmentAtomicCounters 8\n"
964 "MaxCombinedAtomicCounters 8\n"
965 "MaxAtomicCounterBindings 1\n"
966 "MaxVertexAtomicCounterBuffers 0\n"
967 "MaxTessControlAtomicCounterBuffers 0\n"
968 "MaxTessEvaluationAtomicCounterBuffers 0\n"
969 "MaxGeometryAtomicCounterBuffers 0\n"
970 "MaxFragmentAtomicCounterBuffers 1\n"
971 "MaxCombinedAtomicCounterBuffers 1\n"
972 "MaxAtomicCounterBufferSize 16384\n"
973 "MaxTransformFeedbackBuffers 4\n"
974 "MaxTransformFeedbackInterleavedComponents 64\n"
975 "MaxCullDistances 8\n"
976 "MaxCombinedClipAndCullDistances 8\n"
977 "MaxSamples 4\n"
978
979 "nonInductiveForLoops 1\n"
980 "whileLoops 1\n"
981 "doWhileLoops 1\n"
982 "generalUniformIndexing 1\n"
983 "generalAttributeMatrixVectorIndexing 1\n"
984 "generalVaryingIndexing 1\n"
985 "generalSamplerIndexing 1\n"
986 "generalVariableIndexing 1\n"
987 "generalConstantMatrixVectorIndexing 1\n"
988 ;
989
990//
991// *.conf => this is a config file that can set limits/resources
992//
Tony Barbour6918cd52015-04-09 12:58:51 -0600993bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600994{
995 if (name.size() < 5)
996 return false;
997
998 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
999 ConfigFile = name;
1000 return true;
1001 }
1002
1003 return false;
1004}
1005
1006//
1007// Parse either a .conf file provided by the user or the default string above.
1008//
Tony Barbour6918cd52015-04-09 12:58:51 -06001009void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001010{
1011 char** configStrings = 0;
1012 char* config = 0;
1013 if (ConfigFile.size() > 0) {
1014 configStrings = ReadFileData(ConfigFile.c_str());
1015 if (configStrings)
1016 config = *configStrings;
1017 else {
1018 printf("Error opening configuration file; will instead use the default configuration\n");
1019 }
1020 }
1021
1022 if (config == 0) {
1023 config = new char[strlen(DefaultConfig) + 1];
1024 strcpy(config, DefaultConfig);
1025 }
1026
1027 const char* delims = " \t\n\r";
1028 const char* token = strtok(config, delims);
1029 while (token) {
1030 const char* valueStr = strtok(0, delims);
1031 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1032 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1033 return;
1034 }
1035 int value = atoi(valueStr);
1036
1037 if (strcmp(token, "MaxLights") == 0)
1038 Resources.maxLights = value;
1039 else if (strcmp(token, "MaxClipPlanes") == 0)
1040 Resources.maxClipPlanes = value;
1041 else if (strcmp(token, "MaxTextureUnits") == 0)
1042 Resources.maxTextureUnits = value;
1043 else if (strcmp(token, "MaxTextureCoords") == 0)
1044 Resources.maxTextureCoords = value;
1045 else if (strcmp(token, "MaxVertexAttribs") == 0)
1046 Resources.maxVertexAttribs = value;
1047 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1048 Resources.maxVertexUniformComponents = value;
1049 else if (strcmp(token, "MaxVaryingFloats") == 0)
1050 Resources.maxVaryingFloats = value;
1051 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1052 Resources.maxVertexTextureImageUnits = value;
1053 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1054 Resources.maxCombinedTextureImageUnits = value;
1055 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1056 Resources.maxTextureImageUnits = value;
1057 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1058 Resources.maxFragmentUniformComponents = value;
1059 else if (strcmp(token, "MaxDrawBuffers") == 0)
1060 Resources.maxDrawBuffers = value;
1061 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1062 Resources.maxVertexUniformVectors = value;
1063 else if (strcmp(token, "MaxVaryingVectors") == 0)
1064 Resources.maxVaryingVectors = value;
1065 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1066 Resources.maxFragmentUniformVectors = value;
1067 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1068 Resources.maxVertexOutputVectors = value;
1069 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1070 Resources.maxFragmentInputVectors = value;
1071 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1072 Resources.minProgramTexelOffset = value;
1073 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1074 Resources.maxProgramTexelOffset = value;
1075 else if (strcmp(token, "MaxClipDistances") == 0)
1076 Resources.maxClipDistances = value;
1077 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1078 Resources.maxComputeWorkGroupCountX = value;
1079 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1080 Resources.maxComputeWorkGroupCountY = value;
1081 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1082 Resources.maxComputeWorkGroupCountZ = value;
1083 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1084 Resources.maxComputeWorkGroupSizeX = value;
1085 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1086 Resources.maxComputeWorkGroupSizeY = value;
1087 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1088 Resources.maxComputeWorkGroupSizeZ = value;
1089 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1090 Resources.maxComputeUniformComponents = value;
1091 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1092 Resources.maxComputeTextureImageUnits = value;
1093 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1094 Resources.maxComputeImageUniforms = value;
1095 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1096 Resources.maxComputeAtomicCounters = value;
1097 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1098 Resources.maxComputeAtomicCounterBuffers = value;
1099 else if (strcmp(token, "MaxVaryingComponents") == 0)
1100 Resources.maxVaryingComponents = value;
1101 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1102 Resources.maxVertexOutputComponents = value;
1103 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1104 Resources.maxGeometryInputComponents = value;
1105 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1106 Resources.maxGeometryOutputComponents = value;
1107 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1108 Resources.maxFragmentInputComponents = value;
1109 else if (strcmp(token, "MaxImageUnits") == 0)
1110 Resources.maxImageUnits = value;
1111 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1112 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1113 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1114 Resources.maxCombinedShaderOutputResources = value;
1115 else if (strcmp(token, "MaxImageSamples") == 0)
1116 Resources.maxImageSamples = value;
1117 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1118 Resources.maxVertexImageUniforms = value;
1119 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1120 Resources.maxTessControlImageUniforms = value;
1121 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1122 Resources.maxTessEvaluationImageUniforms = value;
1123 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1124 Resources.maxGeometryImageUniforms = value;
1125 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1126 Resources.maxFragmentImageUniforms = value;
1127 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1128 Resources.maxCombinedImageUniforms = value;
1129 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1130 Resources.maxGeometryTextureImageUnits = value;
1131 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1132 Resources.maxGeometryOutputVertices = value;
1133 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1134 Resources.maxGeometryTotalOutputComponents = value;
1135 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1136 Resources.maxGeometryUniformComponents = value;
1137 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1138 Resources.maxGeometryVaryingComponents = value;
1139 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1140 Resources.maxTessControlInputComponents = value;
1141 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1142 Resources.maxTessControlOutputComponents = value;
1143 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1144 Resources.maxTessControlTextureImageUnits = value;
1145 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1146 Resources.maxTessControlUniformComponents = value;
1147 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1148 Resources.maxTessControlTotalOutputComponents = value;
1149 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1150 Resources.maxTessEvaluationInputComponents = value;
1151 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1152 Resources.maxTessEvaluationOutputComponents = value;
1153 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1154 Resources.maxTessEvaluationTextureImageUnits = value;
1155 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1156 Resources.maxTessEvaluationUniformComponents = value;
1157 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1158 Resources.maxTessPatchComponents = value;
1159 else if (strcmp(token, "MaxPatchVertices") == 0)
1160 Resources.maxPatchVertices = value;
1161 else if (strcmp(token, "MaxTessGenLevel") == 0)
1162 Resources.maxTessGenLevel = value;
1163 else if (strcmp(token, "MaxViewports") == 0)
1164 Resources.maxViewports = value;
1165 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1166 Resources.maxVertexAtomicCounters = value;
1167 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1168 Resources.maxTessControlAtomicCounters = value;
1169 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1170 Resources.maxTessEvaluationAtomicCounters = value;
1171 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1172 Resources.maxGeometryAtomicCounters = value;
1173 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1174 Resources.maxFragmentAtomicCounters = value;
1175 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1176 Resources.maxCombinedAtomicCounters = value;
1177 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1178 Resources.maxAtomicCounterBindings = value;
1179 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1180 Resources.maxVertexAtomicCounterBuffers = value;
1181 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1182 Resources.maxTessControlAtomicCounterBuffers = value;
1183 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1184 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1185 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1186 Resources.maxGeometryAtomicCounterBuffers = value;
1187 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1188 Resources.maxFragmentAtomicCounterBuffers = value;
1189 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1190 Resources.maxCombinedAtomicCounterBuffers = value;
1191 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1192 Resources.maxAtomicCounterBufferSize = value;
1193 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1194 Resources.maxTransformFeedbackBuffers = value;
1195 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1196 Resources.maxTransformFeedbackInterleavedComponents = value;
1197 else if (strcmp(token, "MaxCullDistances") == 0)
1198 Resources.maxCullDistances = value;
1199 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1200 Resources.maxCombinedClipAndCullDistances = value;
1201 else if (strcmp(token, "MaxSamples") == 0)
1202 Resources.maxSamples = value;
1203
1204 else if (strcmp(token, "nonInductiveForLoops") == 0)
1205 Resources.limits.nonInductiveForLoops = (value != 0);
1206 else if (strcmp(token, "whileLoops") == 0)
1207 Resources.limits.whileLoops = (value != 0);
1208 else if (strcmp(token, "doWhileLoops") == 0)
1209 Resources.limits.doWhileLoops = (value != 0);
1210 else if (strcmp(token, "generalUniformIndexing") == 0)
1211 Resources.limits.generalUniformIndexing = (value != 0);
1212 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1213 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1214 else if (strcmp(token, "generalVaryingIndexing") == 0)
1215 Resources.limits.generalVaryingIndexing = (value != 0);
1216 else if (strcmp(token, "generalSamplerIndexing") == 0)
1217 Resources.limits.generalSamplerIndexing = (value != 0);
1218 else if (strcmp(token, "generalVariableIndexing") == 0)
1219 Resources.limits.generalVariableIndexing = (value != 0);
1220 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1221 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1222 else
1223 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1224
1225 token = strtok(0, delims);
1226 }
1227 if (configStrings)
1228 FreeFileData(configStrings);
1229}
1230
Tony Barbour6918cd52015-04-09 12:58:51 -06001231void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001232{
1233 if (m_compile_options & EOptionRelaxedErrors)
1234 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1235 if (m_compile_options & EOptionIntermediate)
1236 messages = (EShMessages)(messages | EShMsgAST);
1237 if (m_compile_options & EOptionSuppressWarnings)
1238 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1239}
1240
1241//
1242// Malloc a string of sufficient size and read a string into it.
1243//
Tony Barbour6918cd52015-04-09 12:58:51 -06001244char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001245{
1246 FILE *in;
1247 #if defined(_WIN32) && defined(__GNUC__)
1248 in = fopen(fileName, "r");
1249 int errorCode = in ? 0 : 1;
1250 #else
1251 int errorCode = fopen_s(&in, fileName, "r");
1252 #endif
1253
1254 char *fdata;
1255 int count = 0;
1256 const int maxSourceStrings = 5;
1257 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1258
1259 if (errorCode) {
1260 printf("Error: unable to open input file: %s\n", fileName);
1261 return 0;
1262 }
1263
1264 while (fgetc(in) != EOF)
1265 count++;
1266
1267 fseek(in, 0, SEEK_SET);
1268
1269 if (!(fdata = (char*)malloc(count+2))) {
1270 printf("Error allocating memory\n");
1271 return 0;
1272 }
1273 if (fread(fdata,1,count, in)!=count) {
1274 printf("Error reading input file: %s\n", fileName);
1275 return 0;
1276 }
1277 fdata[count] = '\0';
1278 fclose(in);
1279 if (count == 0) {
1280 return_data[0]=(char*)malloc(count+2);
1281 return_data[0][0]='\0';
1282 m_num_shader_strings = 0;
1283 return return_data;
1284 } else
1285 m_num_shader_strings = 1;
1286
1287 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1288 int ptr_len=0,i=0;
1289 while(count>0){
1290 return_data[i]=(char*)malloc(len+2);
1291 memcpy(return_data[i],fdata+ptr_len,len);
1292 return_data[i][len]='\0';
1293 count-=(len);
1294 ptr_len+=(len);
1295 if(count<len){
1296 if(count==0){
1297 m_num_shader_strings=(i+1);
1298 break;
1299 }
1300 len = count;
1301 }
1302 ++i;
1303 }
1304 return return_data;
1305}
1306
Tony Barbour6918cd52015-04-09 12:58:51 -06001307void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001308{
1309 for(int i=0;i<m_num_shader_strings;i++)
1310 free(data[i]);
1311}
1312
1313//
1314// Deduce the language from the filename. Files must end in one of the
1315// following extensions:
1316//
1317// .vert = vertex
1318// .tesc = tessellation control
1319// .tese = tessellation evaluation
1320// .geom = geometry
1321// .frag = fragment
1322// .comp = compute
1323//
Tony Barbour6918cd52015-04-09 12:58:51 -06001324EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001325{
1326 size_t ext = name.rfind('.');
1327 if (ext == std::string::npos) {
1328 return EShLangVertex;
1329 }
1330
1331 std::string suffix = name.substr(ext + 1, std::string::npos);
1332 if (suffix == "vert")
1333 return EShLangVertex;
1334 else if (suffix == "tesc")
1335 return EShLangTessControl;
1336 else if (suffix == "tese")
1337 return EShLangTessEvaluation;
1338 else if (suffix == "geom")
1339 return EShLangGeometry;
1340 else if (suffix == "frag")
1341 return EShLangFragment;
1342 else if (suffix == "comp")
1343 return EShLangCompute;
1344
1345 return EShLangVertex;
1346}
1347
1348//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001349// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001350//
Tony Barbourd1c35722015-04-16 15:59:00 -06001351EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001352{
1353 switch (shader_type) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001354 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001355 return EShLangVertex;
1356
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001357 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001358 return EShLangTessControl;
1359
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001360 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001361 return EShLangTessEvaluation;
1362
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001363 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001364 return EShLangGeometry;
1365
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001366 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001367 return EShLangFragment;
1368
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001369 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001370 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001371
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001372 default:
1373 return EShLangVertex;
1374 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001375}
1376
1377
1378//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001379// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001380// Return value of false means an error was encountered.
1381//
Tony Barbourd1c35722015-04-16 15:59:00 -06001382bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001383 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001384 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001385{
1386 glslang::TProgram& program = *new glslang::TProgram;
1387 const char *shaderStrings[1];
1388
1389 // TODO: Do we want to load a special config file depending on the
1390 // shader source? Optional name maybe?
1391 // SetConfigFile(fileName);
1392
1393 ProcessConfigFile();
1394
1395 EShMessages messages = EShMsgDefault;
1396 SetMessageOptions(messages);
1397
1398 EShLanguage stage = FindLanguage(shader_type);
1399 glslang::TShader* shader = new glslang::TShader(stage);
1400
1401 shaderStrings[0] = pshader;
1402 shader->setStrings(shaderStrings, 1);
1403
1404 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1405
Cody Northrop195d6622014-11-03 12:54:37 -07001406 if (! (m_compile_options & EOptionSuppressInfolog)) {
1407 puts(shader->getInfoLog());
1408 puts(shader->getInfoDebugLog());
1409 }
1410
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001411 return false; // something didn't work
1412 }
1413
1414 program.addShader(shader);
1415
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001416
1417 //
1418 // Program-level processing...
1419 //
1420
Cody Northrop195d6622014-11-03 12:54:37 -07001421 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001422
Cody Northrop195d6622014-11-03 12:54:37 -07001423 if (! (m_compile_options & EOptionSuppressInfolog)) {
1424 puts(shader->getInfoLog());
1425 puts(shader->getInfoDebugLog());
1426 }
1427
1428 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001429 }
1430
1431 if (m_compile_options & EOptionDumpReflection) {
1432 program.buildReflection();
1433 program.dumpReflection();
1434 }
1435
Cody Northrop5a95b472015-06-03 13:01:54 -06001436 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1437
1438 //
1439 // Test the different modes of SPIR-V modification
1440 //
1441 if (this->m_canonicalize_spv) {
1442 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1443 }
1444
1445 if (this->m_strip_spv) {
1446 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1447 }
1448
1449 if (this->m_do_everything_spv) {
1450 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1451 }
1452
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001453
1454 return true;
1455}
1456
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001457
1458
Tony Barbour6918cd52015-04-09 12:58:51 -06001459VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001460 m_width( 0 ),
1461 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001462 m_data( NULL ),
1463 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001464{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001465}
1466
Tony Barbour6918cd52015-04-09 12:58:51 -06001467VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001468{
1469
1470}
1471
Tony Barbour6918cd52015-04-09 12:58:51 -06001472VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001473{
1474 m_title = copyin.m_title;
1475 m_width = copyin.m_width;
1476 m_height = copyin.m_height;
1477 m_data_size = copyin.m_data_size;
1478 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1479}
1480
Tony Barbour6918cd52015-04-09 12:58:51 -06001481ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001482{
Tony Barbour6918cd52015-04-09 12:58:51 -06001483 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1484 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001485 return output;
1486}
1487
Tony Barbour6918cd52015-04-09 12:58:51 -06001488VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001489{
1490 m_title = rhs.m_title;
1491 m_width = rhs.m_width;
1492 m_height = rhs.m_height;
1493 m_data_size = rhs.m_data_size;
1494 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001495 return *this;
1496}
1497
Tony Barbour6918cd52015-04-09 12:58:51 -06001498int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001499{
1500 if( this->m_data != rhs.m_data) return 0;
1501 return 1;
1502}
1503
1504// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001505int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001506{
1507 if( this->m_data_size < rhs.m_data_size ) return 1;
1508 return 0;
1509}
1510