blob: 3ea9bdf47d10166464781aa49f98c746333f692f [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;
74 vk_testing::CmdBuffer m_cmdbuf;
75
76private:
Tony Barbour3d69c9e2015-05-20 16:53:31 -060077#ifdef _WIN32
78 HINSTANCE m_connection; // hInstance - Windows Instance
79 HWND m_window; // hWnd - window handle
80
81#else
Chia-I Wuf8693382015-04-16 22:02:10 +080082 xcb_connection_t *m_connection;
83 xcb_screen_t *m_screen;
84 xcb_window_t m_window;
85 xcb_intern_atom_reply_t *m_atom_wm_delete_window;
Tony Barbour3d69c9e2015-05-20 16:53:31 -060086#endif
Courtney Goeltzenleuchterd6079ec2015-04-22 10:09:35 -060087 std::list<VkTestImageRecord> m_images;
Chia-I Wuf8693382015-04-16 22:02:10 +080088
Jon Ashburn07daee72015-05-21 18:13:33 -060089 PFN_vkCreateSwapChainWSI m_fpCreateSwapChainWSI;
90 PFN_vkDestroySwapChainWSI m_fpDestroySwapChainWSI;
91 PFN_vkGetSwapChainInfoWSI m_fpGetSwapChainInfoWSI;
92 PFN_vkQueuePresentWSI m_fpQueuePresentWSI;
93
Chia-I Wuf8693382015-04-16 22:02:10 +080094 VkSwapChainWSI m_swap_chain;
Ian Elliott1a3845b2015-07-06 14:33:04 -060095 std::vector<VkSwapChainImagePropertiesWSI> m_persistent_images;
Tony-LunarG399dfca2015-05-19 14:08:26 -060096 int m_current_buffer;
Chia-I Wuf8693382015-04-16 22:02:10 +080097
98 bool m_quit;
99 bool m_pause;
100
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600101 int m_width;
102 int m_height;
Chia-I Wuf8693382015-04-16 22:02:10 +0800103
104 std::list<VkTestImageRecord>::iterator m_display_image;
105
106 void Display();
107 void HandleEvent(xcb_generic_event_t *event);
108};
109
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600110#ifndef _WIN32
111
112#include <errno.h>
113
114int fopen_s(
115 FILE** pFile,
116 const char* filename,
117 const char* mode
118)
119{
120 if (!pFile || !filename || !mode) {
121 return EINVAL;
122 }
123
124 FILE* f = fopen(filename, mode);
125 if (! f) {
126 if (errno != 0) {
127 return errno;
128 } else {
129 return ENOENT;
130 }
131 }
132 *pFile = f;
133
134 return 0;
135}
136
137#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600138
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600139
140
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600141// Set up environment for GLSL compiler
142// Must be done once per process
143void TestEnvironment::SetUp()
144{
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600145 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600146 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800147
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600148 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600149}
150
151void TestEnvironment::TearDown()
152{
153 glslang::FinalizeProcess();
154}
155
Tony Barbour6918cd52015-04-09 12:58:51 -0600156VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600157 m_compile_options( 0 ),
158 m_num_shader_strings( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600159{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600160
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600161}
162
Tony Barbour6918cd52015-04-09 12:58:51 -0600163VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600164{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600165
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600166}
167
168// Define all the static elements
Cody Northropa3673cf2015-06-09 13:00:45 -0600169bool VkTestFramework::m_show_images = false;
170bool VkTestFramework::m_save_images = false;
171bool VkTestFramework::m_compare_images = false;
172bool VkTestFramework::m_use_glsl = false;
173bool VkTestFramework::m_canonicalize_spv = false;
174bool VkTestFramework::m_strip_spv = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600175bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour6918cd52015-04-09 12:58:51 -0600176int VkTestFramework::m_width = 0;
177int VkTestFramework::m_height = 0;
178std::list<VkTestImageRecord> VkTestFramework::m_images;
179std::list<VkTestImageRecord>::iterator VkTestFramework::m_display_image;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600180int m_display_image_idx = 0;
181
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600182bool VkTestFramework::optionMatch(const char* option, char* optionLine)
183{
184 if (strncmp(option, optionLine, strlen(option)) == 0)
185 return true;
186 else
187 return false;
188}
189
Tony Barbour6918cd52015-04-09 12:58:51 -0600190void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600191{
192 int i, n;
193
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600194 for (i=1, n=1; i< *argc; i++) {
195 if (optionMatch("--show-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600196 m_show_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600197 else if (optionMatch("--save-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600198 m_save_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600199 else if (optionMatch("--no-SPV", argv[i]))
200 m_use_glsl = true;
201 else if (optionMatch("--strip-SPV", argv[i]))
202 m_strip_spv = true;
203 else if (optionMatch("--canonicalize-SPV", argv[i]))
204 m_canonicalize_spv = true;
205 else if (optionMatch("--compare-images", argv[i]))
Tony Barbour247bf372014-10-30 14:29:04 -0600206 m_compare_images = true;
Tony Barbour247bf372014-10-30 14:29:04 -0600207
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600208 else if (optionMatch("--help", argv[i]) ||
209 optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700210 printf("\nOther options:\n");
211 printf("\t--show-images\n"
212 "\t\tDisplay test images in viewer after tests complete.\n");
213 printf("\t--save-images\n"
214 "\t\tSave tests images as ppm files in current working directory.\n"
215 "\t\tUsed to generate golden images for compare-images.\n");
216 printf("\t--compare-images\n"
217 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barboura98d3932014-12-11 09:52:49 -0700218 "\t\tAlso saves the generated test image in current working\n"
219 "\t\t\tdirectory but only if the image is different from the golden\n"
220 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
221 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700222 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600223 printf("\t--no-SPV\n"
224 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600225 printf("\t--strip-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600226 "\t\tStrip SPIR-V debug information (line numbers, names, etc).\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600227 printf("\t--canonicalize-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600228 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600229 exit(0);
230 } else {
231 printf("\nUnrecognized option: %s\n", argv[i]);
232 printf("\nUse --help or -h for option list.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700233 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700234 }
235
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600236 /*
237 * Since the above "consume" inputs, update argv
238 * so that it contains the trimmed list of args for glutInit
239 */
240
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600241 argv[n] = argv[i];
242 n++;
243 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600244}
245
Tony Barbour6918cd52015-04-09 12:58:51 -0600246void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600247{
248 string filename;
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600249 VkResult err;
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600250 uint32_t x, y;
Tony Barbour6918cd52015-04-09 12:58:51 -0600251 VkImageObj displayImage(image->device());
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600252 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbour84d448c2015-04-02 14:02:33 -0600253
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600254 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, VK_IMAGE_TILING_LINEAR, reqs);
Tony Barbour84d448c2015-04-02 14:02:33 -0600255 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600256
257 filename.append(basename);
258 filename.append(".ppm");
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600259
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600260 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600261 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600262 };
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600263 VkSubresourceLayout sr_layout;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600264
Tony Barbour59a47322015-06-24 16:06:58 -0600265 err = vkGetImageSubresourceLayout(image->device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600266 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600267
Tony Barbour84d448c2015-04-02 14:02:33 -0600268 char *ptr;
Chia-I Wu681d7a02015-07-03 13:44:34 +0800269 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600270 ptr += sr_layout.offset;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600271 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600272 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
273
274 file << "P6\n";
Tony Barbour84d448c2015-04-02 14:02:33 -0600275 file << displayImage.width() << "\n";
276 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600277 file << 255 << "\n";
278
Tony Barbour84d448c2015-04-02 14:02:33 -0600279 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700280 const int *row = (const int *) ptr;
281 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600282
Tony Barbourd1c35722015-04-16 15:59:00 -0600283 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700284 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600285 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700286 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
287 file.write((char *) &swapped, 3);
288 row++;
289 }
290 }
Tony Barbourd1c35722015-04-16 15:59:00 -0600291 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700292 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600293 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700294 file.write((char *) row, 3);
295 row++;
296 }
297 }
298 else {
299 printf("Unrecognized image format - will not write image files");
300 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600301 }
302
303 ptr += sr_layout.rowPitch;
304 }
305
306 file.close();
Chia-I Wu681d7a02015-07-03 13:44:34 +0800307 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600308}
309
Tony Barbour6918cd52015-04-09 12:58:51 -0600310void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour247bf372014-10-30 14:29:04 -0600311{
312
313 MagickWand *magick_wand_1;
314 MagickWand *magick_wand_2;
315 MagickWand *compare_wand;
316 MagickBooleanType status;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600317 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600318 double differenz;
319
Tony Barbour4ab45422014-12-10 17:00:20 -0700320 if (getenv("RENDERTEST_GOLDEN_DIR"))
321 {
322 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
323 }
324
Tony Barbour247bf372014-10-30 14:29:04 -0600325 MagickWandGenesis();
326 magick_wand_1=NewMagickWand();
327 sprintf(testimage,"%s.ppm",basename);
328 status=MagickReadImage(magick_wand_1,testimage);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600329 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour247bf372014-10-30 14:29:04 -0600330
331
332 MagickWandGenesis();
333 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700334 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600335 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600336 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour247bf372014-10-30 14:29:04 -0600337
Tony Barbour247bf372014-10-30 14:29:04 -0600338 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
339 if (differenz != 0.0)
340 {
341 char difference[256];
342
343 sprintf(difference,"%s-diff.ppm",basename);
344 status = MagickWriteImage(compare_wand, difference);
345 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
346 }
347 DestroyMagickWand(compare_wand);
348
349 DestroyMagickWand(magick_wand_1);
350 DestroyMagickWand(magick_wand_2);
351 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700352
353 if (differenz == 0.0)
354 {
355 /*
356 * If test image and golden image match, we do not need to
357 * keep around the test image.
358 */
359 remove(testimage);
360 }
Tony Barbour247bf372014-10-30 14:29:04 -0600361}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600362
Tony Barbour6918cd52015-04-09 12:58:51 -0600363void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600364{
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600365 VkResult err;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600366 VkSubresourceLayout sr_layout;
367 char *ptr;
368 VkTestImageRecord record;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600369 VkImageObj displayImage(image->device());
370 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
371
Cody Northropc9a69912015-06-18 17:05:15 -0600372 displayImage.init(image->extent().width, image->extent().height, image->format(), VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT, VK_IMAGE_TILING_LINEAR, reqs);
373
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600374 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600375
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600376 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600377 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600378 };
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600379
Tony Barbour59a47322015-06-24 16:06:58 -0600380 err = vkGetImageSubresourceLayout(displayImage.device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600381 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600382
Chia-I Wu681d7a02015-07-03 13:44:34 +0800383 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600384 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600385
386 ptr += sr_layout.offset;
387
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600388 record.m_title.append(comment);
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600389 record.m_width = displayImage.width();
390 record.m_height = displayImage.height();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600391 // TODO: Need to make this more robust to handle different image formats
Tony-LunarG399dfca2015-05-19 14:08:26 -0600392 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600393 record.m_data = malloc(record.m_data_size);
394 memcpy(record.m_data, ptr, record.m_data_size);
395 m_images.push_back(record);
396 m_display_image = --m_images.end();
397
Chia-I Wu681d7a02015-07-03 13:44:34 +0800398 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600399}
400
Tony Barbour6918cd52015-04-09 12:58:51 -0600401void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600402{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600403 for (int32_t i = 0; i < images.size(); i++) {
404 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600405 }
406}
407
Tony Barbour6918cd52015-04-09 12:58:51 -0600408void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600409{
410 const ::testing::TestInfo* const test_info =
411 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600412 ostringstream filestream;
413 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600414
Tony Barbour247bf372014-10-30 14:29:04 -0600415 m_width = 40;
416
417 if (strcmp(test_info->name(), m_testName.c_str())) {
418 filestream << test_info->name();
419 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700420 m_frameNum = 2;
421 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600422 }
423 else {
424 filestream << test_info->name() << "-" << m_frameNum;
425 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700426 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600427 }
428
Tony Barbour247bf372014-10-30 14:29:04 -0600429 // ToDo - scrub string for bad characters
430
431 if (m_save_images || m_compare_images) {
432 WritePPM(filename.c_str(), image);
433 if (m_compare_images) {
434 Compare(filename.c_str(), image);
435 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600436 }
437
438 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600439 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600440 }
441}
442
Chia-I Wuf8693382015-04-16 22:02:10 +0800443TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
444 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700445 m_queue(*m_device.graphics_queues()[0]),
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600446 m_cmdbuf(m_device, vk_testing::CmdBuffer::create_info(m_device.graphics_queue_node_index_))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600447{
Tony Barbour96db8822015-02-25 12:28:39 -0700448 m_quit = false;
449 m_pause = false;
450 m_width = 0;
451 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600452}
453
Tony Barbour6918cd52015-04-09 12:58:51 -0600454void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600455{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600456 VkResult U_ASSERT_ONLY err;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600457 vk_testing::Buffer buf;
458 void *dest_ptr;
459
460 if (m_persistent_images.size() != 2) {
461 return;
462 }
463
464 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Cody Northrop7fb43862015-06-22 14:56:14 -0600465 buf.init_as_src(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800466 dest_ptr = buf.memory().map();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600467 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800468 buf.memory().unmap();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600469
470 m_cmdbuf.begin();
471
472 VkBufferImageCopy region = {};
473 region.imageExtent.height = m_display_image->m_height;
474 region.imageExtent.width = m_display_image->m_width;
475 region.imageExtent.depth = 1;
476
Chia-I Wube2b9172015-07-03 11:49:42 +0800477 vkCmdCopyBufferToImage(m_cmdbuf.handle(),
Chia-I Wu681d7a02015-07-03 13:44:34 +0800478 buf.handle(),
Tony-LunarG399dfca2015-05-19 14:08:26 -0600479 m_persistent_images[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
480 1, &region);
481 m_cmdbuf.end();
482
483 VkCmdBuffer cmdBufs[1];
Chia-I Wube2b9172015-07-03 11:49:42 +0800484 cmdBufs[0] = m_cmdbuf.handle();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600485
Tony Barbour67e99152015-07-10 14:10:27 -0600486 VkFence nullFence = { VK_NULL_HANDLE };
487 vkQueueSubmit(m_queue.handle(), 1, cmdBufs, nullFence);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600488 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700489
Chia-I Wuf8693382015-04-16 22:02:10 +0800490 VkPresentInfoWSI present = {};
Ian Elliott1a3845b2015-07-06 14:33:04 -0600491 // FIXME: WRITE THE REAL CODE!!!
492 // FIXME: WRITE THE REAL CODE!!!
493 // FIXME: WRITE THE REAL CODE!!!
494 // FIXME: WRITE THE REAL CODE!!!
495 present.sType = VK_STRUCTURE_TYPE_QUEUE_PRESENT_INFO_WSI;
Tony Barbour96db8822015-02-25 12:28:39 -0700496
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600497#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800498 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700499 XCB_PROP_MODE_REPLACE,
500 m_window,
501 XCB_ATOM_WM_NAME,
502 XCB_ATOM_STRING,
503 8,
504 m_display_image->m_title.size(),
505 m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600506#endif
Jon Ashburn07daee72015-05-21 18:13:33 -0600507
Chia-I Wudf12ffd2015-07-03 10:53:18 +0800508 err = m_fpQueuePresentWSI(m_queue.handle(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700509 assert(!err);
510
511 m_queue.wait();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600512 m_current_buffer = (m_current_buffer + 1) % 2;
Tony Barbour96db8822015-02-25 12:28:39 -0700513
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600514}
515
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600516#ifdef _WIN32
Tony-LunarG399dfca2015-05-19 14:08:26 -0600517# define PREVIOUSLY_DOWN 1<<29
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600518// MS-Windows event handling function:
519LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
520 UINT uMsg,
521 WPARAM wParam,
522 LPARAM lParam)
523{
524
525 switch(uMsg)
526 {
527 case WM_CLOSE:
528 PostQuitMessage(0);
529 break;
530
531 case WM_PAINT:
532 {
533 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
534 if (me) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600535 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600536 me->Display();
537 }
538 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600539 break;
540
541 case WM_KEYDOWN:
542 {
543 if (lParam & (PREVIOUSLY_DOWN)){
544 break;
545 }
546 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
547 // the window, we put the this pointer into the window's user data so we could get it back now
548 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
549 switch (wParam)
550 {
551 case VK_ESCAPE: me->m_quit = true;
552 break;
553
554 case VK_LEFT: // left arrow key
555 if (me->m_display_image == me->m_images.begin()) {
556 me->m_display_image = --me->m_images.end();
557 }
558 else {
559 --me->m_display_image;
560 }
561 break;
562
563 case VK_RIGHT: // right arrow key
564 ++me->m_display_image;
565 if (me->m_display_image == me->m_images.end()) {
566 me->m_display_image = me->m_images.begin();
567 }
568 break;
569
570 default:
571 break;
572 }
573 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
574 me->Display();
575 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600576 }
577 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
578}
579
580void TestFrameworkVkPresent::Run()
581{
582 MSG msg; // message
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600583
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600584 /* main message loop*/
Tony-LunarG399dfca2015-05-19 14:08:26 -0600585 while(! m_quit) {
586 GetMessage(&msg, m_window, 0, 0);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600587 if (msg.message == WM_QUIT) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600588 m_quit = true; //if found, quit app
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600589 } else {
590 /* Translate and dispatch to event queue*/
591 TranslateMessage(&msg);
592 DispatchMessage(&msg);
593 }
594 }
595}
596
597#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600598void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600599{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600600 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700601 switch (event_code) {
602 case XCB_EXPOSE:
603 Display(); // TODO: handle resize
604 break;
605 case XCB_CLIENT_MESSAGE:
606 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
607 (m_atom_wm_delete_window)->atom) {
608 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600609 }
610 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700611 case XCB_KEY_RELEASE:
612 {
613 const xcb_key_release_event_t *key =
614 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600615
Tony Barbour96db8822015-02-25 12:28:39 -0700616 switch (key->detail) {
617 case 0x9: // Escape
618 m_quit = true;
619 break;
620 case 0x71: // left arrow key
621 if (m_display_image == m_images.begin()) {
622 m_display_image = --m_images.end();
623 } else {
624 --m_display_image;
625 }
626 break;
627 case 0x72: // right arrow key
628 ++m_display_image;
629 if (m_display_image == m_images.end()) {
630 m_display_image = m_images.begin();
631 }
632 break;
633 case 0x41:
634 m_pause = !m_pause;
635 break;
636 }
637 Display();
638 }
639 break;
640 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600641 break;
642 }
Tony Barbour96db8822015-02-25 12:28:39 -0700643}
644
Tony Barbour6918cd52015-04-09 12:58:51 -0600645void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700646{
Chia-I Wuf8693382015-04-16 22:02:10 +0800647 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700648
649 while (! m_quit) {
650 xcb_generic_event_t *event;
651
652 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800653 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700654 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800655 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700656 }
657 if (event) {
658 HandleEvent(event);
659 free(event);
660 }
661 }
662}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600663#endif // _WIN32
Tony Barbour96db8822015-02-25 12:28:39 -0700664
Chia-I Wuf8693382015-04-16 22:02:10 +0800665void TestFrameworkVkPresent::CreateSwapChain()
Tony Barbour96db8822015-02-25 12:28:39 -0700666{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600667 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700668
Tony-LunarG399dfca2015-05-19 14:08:26 -0600669 m_display_image = m_images.begin();
670 m_current_buffer = 0;
671
Ian Elliott1a3845b2015-07-06 14:33:04 -0600672 // FIXME: WRITE THE REAL CODE!!!
673 // FIXME: WRITE THE REAL CODE!!!
674 // FIXME: WRITE THE REAL CODE!!!
675 // FIXME: WRITE THE REAL CODE!!!
676 VkSurfaceDescriptionWindowWSI surface_description;
677 VkPlatformHandleXcbWSI platform_handle_xcb;
678 surface_description.sType = VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_WSI;
679 surface_description.pNext = NULL;
680#ifdef _WIN32
681 surface_description.platform = VK_PLATFORM_WIN32_WSI;
682 surface_description.pPlatformHandle = m_connection;
683#else // _WIN32
684 platform_handle_xcb.connection = m_connection;
685 platform_handle_xcb.root = m_screen->root;
686 surface_description.platform = VK_PLATFORM_XCB_WSI;
687 surface_description.pPlatformHandle = &platform_handle_xcb;
688#endif // _WIN32
689 surface_description.pPlatformWindow = (void *) (intptr_t) m_window;
690
Chia-I Wuf8693382015-04-16 22:02:10 +0800691 VkSwapChainCreateInfoWSI swap_chain = {};
692 swap_chain.sType = VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI;
Ian Elliott1a3845b2015-07-06 14:33:04 -0600693 swap_chain.pNext = NULL;
694 // FIXME: WRITE THE REAL CODE!!!
695 // FIXME: WRITE THE REAL CODE!!!
696 // FIXME: WRITE THE REAL CODE!!!
697 // FIXME: WRITE THE REAL CODE!!!
698 swap_chain.pSurfaceDescription =
699 (VkSurfaceDescriptionWSI*) &surface_description;
Chia-I Wuf8693382015-04-16 22:02:10 +0800700 swap_chain.imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
701 swap_chain.imageExtent.width = m_width;
702 swap_chain.imageExtent.height = m_height;
703 swap_chain.imageArraySize = 1;
Cody Northrope2baad22015-06-09 15:56:56 -0600704 // Note: Addition of color attachment is a workaround needed for some implementations
705 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT |
706 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
Chia-I Wuf8693382015-04-16 22:02:10 +0800707
Chia-I Wuf368b602015-07-03 10:41:20 +0800708 err = m_fpCreateSwapChainWSI(m_device.handle(), &swap_chain, &m_swap_chain);
Chia-I Wuf8693382015-04-16 22:02:10 +0800709 assert(!err);
710
Ian Elliott1a3845b2015-07-06 14:33:04 -0600711 VkSwapChainImagePropertiesWSI infos[2];
712 size_t size = sizeof(VkSwapChainImagePropertiesWSI) * m_images.size() * 2;
713 std::vector<VkSwapChainImagePropertiesWSI> persistent_images;
Jon Ashburn07daee72015-05-21 18:13:33 -0600714 persistent_images.resize(m_images.size());
Ian Elliott1a3845b2015-07-06 14:33:04 -0600715 err = m_fpGetSwapChainInfoWSI(m_device.handle(), m_swap_chain,
716 VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600717 &size, &infos);
Ian Elliott1a3845b2015-07-06 14:33:04 -0600718 assert(!err && size == sizeof(VkSwapChainImagePropertiesWSI) * 2);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600719 m_persistent_images.push_back(infos[0]);
720 m_persistent_images.push_back(infos[1]);
Tony Barbour96db8822015-02-25 12:28:39 -0700721}
722
Jon Ashburn07daee72015-05-21 18:13:33 -0600723void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -0700724{
Jon Ashburn07daee72015-05-21 18:13:33 -0600725 m_fpCreateSwapChainWSI = (PFN_vkCreateSwapChainWSI) vkGetInstanceProcAddr(inst, "vkCreateSwapChainWSI");
726 ASSERT_TRUE(m_fpCreateSwapChainWSI != NULL) << "vkGetInstanceProcAddr failed to find vkCreateSwapChainWSI";
727
728 m_fpDestroySwapChainWSI = (PFN_vkDestroySwapChainWSI) vkGetInstanceProcAddr(inst, "vkDestroySwapChainWSI");
729 ASSERT_TRUE(m_fpDestroySwapChainWSI != NULL) << "vkGetInstanceProcAddr failed to find vkDestroySwapChainWSI";
730
731 m_fpGetSwapChainInfoWSI = (PFN_vkGetSwapChainInfoWSI) vkGetInstanceProcAddr(inst, "vkGetSwapChainInfoWSI");
732 ASSERT_TRUE(m_fpGetSwapChainInfoWSI != NULL) << "vkGetInstanceProcAddr failed to find vkGetSwapChainInfoWSI";
733
734 m_fpQueuePresentWSI = (PFN_vkQueuePresentWSI) vkGetInstanceProcAddr(inst, "vkQueuePresentWSI");
735 ASSERT_TRUE(m_fpQueuePresentWSI != NULL) << "vkGetInstanceProcAddr failed to find vkQueuePresentWSI";
736
Tony Barbour96db8822015-02-25 12:28:39 -0700737 m_images = imagesIn;
738}
739
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600740#ifdef _WIN32
741void TestFrameworkVkPresent::CreateMyWindow()
742{
743 WNDCLASSEX win_class;
744 // const ::testing::TestInfo* const test_info =
745 // ::testing::UnitTest::GetInstance()->current_test_info();
746 m_connection = GetModuleHandle(NULL);
747
748 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
749 it != m_images.end(); it++) {
750 if (m_width < it->m_width)
751 m_width = it->m_width;
752 if (m_height < it->m_height)
753 m_height = it->m_height;
754 }
755 // Initialize the window class structure:
756 win_class.cbSize = sizeof(WNDCLASSEX);
757 win_class.style = CS_HREDRAW | CS_VREDRAW;
758 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
759 win_class.cbClsExtra = 0;
760 win_class.cbWndExtra = 0;
761 win_class.hInstance = m_connection; // hInstance
762 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
763 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
764 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
765 win_class.lpszMenuName = NULL;
766 win_class.lpszClassName = "Test";
767 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
768 // Register window class:
769 if (!RegisterClassEx(&win_class)) {
770 // It didn't work, so try to give a useful error:
771 printf("Unexpected error trying to start the application!\n");
772 fflush(stdout);
773 exit(1);
774 }
775 // Create window with the registered class:
776 m_window = CreateWindowEx(0,
777 "Test", // class name
778 "Test", // app name
779 WS_OVERLAPPEDWINDOW | // window style
780 WS_VISIBLE |
781 WS_SYSMENU,
782 100,100, // x/y coords
783 m_width, // width
784 m_height, // height
785 NULL, // handle to parent
786 NULL, // handle to menu
787 m_connection, // hInstance
788 NULL); // no extra parameters
789
790 if (!m_window) {
791 // It didn't work, so try to give a useful error:
792 DWORD error = GetLastError();
793 char message[120];
794 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
795 MessageBox(NULL, message, "Error", MB_OK);
796 exit(1);
797 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600798 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
799 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600800}
801#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600802void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -0700803{
Chia-I Wuf8693382015-04-16 22:02:10 +0800804 const xcb_setup_t *setup;
805 xcb_screen_iterator_t iter;
806 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -0700807 uint32_t value_mask, value_list[32];
808
Chia-I Wuf8693382015-04-16 22:02:10 +0800809 m_connection = xcb_connect(NULL, &scr);
810
811 setup = xcb_get_setup(m_connection);
812 iter = xcb_setup_roots_iterator(setup);
813 while (scr-- > 0)
814 xcb_screen_next(&iter);
815
816 m_screen = iter.data;
817
818 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
819 it != m_images.end(); it++) {
820 if (m_width < it->m_width)
821 m_width = it->m_width;
822 if (m_height < it->m_height)
823 m_height = it->m_height;
824 }
825
826 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700827
828 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +0800829 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -0700830 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
831 XCB_EVENT_MASK_EXPOSURE |
832 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
833
Chia-I Wuf8693382015-04-16 22:02:10 +0800834 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700835 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800836 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -0700837 0, 0, m_width, m_height, 0,
838 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800839 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -0700840 value_mask, value_list);
841
842 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +0800843 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -0700844 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +0800845 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -0700846
Chia-I Wuf8693382015-04-16 22:02:10 +0800847 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
848 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -0700849
Chia-I Wuf8693382015-04-16 22:02:10 +0800850 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -0700851 m_window, (*reply).atom, 4, 32, 1,
852 &(*m_atom_wm_delete_window).atom);
853 free(reply);
854
Chia-I Wuf8693382015-04-16 22:02:10 +0800855 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -0700856}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600857#endif
Tony Barbour96db8822015-02-25 12:28:39 -0700858
Tony Barbour6918cd52015-04-09 12:58:51 -0600859void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -0700860{
Ian Elliott1a3845b2015-07-06 14:33:04 -0600861 m_fpDestroySwapChainWSI(m_device.handle(), m_swap_chain);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600862#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800863 xcb_destroy_window(m_connection, m_window);
864 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600865#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600866}
867
Tony Barbour6918cd52015-04-09 12:58:51 -0600868void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600869{
870 if (m_images.size() == 0) return;
871
Chia-I Wuf8693382015-04-16 22:02:10 +0800872 vk_testing::Environment env;
873 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -0700874 {
Chia-I Wuf8693382015-04-16 22:02:10 +0800875 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -0700876
Jon Ashburn07daee72015-05-21 18:13:33 -0600877 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600878 vkPresent.CreateMyWindow();
Chia-I Wuf8693382015-04-16 22:02:10 +0800879 vkPresent.CreateSwapChain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600880 vkPresent.Run();
881 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -0700882 }
Chia-I Wuf8693382015-04-16 22:02:10 +0800883 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600884}
885
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600886//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600887// These are the default resources for TBuiltInResources, used for both
888// - parsing this string for the case where the user didn't supply one
889// - dumping out a template for user construction of a config file
890//
891static const char* DefaultConfig =
892 "MaxLights 32\n"
893 "MaxClipPlanes 6\n"
894 "MaxTextureUnits 32\n"
895 "MaxTextureCoords 32\n"
896 "MaxVertexAttribs 64\n"
897 "MaxVertexUniformComponents 4096\n"
898 "MaxVaryingFloats 64\n"
899 "MaxVertexTextureImageUnits 32\n"
900 "MaxCombinedTextureImageUnits 80\n"
901 "MaxTextureImageUnits 32\n"
902 "MaxFragmentUniformComponents 4096\n"
903 "MaxDrawBuffers 32\n"
904 "MaxVertexUniformVectors 128\n"
905 "MaxVaryingVectors 8\n"
906 "MaxFragmentUniformVectors 16\n"
907 "MaxVertexOutputVectors 16\n"
908 "MaxFragmentInputVectors 15\n"
909 "MinProgramTexelOffset -8\n"
910 "MaxProgramTexelOffset 7\n"
911 "MaxClipDistances 8\n"
912 "MaxComputeWorkGroupCountX 65535\n"
913 "MaxComputeWorkGroupCountY 65535\n"
914 "MaxComputeWorkGroupCountZ 65535\n"
915 "MaxComputeWorkGroupSizeX 1024\n"
916 "MaxComputeWorkGroupSizeY 1024\n"
917 "MaxComputeWorkGroupSizeZ 64\n"
918 "MaxComputeUniformComponents 1024\n"
919 "MaxComputeTextureImageUnits 16\n"
920 "MaxComputeImageUniforms 8\n"
921 "MaxComputeAtomicCounters 8\n"
922 "MaxComputeAtomicCounterBuffers 1\n"
923 "MaxVaryingComponents 60\n"
924 "MaxVertexOutputComponents 64\n"
925 "MaxGeometryInputComponents 64\n"
926 "MaxGeometryOutputComponents 128\n"
927 "MaxFragmentInputComponents 128\n"
928 "MaxImageUnits 8\n"
929 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
930 "MaxCombinedShaderOutputResources 8\n"
931 "MaxImageSamples 0\n"
932 "MaxVertexImageUniforms 0\n"
933 "MaxTessControlImageUniforms 0\n"
934 "MaxTessEvaluationImageUniforms 0\n"
935 "MaxGeometryImageUniforms 0\n"
936 "MaxFragmentImageUniforms 8\n"
937 "MaxCombinedImageUniforms 8\n"
938 "MaxGeometryTextureImageUnits 16\n"
939 "MaxGeometryOutputVertices 256\n"
940 "MaxGeometryTotalOutputComponents 1024\n"
941 "MaxGeometryUniformComponents 1024\n"
942 "MaxGeometryVaryingComponents 64\n"
943 "MaxTessControlInputComponents 128\n"
944 "MaxTessControlOutputComponents 128\n"
945 "MaxTessControlTextureImageUnits 16\n"
946 "MaxTessControlUniformComponents 1024\n"
947 "MaxTessControlTotalOutputComponents 4096\n"
948 "MaxTessEvaluationInputComponents 128\n"
949 "MaxTessEvaluationOutputComponents 128\n"
950 "MaxTessEvaluationTextureImageUnits 16\n"
951 "MaxTessEvaluationUniformComponents 1024\n"
952 "MaxTessPatchComponents 120\n"
953 "MaxPatchVertices 32\n"
954 "MaxTessGenLevel 64\n"
955 "MaxViewports 16\n"
956 "MaxVertexAtomicCounters 0\n"
957 "MaxTessControlAtomicCounters 0\n"
958 "MaxTessEvaluationAtomicCounters 0\n"
959 "MaxGeometryAtomicCounters 0\n"
960 "MaxFragmentAtomicCounters 8\n"
961 "MaxCombinedAtomicCounters 8\n"
962 "MaxAtomicCounterBindings 1\n"
963 "MaxVertexAtomicCounterBuffers 0\n"
964 "MaxTessControlAtomicCounterBuffers 0\n"
965 "MaxTessEvaluationAtomicCounterBuffers 0\n"
966 "MaxGeometryAtomicCounterBuffers 0\n"
967 "MaxFragmentAtomicCounterBuffers 1\n"
968 "MaxCombinedAtomicCounterBuffers 1\n"
969 "MaxAtomicCounterBufferSize 16384\n"
970 "MaxTransformFeedbackBuffers 4\n"
971 "MaxTransformFeedbackInterleavedComponents 64\n"
972 "MaxCullDistances 8\n"
973 "MaxCombinedClipAndCullDistances 8\n"
974 "MaxSamples 4\n"
975
976 "nonInductiveForLoops 1\n"
977 "whileLoops 1\n"
978 "doWhileLoops 1\n"
979 "generalUniformIndexing 1\n"
980 "generalAttributeMatrixVectorIndexing 1\n"
981 "generalVaryingIndexing 1\n"
982 "generalSamplerIndexing 1\n"
983 "generalVariableIndexing 1\n"
984 "generalConstantMatrixVectorIndexing 1\n"
985 ;
986
987//
988// *.conf => this is a config file that can set limits/resources
989//
Tony Barbour6918cd52015-04-09 12:58:51 -0600990bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600991{
992 if (name.size() < 5)
993 return false;
994
995 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
996 ConfigFile = name;
997 return true;
998 }
999
1000 return false;
1001}
1002
1003//
1004// Parse either a .conf file provided by the user or the default string above.
1005//
Tony Barbour6918cd52015-04-09 12:58:51 -06001006void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001007{
1008 char** configStrings = 0;
1009 char* config = 0;
1010 if (ConfigFile.size() > 0) {
1011 configStrings = ReadFileData(ConfigFile.c_str());
1012 if (configStrings)
1013 config = *configStrings;
1014 else {
1015 printf("Error opening configuration file; will instead use the default configuration\n");
1016 }
1017 }
1018
1019 if (config == 0) {
1020 config = new char[strlen(DefaultConfig) + 1];
1021 strcpy(config, DefaultConfig);
1022 }
1023
1024 const char* delims = " \t\n\r";
1025 const char* token = strtok(config, delims);
1026 while (token) {
1027 const char* valueStr = strtok(0, delims);
1028 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1029 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1030 return;
1031 }
1032 int value = atoi(valueStr);
1033
1034 if (strcmp(token, "MaxLights") == 0)
1035 Resources.maxLights = value;
1036 else if (strcmp(token, "MaxClipPlanes") == 0)
1037 Resources.maxClipPlanes = value;
1038 else if (strcmp(token, "MaxTextureUnits") == 0)
1039 Resources.maxTextureUnits = value;
1040 else if (strcmp(token, "MaxTextureCoords") == 0)
1041 Resources.maxTextureCoords = value;
1042 else if (strcmp(token, "MaxVertexAttribs") == 0)
1043 Resources.maxVertexAttribs = value;
1044 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1045 Resources.maxVertexUniformComponents = value;
1046 else if (strcmp(token, "MaxVaryingFloats") == 0)
1047 Resources.maxVaryingFloats = value;
1048 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1049 Resources.maxVertexTextureImageUnits = value;
1050 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1051 Resources.maxCombinedTextureImageUnits = value;
1052 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1053 Resources.maxTextureImageUnits = value;
1054 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1055 Resources.maxFragmentUniformComponents = value;
1056 else if (strcmp(token, "MaxDrawBuffers") == 0)
1057 Resources.maxDrawBuffers = value;
1058 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1059 Resources.maxVertexUniformVectors = value;
1060 else if (strcmp(token, "MaxVaryingVectors") == 0)
1061 Resources.maxVaryingVectors = value;
1062 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1063 Resources.maxFragmentUniformVectors = value;
1064 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1065 Resources.maxVertexOutputVectors = value;
1066 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1067 Resources.maxFragmentInputVectors = value;
1068 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1069 Resources.minProgramTexelOffset = value;
1070 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1071 Resources.maxProgramTexelOffset = value;
1072 else if (strcmp(token, "MaxClipDistances") == 0)
1073 Resources.maxClipDistances = value;
1074 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1075 Resources.maxComputeWorkGroupCountX = value;
1076 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1077 Resources.maxComputeWorkGroupCountY = value;
1078 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1079 Resources.maxComputeWorkGroupCountZ = value;
1080 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1081 Resources.maxComputeWorkGroupSizeX = value;
1082 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1083 Resources.maxComputeWorkGroupSizeY = value;
1084 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1085 Resources.maxComputeWorkGroupSizeZ = value;
1086 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1087 Resources.maxComputeUniformComponents = value;
1088 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1089 Resources.maxComputeTextureImageUnits = value;
1090 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1091 Resources.maxComputeImageUniforms = value;
1092 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1093 Resources.maxComputeAtomicCounters = value;
1094 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1095 Resources.maxComputeAtomicCounterBuffers = value;
1096 else if (strcmp(token, "MaxVaryingComponents") == 0)
1097 Resources.maxVaryingComponents = value;
1098 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1099 Resources.maxVertexOutputComponents = value;
1100 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1101 Resources.maxGeometryInputComponents = value;
1102 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1103 Resources.maxGeometryOutputComponents = value;
1104 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1105 Resources.maxFragmentInputComponents = value;
1106 else if (strcmp(token, "MaxImageUnits") == 0)
1107 Resources.maxImageUnits = value;
1108 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1109 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1110 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1111 Resources.maxCombinedShaderOutputResources = value;
1112 else if (strcmp(token, "MaxImageSamples") == 0)
1113 Resources.maxImageSamples = value;
1114 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1115 Resources.maxVertexImageUniforms = value;
1116 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1117 Resources.maxTessControlImageUniforms = value;
1118 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1119 Resources.maxTessEvaluationImageUniforms = value;
1120 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1121 Resources.maxGeometryImageUniforms = value;
1122 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1123 Resources.maxFragmentImageUniforms = value;
1124 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1125 Resources.maxCombinedImageUniforms = value;
1126 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1127 Resources.maxGeometryTextureImageUnits = value;
1128 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1129 Resources.maxGeometryOutputVertices = value;
1130 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1131 Resources.maxGeometryTotalOutputComponents = value;
1132 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1133 Resources.maxGeometryUniformComponents = value;
1134 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1135 Resources.maxGeometryVaryingComponents = value;
1136 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1137 Resources.maxTessControlInputComponents = value;
1138 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1139 Resources.maxTessControlOutputComponents = value;
1140 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1141 Resources.maxTessControlTextureImageUnits = value;
1142 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1143 Resources.maxTessControlUniformComponents = value;
1144 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1145 Resources.maxTessControlTotalOutputComponents = value;
1146 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1147 Resources.maxTessEvaluationInputComponents = value;
1148 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1149 Resources.maxTessEvaluationOutputComponents = value;
1150 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1151 Resources.maxTessEvaluationTextureImageUnits = value;
1152 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1153 Resources.maxTessEvaluationUniformComponents = value;
1154 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1155 Resources.maxTessPatchComponents = value;
1156 else if (strcmp(token, "MaxPatchVertices") == 0)
1157 Resources.maxPatchVertices = value;
1158 else if (strcmp(token, "MaxTessGenLevel") == 0)
1159 Resources.maxTessGenLevel = value;
1160 else if (strcmp(token, "MaxViewports") == 0)
1161 Resources.maxViewports = value;
1162 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1163 Resources.maxVertexAtomicCounters = value;
1164 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1165 Resources.maxTessControlAtomicCounters = value;
1166 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1167 Resources.maxTessEvaluationAtomicCounters = value;
1168 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1169 Resources.maxGeometryAtomicCounters = value;
1170 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1171 Resources.maxFragmentAtomicCounters = value;
1172 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1173 Resources.maxCombinedAtomicCounters = value;
1174 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1175 Resources.maxAtomicCounterBindings = value;
1176 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1177 Resources.maxVertexAtomicCounterBuffers = value;
1178 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1179 Resources.maxTessControlAtomicCounterBuffers = value;
1180 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1181 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1182 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1183 Resources.maxGeometryAtomicCounterBuffers = value;
1184 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1185 Resources.maxFragmentAtomicCounterBuffers = value;
1186 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1187 Resources.maxCombinedAtomicCounterBuffers = value;
1188 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1189 Resources.maxAtomicCounterBufferSize = value;
1190 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1191 Resources.maxTransformFeedbackBuffers = value;
1192 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1193 Resources.maxTransformFeedbackInterleavedComponents = value;
1194 else if (strcmp(token, "MaxCullDistances") == 0)
1195 Resources.maxCullDistances = value;
1196 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1197 Resources.maxCombinedClipAndCullDistances = value;
1198 else if (strcmp(token, "MaxSamples") == 0)
1199 Resources.maxSamples = value;
1200
1201 else if (strcmp(token, "nonInductiveForLoops") == 0)
1202 Resources.limits.nonInductiveForLoops = (value != 0);
1203 else if (strcmp(token, "whileLoops") == 0)
1204 Resources.limits.whileLoops = (value != 0);
1205 else if (strcmp(token, "doWhileLoops") == 0)
1206 Resources.limits.doWhileLoops = (value != 0);
1207 else if (strcmp(token, "generalUniformIndexing") == 0)
1208 Resources.limits.generalUniformIndexing = (value != 0);
1209 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1210 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1211 else if (strcmp(token, "generalVaryingIndexing") == 0)
1212 Resources.limits.generalVaryingIndexing = (value != 0);
1213 else if (strcmp(token, "generalSamplerIndexing") == 0)
1214 Resources.limits.generalSamplerIndexing = (value != 0);
1215 else if (strcmp(token, "generalVariableIndexing") == 0)
1216 Resources.limits.generalVariableIndexing = (value != 0);
1217 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1218 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1219 else
1220 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1221
1222 token = strtok(0, delims);
1223 }
1224 if (configStrings)
1225 FreeFileData(configStrings);
1226}
1227
Tony Barbour6918cd52015-04-09 12:58:51 -06001228void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001229{
1230 if (m_compile_options & EOptionRelaxedErrors)
1231 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1232 if (m_compile_options & EOptionIntermediate)
1233 messages = (EShMessages)(messages | EShMsgAST);
1234 if (m_compile_options & EOptionSuppressWarnings)
1235 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1236}
1237
1238//
1239// Malloc a string of sufficient size and read a string into it.
1240//
Tony Barbour6918cd52015-04-09 12:58:51 -06001241char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001242{
1243 FILE *in;
1244 #if defined(_WIN32) && defined(__GNUC__)
1245 in = fopen(fileName, "r");
1246 int errorCode = in ? 0 : 1;
1247 #else
1248 int errorCode = fopen_s(&in, fileName, "r");
1249 #endif
1250
1251 char *fdata;
1252 int count = 0;
1253 const int maxSourceStrings = 5;
1254 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1255
1256 if (errorCode) {
1257 printf("Error: unable to open input file: %s\n", fileName);
1258 return 0;
1259 }
1260
1261 while (fgetc(in) != EOF)
1262 count++;
1263
1264 fseek(in, 0, SEEK_SET);
1265
1266 if (!(fdata = (char*)malloc(count+2))) {
1267 printf("Error allocating memory\n");
1268 return 0;
1269 }
1270 if (fread(fdata,1,count, in)!=count) {
1271 printf("Error reading input file: %s\n", fileName);
1272 return 0;
1273 }
1274 fdata[count] = '\0';
1275 fclose(in);
1276 if (count == 0) {
1277 return_data[0]=(char*)malloc(count+2);
1278 return_data[0][0]='\0';
1279 m_num_shader_strings = 0;
1280 return return_data;
1281 } else
1282 m_num_shader_strings = 1;
1283
1284 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1285 int ptr_len=0,i=0;
1286 while(count>0){
1287 return_data[i]=(char*)malloc(len+2);
1288 memcpy(return_data[i],fdata+ptr_len,len);
1289 return_data[i][len]='\0';
1290 count-=(len);
1291 ptr_len+=(len);
1292 if(count<len){
1293 if(count==0){
1294 m_num_shader_strings=(i+1);
1295 break;
1296 }
1297 len = count;
1298 }
1299 ++i;
1300 }
1301 return return_data;
1302}
1303
Tony Barbour6918cd52015-04-09 12:58:51 -06001304void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001305{
1306 for(int i=0;i<m_num_shader_strings;i++)
1307 free(data[i]);
1308}
1309
1310//
1311// Deduce the language from the filename. Files must end in one of the
1312// following extensions:
1313//
1314// .vert = vertex
1315// .tesc = tessellation control
1316// .tese = tessellation evaluation
1317// .geom = geometry
1318// .frag = fragment
1319// .comp = compute
1320//
Tony Barbour6918cd52015-04-09 12:58:51 -06001321EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001322{
1323 size_t ext = name.rfind('.');
1324 if (ext == std::string::npos) {
1325 return EShLangVertex;
1326 }
1327
1328 std::string suffix = name.substr(ext + 1, std::string::npos);
1329 if (suffix == "vert")
1330 return EShLangVertex;
1331 else if (suffix == "tesc")
1332 return EShLangTessControl;
1333 else if (suffix == "tese")
1334 return EShLangTessEvaluation;
1335 else if (suffix == "geom")
1336 return EShLangGeometry;
1337 else if (suffix == "frag")
1338 return EShLangFragment;
1339 else if (suffix == "comp")
1340 return EShLangCompute;
1341
1342 return EShLangVertex;
1343}
1344
1345//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001346// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001347//
Tony Barbourd1c35722015-04-16 15:59:00 -06001348EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001349{
1350 switch (shader_type) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001351 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001352 return EShLangVertex;
1353
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001354 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001355 return EShLangTessControl;
1356
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001357 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001358 return EShLangTessEvaluation;
1359
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001360 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001361 return EShLangGeometry;
1362
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001363 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001364 return EShLangFragment;
1365
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001366 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001367 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001368
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001369 default:
1370 return EShLangVertex;
1371 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001372}
1373
1374
1375//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001376// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001377// Return value of false means an error was encountered.
1378//
Tony Barbourd1c35722015-04-16 15:59:00 -06001379bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001380 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001381 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001382{
1383 glslang::TProgram& program = *new glslang::TProgram;
1384 const char *shaderStrings[1];
1385
1386 // TODO: Do we want to load a special config file depending on the
1387 // shader source? Optional name maybe?
1388 // SetConfigFile(fileName);
1389
1390 ProcessConfigFile();
1391
1392 EShMessages messages = EShMsgDefault;
1393 SetMessageOptions(messages);
1394
1395 EShLanguage stage = FindLanguage(shader_type);
1396 glslang::TShader* shader = new glslang::TShader(stage);
1397
1398 shaderStrings[0] = pshader;
1399 shader->setStrings(shaderStrings, 1);
1400
1401 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1402
Cody Northrop195d6622014-11-03 12:54:37 -07001403 if (! (m_compile_options & EOptionSuppressInfolog)) {
1404 puts(shader->getInfoLog());
1405 puts(shader->getInfoDebugLog());
1406 }
1407
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001408 return false; // something didn't work
1409 }
1410
1411 program.addShader(shader);
1412
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001413
1414 //
1415 // Program-level processing...
1416 //
1417
Cody Northrop195d6622014-11-03 12:54:37 -07001418 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001419
Cody Northrop195d6622014-11-03 12:54:37 -07001420 if (! (m_compile_options & EOptionSuppressInfolog)) {
1421 puts(shader->getInfoLog());
1422 puts(shader->getInfoDebugLog());
1423 }
1424
1425 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001426 }
1427
1428 if (m_compile_options & EOptionDumpReflection) {
1429 program.buildReflection();
1430 program.dumpReflection();
1431 }
1432
Cody Northrop5a95b472015-06-03 13:01:54 -06001433 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1434
1435 //
1436 // Test the different modes of SPIR-V modification
1437 //
1438 if (this->m_canonicalize_spv) {
1439 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1440 }
1441
1442 if (this->m_strip_spv) {
1443 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1444 }
1445
1446 if (this->m_do_everything_spv) {
1447 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1448 }
1449
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001450
1451 return true;
1452}
1453
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001454
1455
Tony Barbour6918cd52015-04-09 12:58:51 -06001456VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001457 m_width( 0 ),
1458 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001459 m_data( NULL ),
1460 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001461{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001462}
1463
Tony Barbour6918cd52015-04-09 12:58:51 -06001464VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001465{
1466
1467}
1468
Tony Barbour6918cd52015-04-09 12:58:51 -06001469VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001470{
1471 m_title = copyin.m_title;
1472 m_width = copyin.m_width;
1473 m_height = copyin.m_height;
1474 m_data_size = copyin.m_data_size;
1475 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1476}
1477
Tony Barbour6918cd52015-04-09 12:58:51 -06001478ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001479{
Tony Barbour6918cd52015-04-09 12:58:51 -06001480 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1481 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001482 return output;
1483}
1484
Tony Barbour6918cd52015-04-09 12:58:51 -06001485VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001486{
1487 m_title = rhs.m_title;
1488 m_width = rhs.m_width;
1489 m_height = rhs.m_height;
1490 m_data_size = rhs.m_data_size;
1491 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001492 return *this;
1493}
1494
Tony Barbour6918cd52015-04-09 12:58:51 -06001495int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001496{
1497 if( this->m_data != rhs.m_data) return 0;
1498 return 1;
1499}
1500
1501// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001502int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001503{
1504 if( this->m_data_size < rhs.m_data_size ) return 1;
1505 return 0;
1506}
1507