blob: ed2706aeccbd09c7357d8aaacbce26734833f54d [file] [log] [blame]
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001// VK tests
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06002//
3// Copyright (C) 2014 LunarG, Inc.
4//
5// Permission is hereby granted, free of charge, to any person obtaining a
6// copy of this software and associated documentation files (the "Software"),
7// to deal in the Software without restriction, including without limitation
8// the rights to use, copy, modify, merge, publish, distribute, sublicense,
9// and/or sell copies of the Software, and to permit persons to whom the
10// Software is furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included
13// in all copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21// DEALINGS IN THE SOFTWARE.
22
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060023#include "vktestframework.h"
24#include "vkrenderframework.h"
Cody Northropeb9130e2015-06-03 13:01:54 -060025#include "SPIRV/GlslangToSpv.h"
26#include "SPIRV/SPVRemapper.h"
Tony Barbour772c5ef2014-12-10 17:00:20 -070027#include <limits.h>
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -060028#include <math.h>
Chia-I Wu3d9ebb22014-12-02 11:54:24 +080029#include <wand/MagickWand.h>
Chia-I Wu5b66aa52015-04-16 22:02:10 +080030#include <xcb/xcb.h>
31#include <vk_wsi_lunarg.h>
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -060032
Tony Barbour25e3b832015-05-20 16:53:31 -060033#if defined(PATH_MAX) && !defined(MAX_PATH)
34#define MAX_PATH PATH_MAX
35#endif
36
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -060037// Command-line options
38enum TOptions {
39 EOptionNone = 0x000,
40 EOptionIntermediate = 0x001,
41 EOptionSuppressInfolog = 0x002,
42 EOptionMemoryLeakMode = 0x004,
43 EOptionRelaxedErrors = 0x008,
44 EOptionGiveWarnings = 0x010,
45 EOptionLinkProgram = 0x020,
46 EOptionMultiThreaded = 0x040,
47 EOptionDumpConfig = 0x080,
48 EOptionDumpReflection = 0x100,
49 EOptionSuppressWarnings = 0x200,
50 EOptionDumpVersions = 0x400,
Cody Northropacfb0492015-03-17 15:55:58 -060051 EOptionSpv = 0x800,
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -060052 EOptionDefaultDesktop = 0x1000,
53};
54
Chia-I Wu5b66aa52015-04-16 22:02:10 +080055class TestFrameworkVkPresent
56{
57public:
58 TestFrameworkVkPresent(vk_testing::Device &device);
59
60 void Run();
Jon Ashburncedc15f2015-05-21 18:13:33 -060061 void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst);
Chia-I Wu5b66aa52015-04-16 22:02:10 +080062 void CreateMyWindow();
63 void CreateSwapChain();
64 void TearDown();
Tony Barbour25e3b832015-05-20 16:53:31 -060065#ifdef _WIN32
66 static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
67#endif
68
Chia-I Wu5b66aa52015-04-16 22:02:10 +080069
70protected:
71 vk_testing::Device &m_device;
72 vk_testing::Queue &m_queue;
73 vk_testing::CmdBuffer m_cmdbuf;
74
75private:
Tony Barbour25e3b832015-05-20 16:53:31 -060076#ifdef _WIN32
77 HINSTANCE m_connection; // hInstance - Windows Instance
78 HWND m_window; // hWnd - window handle
79
80#else
Chia-I Wu5b66aa52015-04-16 22:02:10 +080081 xcb_connection_t *m_connection;
82 xcb_screen_t *m_screen;
83 xcb_window_t m_window;
84 xcb_intern_atom_reply_t *m_atom_wm_delete_window;
Tony Barbour25e3b832015-05-20 16:53:31 -060085#endif
Courtney Goeltzenleuchterec69b9c2015-04-22 10:09:35 -060086 std::list<VkTestImageRecord> m_images;
Chia-I Wu5b66aa52015-04-16 22:02:10 +080087
Jon Ashburncedc15f2015-05-21 18:13:33 -060088 PFN_vkCreateSwapChainWSI m_fpCreateSwapChainWSI;
89 PFN_vkDestroySwapChainWSI m_fpDestroySwapChainWSI;
90 PFN_vkGetSwapChainInfoWSI m_fpGetSwapChainInfoWSI;
91 PFN_vkQueuePresentWSI m_fpQueuePresentWSI;
92
Chia-I Wu5b66aa52015-04-16 22:02:10 +080093 VkSwapChainWSI m_swap_chain;
Tony-LunarGf05ba082015-05-19 14:08:26 -060094 std::vector<VkSwapChainImageInfoWSI> m_persistent_images;
95 int m_current_buffer;
Chia-I Wu5b66aa52015-04-16 22:02:10 +080096
97 bool m_quit;
98 bool m_pause;
99
Tony Barbour8bef8ee2015-05-22 09:44:58 -0600100 int m_width;
101 int m_height;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800102
103 std::list<VkTestImageRecord>::iterator m_display_image;
104
105 void Display();
106 void HandleEvent(xcb_generic_event_t *event);
107};
108
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600109#ifndef _WIN32
110
111#include <errno.h>
112
113int fopen_s(
114 FILE** pFile,
115 const char* filename,
116 const char* mode
117)
118{
119 if (!pFile || !filename || !mode) {
120 return EINVAL;
121 }
122
123 FILE* f = fopen(filename, mode);
124 if (! f) {
125 if (errno != 0) {
126 return errno;
127 } else {
128 return ENOENT;
129 }
130 }
131 *pFile = f;
132
133 return 0;
134}
135
136#endif
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600137
Tony Barbour25e3b832015-05-20 16:53:31 -0600138
139
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600140// Set up environment for GLSL compiler
141// Must be done once per process
142void TestEnvironment::SetUp()
143{
Cody Northropacfb0492015-03-17 15:55:58 -0600144 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600145 glslang::InitializeProcess();
Chia-I Wu1c9869e2014-12-28 14:27:28 +0800146
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600147 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600148}
149
150void TestEnvironment::TearDown()
151{
152 glslang::FinalizeProcess();
153}
154
Tony Barbour01999182015-04-09 12:58:51 -0600155VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600156 m_compile_options( 0 ),
157 m_num_shader_strings( 0 )
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600158{
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600159
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600160}
161
Tony Barbour01999182015-04-09 12:58:51 -0600162VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600163{
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600164
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600165}
166
167// Define all the static elements
Cody Northropa392a292015-06-09 13:00:45 -0600168bool VkTestFramework::m_show_images = false;
169bool VkTestFramework::m_save_images = false;
170bool VkTestFramework::m_compare_images = false;
171bool VkTestFramework::m_use_glsl = false;
172bool VkTestFramework::m_canonicalize_spv = false;
173bool VkTestFramework::m_strip_spv = false;
Cody Northropeb9130e2015-06-03 13:01:54 -0600174bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour01999182015-04-09 12:58:51 -0600175int VkTestFramework::m_width = 0;
176int VkTestFramework::m_height = 0;
177std::list<VkTestImageRecord> VkTestFramework::m_images;
178std::list<VkTestImageRecord>::iterator VkTestFramework::m_display_image;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600179int m_display_image_idx = 0;
180
Cody Northrop1cfbd172015-06-03 16:49:20 -0600181bool VkTestFramework::optionMatch(const char* option, char* optionLine)
182{
183 if (strncmp(option, optionLine, strlen(option)) == 0)
184 return true;
185 else
186 return false;
187}
188
Tony Barbour01999182015-04-09 12:58:51 -0600189void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600190{
191 int i, n;
192
Cody Northrop1cfbd172015-06-03 16:49:20 -0600193 for (i=1, n=1; i< *argc; i++) {
194 if (optionMatch("--show-images", argv[i]))
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600195 m_show_images = true;
Cody Northrop1cfbd172015-06-03 16:49:20 -0600196 else if (optionMatch("--save-images", argv[i]))
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600197 m_save_images = true;
Cody Northrop1cfbd172015-06-03 16:49:20 -0600198 else if (optionMatch("--no-SPV", argv[i]))
199 m_use_glsl = true;
200 else if (optionMatch("--strip-SPV", argv[i]))
201 m_strip_spv = true;
202 else if (optionMatch("--canonicalize-SPV", argv[i]))
203 m_canonicalize_spv = true;
204 else if (optionMatch("--compare-images", argv[i]))
Tony Barbour32f368c2014-10-30 14:29:04 -0600205 m_compare_images = true;
Tony Barbour32f368c2014-10-30 14:29:04 -0600206
Cody Northrop1cfbd172015-06-03 16:49:20 -0600207 else if (optionMatch("--help", argv[i]) ||
208 optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchterb7f26e02014-12-02 13:13:10 -0700209 printf("\nOther options:\n");
210 printf("\t--show-images\n"
211 "\t\tDisplay test images in viewer after tests complete.\n");
212 printf("\t--save-images\n"
213 "\t\tSave tests images as ppm files in current working directory.\n"
214 "\t\tUsed to generate golden images for compare-images.\n");
215 printf("\t--compare-images\n"
216 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barbour0e4235d2014-12-11 09:52:49 -0700217 "\t\tAlso saves the generated test image in current working\n"
218 "\t\t\tdirectory but only if the image is different from the golden\n"
219 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
220 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchterb7f26e02014-12-02 13:13:10 -0700221 "\t\tSignal test failure if different.\n");
Cody Northropacfb0492015-03-17 15:55:58 -0600222 printf("\t--no-SPV\n"
223 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop1cfbd172015-06-03 16:49:20 -0600224 printf("\t--strip-SPV\n"
225 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
226 printf("\t--canonicalize-SPV\n"
227 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
228 exit(0);
229 } else {
230 printf("\nUnrecognized option: %s\n", argv[i]);
231 printf("\nUse --help or -h for option list.\n");
Tony Barbour772c5ef2014-12-10 17:00:20 -0700232 exit(0);
Courtney Goeltzenleuchterb7f26e02014-12-02 13:13:10 -0700233 }
234
Cody Northrop1cfbd172015-06-03 16:49:20 -0600235 /*
236 * Since the above "consume" inputs, update argv
237 * so that it contains the trimmed list of args for glutInit
238 */
239
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600240 argv[n] = argv[i];
241 n++;
242 }
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600243}
244
Tony Barbour01999182015-04-09 12:58:51 -0600245void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600246{
247 string filename;
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600248 VkResult err;
Tony Barbour8bef8ee2015-05-22 09:44:58 -0600249 uint32_t x, y;
Tony Barbour01999182015-04-09 12:58:51 -0600250 VkImageObj displayImage(image->device());
Tony Barbour94310562015-04-22 15:10:33 -0600251 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbouredc49d92015-04-02 14:02:33 -0600252
Tony Barbour94310562015-04-22 15:10:33 -0600253 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, VK_IMAGE_TILING_LINEAR, reqs);
Tony Barbouredc49d92015-04-02 14:02:33 -0600254 displayImage.CopyImage(*image);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600255
256 filename.append(basename);
257 filename.append(".ppm");
Tony Barbour25e3b832015-05-20 16:53:31 -0600258
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600259 const VkImageSubresource sr = {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600260 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600261 };
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600262 VkSubresourceLayout sr_layout;
Tony Barbour25e3b832015-05-20 16:53:31 -0600263
Tony Barbour426b9052015-06-24 16:06:58 -0600264 err = vkGetImageSubresourceLayout(image->device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600265 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600266
Tony Barbouredc49d92015-04-02 14:02:33 -0600267 char *ptr;
268 ptr = (char *) displayImage.map();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600269 ptr += sr_layout.offset;
Tony Barbour25e3b832015-05-20 16:53:31 -0600270 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600271 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
272
273 file << "P6\n";
Tony Barbouredc49d92015-04-02 14:02:33 -0600274 file << displayImage.width() << "\n";
275 file << displayImage.height() << "\n";
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600276 file << 255 << "\n";
277
Tony Barbouredc49d92015-04-02 14:02:33 -0600278 for (y = 0; y < displayImage.height(); y++) {
Tony Barboure2668672015-02-25 11:25:11 -0700279 const int *row = (const int *) ptr;
280 int swapped;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600281
Tony Barbour8205d902015-04-16 15:59:00 -0600282 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboure2668672015-02-25 11:25:11 -0700283 {
Tony Barbouredc49d92015-04-02 14:02:33 -0600284 for (x = 0; x < displayImage.width(); x++) {
Tony Barboure2668672015-02-25 11:25:11 -0700285 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
286 file.write((char *) &swapped, 3);
287 row++;
288 }
289 }
Tony Barbour8205d902015-04-16 15:59:00 -0600290 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboure2668672015-02-25 11:25:11 -0700291 {
Tony Barbouredc49d92015-04-02 14:02:33 -0600292 for (x = 0; x < displayImage.width(); x++) {
Tony Barboure2668672015-02-25 11:25:11 -0700293 file.write((char *) row, 3);
294 row++;
295 }
296 }
297 else {
298 printf("Unrecognized image format - will not write image files");
299 break;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600300 }
301
302 ptr += sr_layout.rowPitch;
303 }
304
305 file.close();
Tony Barbouredc49d92015-04-02 14:02:33 -0600306 displayImage.unmap();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600307}
308
Tony Barbour01999182015-04-09 12:58:51 -0600309void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour32f368c2014-10-30 14:29:04 -0600310{
311
312 MagickWand *magick_wand_1;
313 MagickWand *magick_wand_2;
314 MagickWand *compare_wand;
315 MagickBooleanType status;
Tony Barbour25e3b832015-05-20 16:53:31 -0600316 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour32f368c2014-10-30 14:29:04 -0600317 double differenz;
318
Tony Barbour772c5ef2014-12-10 17:00:20 -0700319 if (getenv("RENDERTEST_GOLDEN_DIR"))
320 {
321 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
322 }
323
Tony Barbour32f368c2014-10-30 14:29:04 -0600324 MagickWandGenesis();
325 magick_wand_1=NewMagickWand();
326 sprintf(testimage,"%s.ppm",basename);
327 status=MagickReadImage(magick_wand_1,testimage);
Tony Barbour8bef8ee2015-05-22 09:44:58 -0600328 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour32f368c2014-10-30 14:29:04 -0600329
330
331 MagickWandGenesis();
332 magick_wand_2=NewMagickWand();
Tony Barbour772c5ef2014-12-10 17:00:20 -0700333 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour32f368c2014-10-30 14:29:04 -0600334 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour8bef8ee2015-05-22 09:44:58 -0600335 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour32f368c2014-10-30 14:29:04 -0600336
Tony Barbour32f368c2014-10-30 14:29:04 -0600337 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
338 if (differenz != 0.0)
339 {
340 char difference[256];
341
342 sprintf(difference,"%s-diff.ppm",basename);
343 status = MagickWriteImage(compare_wand, difference);
344 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
345 }
346 DestroyMagickWand(compare_wand);
347
348 DestroyMagickWand(magick_wand_1);
349 DestroyMagickWand(magick_wand_2);
350 MagickWandTerminus();
Courtney Goeltzenleuchterdfa97b82014-12-05 15:41:02 -0700351
352 if (differenz == 0.0)
353 {
354 /*
355 * If test image and golden image match, we do not need to
356 * keep around the test image.
357 */
358 remove(testimage);
359 }
Tony Barbour32f368c2014-10-30 14:29:04 -0600360}
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600361
Tony Barbour01999182015-04-09 12:58:51 -0600362void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600363{
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600364 VkResult err;
Courtney Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600365 VkSubresourceLayout sr_layout;
366 char *ptr;
367 VkTestImageRecord record;
Courtney Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600368 VkImageObj displayImage(image->device());
369 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
370
Courtney Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600371 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, VK_IMAGE_TILING_LINEAR, reqs);
372 displayImage.CopyImage(*image);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600373
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600374 const VkImageSubresource sr = {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600375 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600376 };
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600377
Tony Barbour426b9052015-06-24 16:06:58 -0600378 err = vkGetImageSubresourceLayout(displayImage.device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600379 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600380
Courtney Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600381 err = displayImage.MapMemory( (void **) &ptr );
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600382 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600383
384 ptr += sr_layout.offset;
385
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600386 record.m_title.append(comment);
Courtney Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600387 record.m_width = displayImage.width();
388 record.m_height = displayImage.height();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600389 // TODO: Need to make this more robust to handle different image formats
Tony-LunarGf05ba082015-05-19 14:08:26 -0600390 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600391 record.m_data = malloc(record.m_data_size);
392 memcpy(record.m_data, ptr, record.m_data_size);
393 m_images.push_back(record);
394 m_display_image = --m_images.end();
395
Courtney Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600396 err = displayImage.UnmapMemory();
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600397 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600398}
399
Tony Barbour01999182015-04-09 12:58:51 -0600400void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour32f368c2014-10-30 14:29:04 -0600401{
Courtney Goeltzenleuchtercd5ed1e2015-04-02 14:17:44 -0600402 for (int32_t i = 0; i < images.size(); i++) {
403 RecordImage(images[i]);
Tony Barbour32f368c2014-10-30 14:29:04 -0600404 }
405}
406
Tony Barbour01999182015-04-09 12:58:51 -0600407void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600408{
409 const ::testing::TestInfo* const test_info =
410 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour32f368c2014-10-30 14:29:04 -0600411 ostringstream filestream;
412 string filename;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600413
Tony Barbour32f368c2014-10-30 14:29:04 -0600414 m_width = 40;
415
416 if (strcmp(test_info->name(), m_testName.c_str())) {
417 filestream << test_info->name();
418 m_testName.assign(test_info->name());
Tony Barboura48b0812014-11-18 17:02:36 -0700419 m_frameNum = 2;
420 filename = filestream.str();
Tony Barbour32f368c2014-10-30 14:29:04 -0600421 }
422 else {
423 filestream << test_info->name() << "-" << m_frameNum;
424 m_frameNum++;
Tony Barboura48b0812014-11-18 17:02:36 -0700425 filename = filestream.str();
Tony Barbour32f368c2014-10-30 14:29:04 -0600426 }
427
Tony Barbour32f368c2014-10-30 14:29:04 -0600428 // ToDo - scrub string for bad characters
429
430 if (m_save_images || m_compare_images) {
431 WritePPM(filename.c_str(), image);
432 if (m_compare_images) {
433 Compare(filename.c_str(), image);
434 }
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600435 }
436
437 if (m_show_images) {
Courtney Goeltzenleuchtere5409342014-10-08 14:26:40 -0600438 Show(test_info->name(), image);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600439 }
440}
441
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800442TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
443 m_device(device),
Courtney Goeltzenleuchterdd745fd2015-03-05 16:47:18 -0700444 m_queue(*m_device.graphics_queues()[0]),
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600445 m_cmdbuf(m_device, vk_testing::CmdBuffer::create_info(m_device.graphics_queue_node_index_))
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600446{
Tony Barbouref20d322015-02-25 12:28:39 -0700447 m_quit = false;
448 m_pause = false;
449 m_width = 0;
450 m_height = 0;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600451}
452
Tony Barbour01999182015-04-09 12:58:51 -0600453void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600454{
Tony Barbour22a30862015-04-22 09:02:32 -0600455 VkResult U_ASSERT_ONLY err;
Tony-LunarGf05ba082015-05-19 14:08:26 -0600456 vk_testing::Buffer buf;
457 void *dest_ptr;
458
459 if (m_persistent_images.size() != 2) {
460 return;
461 }
462
463 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
464 buf.init(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
465 dest_ptr = buf.map();
466 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
467 buf.unmap();
468
469 m_cmdbuf.begin();
470
471 VkBufferImageCopy region = {};
472 region.imageExtent.height = m_display_image->m_height;
473 region.imageExtent.width = m_display_image->m_width;
474 region.imageExtent.depth = 1;
475
476 vkCmdCopyBufferToImage(m_cmdbuf.obj(),
477 buf.obj(),
478 m_persistent_images[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
479 1, &region);
480 m_cmdbuf.end();
481
482 VkCmdBuffer cmdBufs[1];
483 cmdBufs[0] = m_cmdbuf.obj();
484
485 vkQueueSubmit(m_queue.obj(), 1, cmdBufs, NULL);
486 m_queue.wait();
Tony Barbouref20d322015-02-25 12:28:39 -0700487
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800488 VkPresentInfoWSI present = {};
489 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_WSI;
Tony-LunarGf05ba082015-05-19 14:08:26 -0600490 present.image = m_persistent_images[m_current_buffer].image;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800491 present.flipInterval = 1;
Tony Barbouref20d322015-02-25 12:28:39 -0700492
Tony Barbour25e3b832015-05-20 16:53:31 -0600493#ifndef _WIN32
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800494 xcb_change_property (m_connection,
Tony Barbouref20d322015-02-25 12:28:39 -0700495 XCB_PROP_MODE_REPLACE,
496 m_window,
497 XCB_ATOM_WM_NAME,
498 XCB_ATOM_STRING,
499 8,
500 m_display_image->m_title.size(),
501 m_display_image->m_title.c_str());
Tony Barbour25e3b832015-05-20 16:53:31 -0600502#endif
Jon Ashburncedc15f2015-05-21 18:13:33 -0600503
504 err = m_fpQueuePresentWSI(m_queue.obj(), &present);
Tony Barbouref20d322015-02-25 12:28:39 -0700505 assert(!err);
506
507 m_queue.wait();
Tony-LunarGf05ba082015-05-19 14:08:26 -0600508 m_current_buffer = (m_current_buffer + 1) % 2;
Tony Barbouref20d322015-02-25 12:28:39 -0700509
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600510}
511
Tony Barbour25e3b832015-05-20 16:53:31 -0600512#ifdef _WIN32
Tony-LunarGf05ba082015-05-19 14:08:26 -0600513# define PREVIOUSLY_DOWN 1<<29
Tony Barbour25e3b832015-05-20 16:53:31 -0600514// MS-Windows event handling function:
515LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
516 UINT uMsg,
517 WPARAM wParam,
518 LPARAM lParam)
519{
520
521 switch(uMsg)
522 {
523 case WM_CLOSE:
524 PostQuitMessage(0);
525 break;
526
527 case WM_PAINT:
528 {
529 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
530 if (me) {
Tony-LunarGf05ba082015-05-19 14:08:26 -0600531 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour25e3b832015-05-20 16:53:31 -0600532 me->Display();
533 }
534 }
Tony-LunarGf05ba082015-05-19 14:08:26 -0600535 break;
536
537 case WM_KEYDOWN:
538 {
539 if (lParam & (PREVIOUSLY_DOWN)){
540 break;
541 }
542 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
543 // the window, we put the this pointer into the window's user data so we could get it back now
544 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
545 switch (wParam)
546 {
547 case VK_ESCAPE: me->m_quit = true;
548 break;
549
550 case VK_LEFT: // left arrow key
551 if (me->m_display_image == me->m_images.begin()) {
552 me->m_display_image = --me->m_images.end();
553 }
554 else {
555 --me->m_display_image;
556 }
557 break;
558
559 case VK_RIGHT: // right arrow key
560 ++me->m_display_image;
561 if (me->m_display_image == me->m_images.end()) {
562 me->m_display_image = me->m_images.begin();
563 }
564 break;
565
566 default:
567 break;
568 }
569 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
570 me->Display();
571 }
Tony Barbour25e3b832015-05-20 16:53:31 -0600572 }
573 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
574}
575
576void TestFrameworkVkPresent::Run()
577{
578 MSG msg; // message
Tony Barbour25e3b832015-05-20 16:53:31 -0600579
Tony Barbour25e3b832015-05-20 16:53:31 -0600580 /* main message loop*/
Tony-LunarGf05ba082015-05-19 14:08:26 -0600581 while(! m_quit) {
582 GetMessage(&msg, m_window, 0, 0);
Tony Barbour25e3b832015-05-20 16:53:31 -0600583 if (msg.message == WM_QUIT) {
Tony-LunarGf05ba082015-05-19 14:08:26 -0600584 m_quit = true; //if found, quit app
Tony Barbour25e3b832015-05-20 16:53:31 -0600585 } else {
586 /* Translate and dispatch to event queue*/
587 TranslateMessage(&msg);
588 DispatchMessage(&msg);
589 }
590 }
591}
592
593#else
Tony Barbour01999182015-04-09 12:58:51 -0600594void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600595{
Tony Barbour3a5cda02015-04-02 15:48:24 -0600596 uint8_t event_code = event->response_type & 0x7f;
Tony Barbouref20d322015-02-25 12:28:39 -0700597 switch (event_code) {
598 case XCB_EXPOSE:
599 Display(); // TODO: handle resize
600 break;
601 case XCB_CLIENT_MESSAGE:
602 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
603 (m_atom_wm_delete_window)->atom) {
604 m_quit = true;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600605 }
606 break;
Tony Barbouref20d322015-02-25 12:28:39 -0700607 case XCB_KEY_RELEASE:
608 {
609 const xcb_key_release_event_t *key =
610 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600611
Tony Barbouref20d322015-02-25 12:28:39 -0700612 switch (key->detail) {
613 case 0x9: // Escape
614 m_quit = true;
615 break;
616 case 0x71: // left arrow key
617 if (m_display_image == m_images.begin()) {
618 m_display_image = --m_images.end();
619 } else {
620 --m_display_image;
621 }
622 break;
623 case 0x72: // right arrow key
624 ++m_display_image;
625 if (m_display_image == m_images.end()) {
626 m_display_image = m_images.begin();
627 }
628 break;
629 case 0x41:
630 m_pause = !m_pause;
631 break;
632 }
633 Display();
634 }
635 break;
636 default:
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600637 break;
638 }
Tony Barbouref20d322015-02-25 12:28:39 -0700639}
640
Tony Barbour01999182015-04-09 12:58:51 -0600641void TestFrameworkVkPresent::Run()
Tony Barbouref20d322015-02-25 12:28:39 -0700642{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800643 xcb_flush(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700644
645 while (! m_quit) {
646 xcb_generic_event_t *event;
647
648 if (m_pause) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800649 event = xcb_wait_for_event(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700650 } else {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800651 event = xcb_poll_for_event(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700652 }
653 if (event) {
654 HandleEvent(event);
655 free(event);
656 }
657 }
658}
Tony Barbour25e3b832015-05-20 16:53:31 -0600659#endif // _WIN32
Tony Barbouref20d322015-02-25 12:28:39 -0700660
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800661void TestFrameworkVkPresent::CreateSwapChain()
Tony Barbouref20d322015-02-25 12:28:39 -0700662{
Tony Barbour22a30862015-04-22 09:02:32 -0600663 VkResult U_ASSERT_ONLY err;
Tony Barbouref20d322015-02-25 12:28:39 -0700664
Tony-LunarGf05ba082015-05-19 14:08:26 -0600665 m_display_image = m_images.begin();
666 m_current_buffer = 0;
667
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800668 VkSwapChainCreateInfoWSI swap_chain = {};
669 swap_chain.sType = VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI;
670 swap_chain.pNativeWindowSystemHandle = (void *) m_connection;
671 swap_chain.pNativeWindowHandle = (void *) (intptr_t) m_window;
Tony-LunarGf05ba082015-05-19 14:08:26 -0600672 swap_chain.imageCount = 2;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800673 swap_chain.imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
674 swap_chain.imageExtent.width = m_width;
675 swap_chain.imageExtent.height = m_height;
676 swap_chain.imageArraySize = 1;
677 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT;
678 swap_chain.swapModeFlags = VK_SWAP_MODE_FLIP_BIT_WSI |
679 VK_SWAP_MODE_BLIT_BIT_WSI;
680
Jon Ashburncedc15f2015-05-21 18:13:33 -0600681 err = m_fpCreateSwapChainWSI(m_device.obj(), &swap_chain, &m_swap_chain);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800682 assert(!err);
683
Tony-LunarGf05ba082015-05-19 14:08:26 -0600684 VkSwapChainImageInfoWSI infos[2];
Courtney Goeltzenleuchter7ce9d262015-06-24 15:02:51 -0600685 size_t size = sizeof(VkSwapChainImageInfoWSI) * m_images.size() * 2;
Jon Ashburncedc15f2015-05-21 18:13:33 -0600686 std::vector<VkSwapChainImageInfoWSI> persistent_images;
687 persistent_images.resize(m_images.size());
688 err = m_fpGetSwapChainInfoWSI(m_swap_chain,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800689 VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI,
Tony-LunarGf05ba082015-05-19 14:08:26 -0600690 &size, &infos);
691 assert(!err && size == sizeof(VkSwapChainImageInfoWSI) * 2);
692 m_persistent_images.push_back(infos[0]);
693 m_persistent_images.push_back(infos[1]);
Tony Barbouref20d322015-02-25 12:28:39 -0700694}
695
Jon Ashburncedc15f2015-05-21 18:13:33 -0600696void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbouref20d322015-02-25 12:28:39 -0700697{
Jon Ashburncedc15f2015-05-21 18:13:33 -0600698 m_fpCreateSwapChainWSI = (PFN_vkCreateSwapChainWSI) vkGetInstanceProcAddr(inst, "vkCreateSwapChainWSI");
699 ASSERT_TRUE(m_fpCreateSwapChainWSI != NULL) << "vkGetInstanceProcAddr failed to find vkCreateSwapChainWSI";
700
701 m_fpDestroySwapChainWSI = (PFN_vkDestroySwapChainWSI) vkGetInstanceProcAddr(inst, "vkDestroySwapChainWSI");
702 ASSERT_TRUE(m_fpDestroySwapChainWSI != NULL) << "vkGetInstanceProcAddr failed to find vkDestroySwapChainWSI";
703
704 m_fpGetSwapChainInfoWSI = (PFN_vkGetSwapChainInfoWSI) vkGetInstanceProcAddr(inst, "vkGetSwapChainInfoWSI");
705 ASSERT_TRUE(m_fpGetSwapChainInfoWSI != NULL) << "vkGetInstanceProcAddr failed to find vkGetSwapChainInfoWSI";
706
707 m_fpQueuePresentWSI = (PFN_vkQueuePresentWSI) vkGetInstanceProcAddr(inst, "vkQueuePresentWSI");
708 ASSERT_TRUE(m_fpQueuePresentWSI != NULL) << "vkGetInstanceProcAddr failed to find vkQueuePresentWSI";
709
Tony Barbouref20d322015-02-25 12:28:39 -0700710 m_images = imagesIn;
711}
712
Tony Barbour25e3b832015-05-20 16:53:31 -0600713#ifdef _WIN32
714void TestFrameworkVkPresent::CreateMyWindow()
715{
716 WNDCLASSEX win_class;
717 // const ::testing::TestInfo* const test_info =
718 // ::testing::UnitTest::GetInstance()->current_test_info();
719 m_connection = GetModuleHandle(NULL);
720
721 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
722 it != m_images.end(); it++) {
723 if (m_width < it->m_width)
724 m_width = it->m_width;
725 if (m_height < it->m_height)
726 m_height = it->m_height;
727 }
728 // Initialize the window class structure:
729 win_class.cbSize = sizeof(WNDCLASSEX);
730 win_class.style = CS_HREDRAW | CS_VREDRAW;
731 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
732 win_class.cbClsExtra = 0;
733 win_class.cbWndExtra = 0;
734 win_class.hInstance = m_connection; // hInstance
735 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
736 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
737 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
738 win_class.lpszMenuName = NULL;
739 win_class.lpszClassName = "Test";
740 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
741 // Register window class:
742 if (!RegisterClassEx(&win_class)) {
743 // It didn't work, so try to give a useful error:
744 printf("Unexpected error trying to start the application!\n");
745 fflush(stdout);
746 exit(1);
747 }
748 // Create window with the registered class:
749 m_window = CreateWindowEx(0,
750 "Test", // class name
751 "Test", // app name
752 WS_OVERLAPPEDWINDOW | // window style
753 WS_VISIBLE |
754 WS_SYSMENU,
755 100,100, // x/y coords
756 m_width, // width
757 m_height, // height
758 NULL, // handle to parent
759 NULL, // handle to menu
760 m_connection, // hInstance
761 NULL); // no extra parameters
762
763 if (!m_window) {
764 // It didn't work, so try to give a useful error:
765 DWORD error = GetLastError();
766 char message[120];
767 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
768 MessageBox(NULL, message, "Error", MB_OK);
769 exit(1);
770 }
Tony-LunarGf05ba082015-05-19 14:08:26 -0600771 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
772 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour25e3b832015-05-20 16:53:31 -0600773}
774#else
Tony Barbour01999182015-04-09 12:58:51 -0600775void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbouref20d322015-02-25 12:28:39 -0700776{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800777 const xcb_setup_t *setup;
778 xcb_screen_iterator_t iter;
779 int scr;
Tony Barbouref20d322015-02-25 12:28:39 -0700780 uint32_t value_mask, value_list[32];
781
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800782 m_connection = xcb_connect(NULL, &scr);
783
784 setup = xcb_get_setup(m_connection);
785 iter = xcb_setup_roots_iterator(setup);
786 while (scr-- > 0)
787 xcb_screen_next(&iter);
788
789 m_screen = iter.data;
790
791 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
792 it != m_images.end(); it++) {
793 if (m_width < it->m_width)
794 m_width = it->m_width;
795 if (m_height < it->m_height)
796 m_height = it->m_height;
797 }
798
799 m_window = xcb_generate_id(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700800
801 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800802 value_list[0] = m_screen->black_pixel;
Tony Barbouref20d322015-02-25 12:28:39 -0700803 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
804 XCB_EVENT_MASK_EXPOSURE |
805 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
806
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800807 xcb_create_window(m_connection,
Tony Barbouref20d322015-02-25 12:28:39 -0700808 XCB_COPY_FROM_PARENT,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800809 m_window, m_screen->root,
Tony Barbouref20d322015-02-25 12:28:39 -0700810 0, 0, m_width, m_height, 0,
811 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800812 m_screen->root_visual,
Tony Barbouref20d322015-02-25 12:28:39 -0700813 value_mask, value_list);
814
815 /* Magic code that will send notification when window is destroyed */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800816 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbouref20d322015-02-25 12:28:39 -0700817 "WM_PROTOCOLS");
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800818 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbouref20d322015-02-25 12:28:39 -0700819
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800820 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
821 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbouref20d322015-02-25 12:28:39 -0700822
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800823 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbouref20d322015-02-25 12:28:39 -0700824 m_window, (*reply).atom, 4, 32, 1,
825 &(*m_atom_wm_delete_window).atom);
826 free(reply);
827
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800828 xcb_map_window(m_connection, m_window);
Tony Barbouref20d322015-02-25 12:28:39 -0700829}
Tony Barbour25e3b832015-05-20 16:53:31 -0600830#endif
Tony Barbouref20d322015-02-25 12:28:39 -0700831
Tony Barbour01999182015-04-09 12:58:51 -0600832void TestFrameworkVkPresent::TearDown()
Tony Barbouref20d322015-02-25 12:28:39 -0700833{
Jon Ashburncedc15f2015-05-21 18:13:33 -0600834 m_fpDestroySwapChainWSI(m_swap_chain);
Tony Barbour25e3b832015-05-20 16:53:31 -0600835#ifndef _WIN32
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800836 xcb_destroy_window(m_connection, m_window);
837 xcb_disconnect(m_connection);
Tony Barbour25e3b832015-05-20 16:53:31 -0600838#endif
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600839}
840
Tony Barbour01999182015-04-09 12:58:51 -0600841void VkTestFramework::Finish()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600842{
843 if (m_images.size() == 0) return;
844
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800845 vk_testing::Environment env;
846 env.SetUp();
Tony Barbouref20d322015-02-25 12:28:39 -0700847 {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800848 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbouref20d322015-02-25 12:28:39 -0700849
Jon Ashburncedc15f2015-05-21 18:13:33 -0600850 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600851 vkPresent.CreateMyWindow();
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800852 vkPresent.CreateSwapChain();
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600853 vkPresent.Run();
854 vkPresent.TearDown();
Tony Barbouref20d322015-02-25 12:28:39 -0700855 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800856 env.TearDown();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600857}
858
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600859//
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600860// These are the default resources for TBuiltInResources, used for both
861// - parsing this string for the case where the user didn't supply one
862// - dumping out a template for user construction of a config file
863//
864static const char* DefaultConfig =
865 "MaxLights 32\n"
866 "MaxClipPlanes 6\n"
867 "MaxTextureUnits 32\n"
868 "MaxTextureCoords 32\n"
869 "MaxVertexAttribs 64\n"
870 "MaxVertexUniformComponents 4096\n"
871 "MaxVaryingFloats 64\n"
872 "MaxVertexTextureImageUnits 32\n"
873 "MaxCombinedTextureImageUnits 80\n"
874 "MaxTextureImageUnits 32\n"
875 "MaxFragmentUniformComponents 4096\n"
876 "MaxDrawBuffers 32\n"
877 "MaxVertexUniformVectors 128\n"
878 "MaxVaryingVectors 8\n"
879 "MaxFragmentUniformVectors 16\n"
880 "MaxVertexOutputVectors 16\n"
881 "MaxFragmentInputVectors 15\n"
882 "MinProgramTexelOffset -8\n"
883 "MaxProgramTexelOffset 7\n"
884 "MaxClipDistances 8\n"
885 "MaxComputeWorkGroupCountX 65535\n"
886 "MaxComputeWorkGroupCountY 65535\n"
887 "MaxComputeWorkGroupCountZ 65535\n"
888 "MaxComputeWorkGroupSizeX 1024\n"
889 "MaxComputeWorkGroupSizeY 1024\n"
890 "MaxComputeWorkGroupSizeZ 64\n"
891 "MaxComputeUniformComponents 1024\n"
892 "MaxComputeTextureImageUnits 16\n"
893 "MaxComputeImageUniforms 8\n"
894 "MaxComputeAtomicCounters 8\n"
895 "MaxComputeAtomicCounterBuffers 1\n"
896 "MaxVaryingComponents 60\n"
897 "MaxVertexOutputComponents 64\n"
898 "MaxGeometryInputComponents 64\n"
899 "MaxGeometryOutputComponents 128\n"
900 "MaxFragmentInputComponents 128\n"
901 "MaxImageUnits 8\n"
902 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
903 "MaxCombinedShaderOutputResources 8\n"
904 "MaxImageSamples 0\n"
905 "MaxVertexImageUniforms 0\n"
906 "MaxTessControlImageUniforms 0\n"
907 "MaxTessEvaluationImageUniforms 0\n"
908 "MaxGeometryImageUniforms 0\n"
909 "MaxFragmentImageUniforms 8\n"
910 "MaxCombinedImageUniforms 8\n"
911 "MaxGeometryTextureImageUnits 16\n"
912 "MaxGeometryOutputVertices 256\n"
913 "MaxGeometryTotalOutputComponents 1024\n"
914 "MaxGeometryUniformComponents 1024\n"
915 "MaxGeometryVaryingComponents 64\n"
916 "MaxTessControlInputComponents 128\n"
917 "MaxTessControlOutputComponents 128\n"
918 "MaxTessControlTextureImageUnits 16\n"
919 "MaxTessControlUniformComponents 1024\n"
920 "MaxTessControlTotalOutputComponents 4096\n"
921 "MaxTessEvaluationInputComponents 128\n"
922 "MaxTessEvaluationOutputComponents 128\n"
923 "MaxTessEvaluationTextureImageUnits 16\n"
924 "MaxTessEvaluationUniformComponents 1024\n"
925 "MaxTessPatchComponents 120\n"
926 "MaxPatchVertices 32\n"
927 "MaxTessGenLevel 64\n"
928 "MaxViewports 16\n"
929 "MaxVertexAtomicCounters 0\n"
930 "MaxTessControlAtomicCounters 0\n"
931 "MaxTessEvaluationAtomicCounters 0\n"
932 "MaxGeometryAtomicCounters 0\n"
933 "MaxFragmentAtomicCounters 8\n"
934 "MaxCombinedAtomicCounters 8\n"
935 "MaxAtomicCounterBindings 1\n"
936 "MaxVertexAtomicCounterBuffers 0\n"
937 "MaxTessControlAtomicCounterBuffers 0\n"
938 "MaxTessEvaluationAtomicCounterBuffers 0\n"
939 "MaxGeometryAtomicCounterBuffers 0\n"
940 "MaxFragmentAtomicCounterBuffers 1\n"
941 "MaxCombinedAtomicCounterBuffers 1\n"
942 "MaxAtomicCounterBufferSize 16384\n"
943 "MaxTransformFeedbackBuffers 4\n"
944 "MaxTransformFeedbackInterleavedComponents 64\n"
945 "MaxCullDistances 8\n"
946 "MaxCombinedClipAndCullDistances 8\n"
947 "MaxSamples 4\n"
948
949 "nonInductiveForLoops 1\n"
950 "whileLoops 1\n"
951 "doWhileLoops 1\n"
952 "generalUniformIndexing 1\n"
953 "generalAttributeMatrixVectorIndexing 1\n"
954 "generalVaryingIndexing 1\n"
955 "generalSamplerIndexing 1\n"
956 "generalVariableIndexing 1\n"
957 "generalConstantMatrixVectorIndexing 1\n"
958 ;
959
960//
961// *.conf => this is a config file that can set limits/resources
962//
Tony Barbour01999182015-04-09 12:58:51 -0600963bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600964{
965 if (name.size() < 5)
966 return false;
967
968 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
969 ConfigFile = name;
970 return true;
971 }
972
973 return false;
974}
975
976//
977// Parse either a .conf file provided by the user or the default string above.
978//
Tony Barbour01999182015-04-09 12:58:51 -0600979void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600980{
981 char** configStrings = 0;
982 char* config = 0;
983 if (ConfigFile.size() > 0) {
984 configStrings = ReadFileData(ConfigFile.c_str());
985 if (configStrings)
986 config = *configStrings;
987 else {
988 printf("Error opening configuration file; will instead use the default configuration\n");
989 }
990 }
991
992 if (config == 0) {
993 config = new char[strlen(DefaultConfig) + 1];
994 strcpy(config, DefaultConfig);
995 }
996
997 const char* delims = " \t\n\r";
998 const char* token = strtok(config, delims);
999 while (token) {
1000 const char* valueStr = strtok(0, delims);
1001 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1002 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1003 return;
1004 }
1005 int value = atoi(valueStr);
1006
1007 if (strcmp(token, "MaxLights") == 0)
1008 Resources.maxLights = value;
1009 else if (strcmp(token, "MaxClipPlanes") == 0)
1010 Resources.maxClipPlanes = value;
1011 else if (strcmp(token, "MaxTextureUnits") == 0)
1012 Resources.maxTextureUnits = value;
1013 else if (strcmp(token, "MaxTextureCoords") == 0)
1014 Resources.maxTextureCoords = value;
1015 else if (strcmp(token, "MaxVertexAttribs") == 0)
1016 Resources.maxVertexAttribs = value;
1017 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1018 Resources.maxVertexUniformComponents = value;
1019 else if (strcmp(token, "MaxVaryingFloats") == 0)
1020 Resources.maxVaryingFloats = value;
1021 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1022 Resources.maxVertexTextureImageUnits = value;
1023 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1024 Resources.maxCombinedTextureImageUnits = value;
1025 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1026 Resources.maxTextureImageUnits = value;
1027 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1028 Resources.maxFragmentUniformComponents = value;
1029 else if (strcmp(token, "MaxDrawBuffers") == 0)
1030 Resources.maxDrawBuffers = value;
1031 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1032 Resources.maxVertexUniformVectors = value;
1033 else if (strcmp(token, "MaxVaryingVectors") == 0)
1034 Resources.maxVaryingVectors = value;
1035 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1036 Resources.maxFragmentUniformVectors = value;
1037 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1038 Resources.maxVertexOutputVectors = value;
1039 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1040 Resources.maxFragmentInputVectors = value;
1041 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1042 Resources.minProgramTexelOffset = value;
1043 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1044 Resources.maxProgramTexelOffset = value;
1045 else if (strcmp(token, "MaxClipDistances") == 0)
1046 Resources.maxClipDistances = value;
1047 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1048 Resources.maxComputeWorkGroupCountX = value;
1049 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1050 Resources.maxComputeWorkGroupCountY = value;
1051 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1052 Resources.maxComputeWorkGroupCountZ = value;
1053 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1054 Resources.maxComputeWorkGroupSizeX = value;
1055 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1056 Resources.maxComputeWorkGroupSizeY = value;
1057 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1058 Resources.maxComputeWorkGroupSizeZ = value;
1059 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1060 Resources.maxComputeUniformComponents = value;
1061 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1062 Resources.maxComputeTextureImageUnits = value;
1063 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1064 Resources.maxComputeImageUniforms = value;
1065 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1066 Resources.maxComputeAtomicCounters = value;
1067 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1068 Resources.maxComputeAtomicCounterBuffers = value;
1069 else if (strcmp(token, "MaxVaryingComponents") == 0)
1070 Resources.maxVaryingComponents = value;
1071 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1072 Resources.maxVertexOutputComponents = value;
1073 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1074 Resources.maxGeometryInputComponents = value;
1075 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1076 Resources.maxGeometryOutputComponents = value;
1077 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1078 Resources.maxFragmentInputComponents = value;
1079 else if (strcmp(token, "MaxImageUnits") == 0)
1080 Resources.maxImageUnits = value;
1081 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1082 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1083 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1084 Resources.maxCombinedShaderOutputResources = value;
1085 else if (strcmp(token, "MaxImageSamples") == 0)
1086 Resources.maxImageSamples = value;
1087 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1088 Resources.maxVertexImageUniforms = value;
1089 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1090 Resources.maxTessControlImageUniforms = value;
1091 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1092 Resources.maxTessEvaluationImageUniforms = value;
1093 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1094 Resources.maxGeometryImageUniforms = value;
1095 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1096 Resources.maxFragmentImageUniforms = value;
1097 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1098 Resources.maxCombinedImageUniforms = value;
1099 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1100 Resources.maxGeometryTextureImageUnits = value;
1101 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1102 Resources.maxGeometryOutputVertices = value;
1103 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1104 Resources.maxGeometryTotalOutputComponents = value;
1105 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1106 Resources.maxGeometryUniformComponents = value;
1107 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1108 Resources.maxGeometryVaryingComponents = value;
1109 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1110 Resources.maxTessControlInputComponents = value;
1111 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1112 Resources.maxTessControlOutputComponents = value;
1113 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1114 Resources.maxTessControlTextureImageUnits = value;
1115 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1116 Resources.maxTessControlUniformComponents = value;
1117 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1118 Resources.maxTessControlTotalOutputComponents = value;
1119 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1120 Resources.maxTessEvaluationInputComponents = value;
1121 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1122 Resources.maxTessEvaluationOutputComponents = value;
1123 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1124 Resources.maxTessEvaluationTextureImageUnits = value;
1125 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1126 Resources.maxTessEvaluationUniformComponents = value;
1127 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1128 Resources.maxTessPatchComponents = value;
1129 else if (strcmp(token, "MaxPatchVertices") == 0)
1130 Resources.maxPatchVertices = value;
1131 else if (strcmp(token, "MaxTessGenLevel") == 0)
1132 Resources.maxTessGenLevel = value;
1133 else if (strcmp(token, "MaxViewports") == 0)
1134 Resources.maxViewports = value;
1135 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1136 Resources.maxVertexAtomicCounters = value;
1137 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1138 Resources.maxTessControlAtomicCounters = value;
1139 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1140 Resources.maxTessEvaluationAtomicCounters = value;
1141 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1142 Resources.maxGeometryAtomicCounters = value;
1143 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1144 Resources.maxFragmentAtomicCounters = value;
1145 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1146 Resources.maxCombinedAtomicCounters = value;
1147 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1148 Resources.maxAtomicCounterBindings = value;
1149 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1150 Resources.maxVertexAtomicCounterBuffers = value;
1151 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1152 Resources.maxTessControlAtomicCounterBuffers = value;
1153 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1154 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1155 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1156 Resources.maxGeometryAtomicCounterBuffers = value;
1157 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1158 Resources.maxFragmentAtomicCounterBuffers = value;
1159 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1160 Resources.maxCombinedAtomicCounterBuffers = value;
1161 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1162 Resources.maxAtomicCounterBufferSize = value;
1163 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1164 Resources.maxTransformFeedbackBuffers = value;
1165 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1166 Resources.maxTransformFeedbackInterleavedComponents = value;
1167 else if (strcmp(token, "MaxCullDistances") == 0)
1168 Resources.maxCullDistances = value;
1169 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1170 Resources.maxCombinedClipAndCullDistances = value;
1171 else if (strcmp(token, "MaxSamples") == 0)
1172 Resources.maxSamples = value;
1173
1174 else if (strcmp(token, "nonInductiveForLoops") == 0)
1175 Resources.limits.nonInductiveForLoops = (value != 0);
1176 else if (strcmp(token, "whileLoops") == 0)
1177 Resources.limits.whileLoops = (value != 0);
1178 else if (strcmp(token, "doWhileLoops") == 0)
1179 Resources.limits.doWhileLoops = (value != 0);
1180 else if (strcmp(token, "generalUniformIndexing") == 0)
1181 Resources.limits.generalUniformIndexing = (value != 0);
1182 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1183 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1184 else if (strcmp(token, "generalVaryingIndexing") == 0)
1185 Resources.limits.generalVaryingIndexing = (value != 0);
1186 else if (strcmp(token, "generalSamplerIndexing") == 0)
1187 Resources.limits.generalSamplerIndexing = (value != 0);
1188 else if (strcmp(token, "generalVariableIndexing") == 0)
1189 Resources.limits.generalVariableIndexing = (value != 0);
1190 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1191 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1192 else
1193 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1194
1195 token = strtok(0, delims);
1196 }
1197 if (configStrings)
1198 FreeFileData(configStrings);
1199}
1200
Tony Barbour01999182015-04-09 12:58:51 -06001201void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001202{
1203 if (m_compile_options & EOptionRelaxedErrors)
1204 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1205 if (m_compile_options & EOptionIntermediate)
1206 messages = (EShMessages)(messages | EShMsgAST);
1207 if (m_compile_options & EOptionSuppressWarnings)
1208 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1209}
1210
1211//
1212// Malloc a string of sufficient size and read a string into it.
1213//
Tony Barbour01999182015-04-09 12:58:51 -06001214char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001215{
1216 FILE *in;
1217 #if defined(_WIN32) && defined(__GNUC__)
1218 in = fopen(fileName, "r");
1219 int errorCode = in ? 0 : 1;
1220 #else
1221 int errorCode = fopen_s(&in, fileName, "r");
1222 #endif
1223
1224 char *fdata;
1225 int count = 0;
1226 const int maxSourceStrings = 5;
1227 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1228
1229 if (errorCode) {
1230 printf("Error: unable to open input file: %s\n", fileName);
1231 return 0;
1232 }
1233
1234 while (fgetc(in) != EOF)
1235 count++;
1236
1237 fseek(in, 0, SEEK_SET);
1238
1239 if (!(fdata = (char*)malloc(count+2))) {
1240 printf("Error allocating memory\n");
1241 return 0;
1242 }
1243 if (fread(fdata,1,count, in)!=count) {
1244 printf("Error reading input file: %s\n", fileName);
1245 return 0;
1246 }
1247 fdata[count] = '\0';
1248 fclose(in);
1249 if (count == 0) {
1250 return_data[0]=(char*)malloc(count+2);
1251 return_data[0][0]='\0';
1252 m_num_shader_strings = 0;
1253 return return_data;
1254 } else
1255 m_num_shader_strings = 1;
1256
1257 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1258 int ptr_len=0,i=0;
1259 while(count>0){
1260 return_data[i]=(char*)malloc(len+2);
1261 memcpy(return_data[i],fdata+ptr_len,len);
1262 return_data[i][len]='\0';
1263 count-=(len);
1264 ptr_len+=(len);
1265 if(count<len){
1266 if(count==0){
1267 m_num_shader_strings=(i+1);
1268 break;
1269 }
1270 len = count;
1271 }
1272 ++i;
1273 }
1274 return return_data;
1275}
1276
Tony Barbour01999182015-04-09 12:58:51 -06001277void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001278{
1279 for(int i=0;i<m_num_shader_strings;i++)
1280 free(data[i]);
1281}
1282
1283//
1284// Deduce the language from the filename. Files must end in one of the
1285// following extensions:
1286//
1287// .vert = vertex
1288// .tesc = tessellation control
1289// .tese = tessellation evaluation
1290// .geom = geometry
1291// .frag = fragment
1292// .comp = compute
1293//
Tony Barbour01999182015-04-09 12:58:51 -06001294EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001295{
1296 size_t ext = name.rfind('.');
1297 if (ext == std::string::npos) {
1298 return EShLangVertex;
1299 }
1300
1301 std::string suffix = name.substr(ext + 1, std::string::npos);
1302 if (suffix == "vert")
1303 return EShLangVertex;
1304 else if (suffix == "tesc")
1305 return EShLangTessControl;
1306 else if (suffix == "tese")
1307 return EShLangTessEvaluation;
1308 else if (suffix == "geom")
1309 return EShLangGeometry;
1310 else if (suffix == "frag")
1311 return EShLangFragment;
1312 else if (suffix == "comp")
1313 return EShLangCompute;
1314
1315 return EShLangVertex;
1316}
1317
1318//
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001319// Convert VK shader type to compiler's
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001320//
Tony Barbour8205d902015-04-16 15:59:00 -06001321EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001322{
1323 switch (shader_type) {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001324 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001325 return EShLangVertex;
1326
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001327 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001328 return EShLangTessControl;
1329
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001330 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001331 return EShLangTessEvaluation;
1332
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001333 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001334 return EShLangGeometry;
1335
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001336 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001337 return EShLangFragment;
1338
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001339 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001340 return EShLangCompute;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001341
Chia-I Wubbdeacc2014-12-15 23:50:11 +08001342 default:
1343 return EShLangVertex;
1344 }
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001345}
1346
1347
1348//
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001349// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001350// Return value of false means an error was encountered.
1351//
Tony Barbour8205d902015-04-16 15:59:00 -06001352bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001353 const char *pshader,
Cody Northropeb9130e2015-06-03 13:01:54 -06001354 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001355{
1356 glslang::TProgram& program = *new glslang::TProgram;
1357 const char *shaderStrings[1];
1358
1359 // TODO: Do we want to load a special config file depending on the
1360 // shader source? Optional name maybe?
1361 // SetConfigFile(fileName);
1362
1363 ProcessConfigFile();
1364
1365 EShMessages messages = EShMsgDefault;
1366 SetMessageOptions(messages);
1367
1368 EShLanguage stage = FindLanguage(shader_type);
1369 glslang::TShader* shader = new glslang::TShader(stage);
1370
1371 shaderStrings[0] = pshader;
1372 shader->setStrings(shaderStrings, 1);
1373
1374 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1375
Cody Northropad306f02014-11-03 12:54:37 -07001376 if (! (m_compile_options & EOptionSuppressInfolog)) {
1377 puts(shader->getInfoLog());
1378 puts(shader->getInfoDebugLog());
1379 }
1380
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001381 return false; // something didn't work
1382 }
1383
1384 program.addShader(shader);
1385
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001386
1387 //
1388 // Program-level processing...
1389 //
1390
Cody Northropad306f02014-11-03 12:54:37 -07001391 if (! program.link(messages)) {
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001392
Cody Northropad306f02014-11-03 12:54:37 -07001393 if (! (m_compile_options & EOptionSuppressInfolog)) {
1394 puts(shader->getInfoLog());
1395 puts(shader->getInfoDebugLog());
1396 }
1397
1398 return false;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001399 }
1400
1401 if (m_compile_options & EOptionDumpReflection) {
1402 program.buildReflection();
1403 program.dumpReflection();
1404 }
1405
Cody Northropeb9130e2015-06-03 13:01:54 -06001406 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1407
1408 //
1409 // Test the different modes of SPIR-V modification
1410 //
1411 if (this->m_canonicalize_spv) {
1412 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1413 }
1414
1415 if (this->m_strip_spv) {
1416 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1417 }
1418
1419 if (this->m_do_everything_spv) {
1420 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1421 }
1422
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001423
1424 return true;
1425}
1426
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001427
1428
Tony Barbour01999182015-04-09 12:58:51 -06001429VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001430 m_width( 0 ),
1431 m_height( 0 ),
Chia-I Wub2c2dea2014-12-15 23:29:34 +08001432 m_data( NULL ),
1433 m_data_size( 0 )
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001434{
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001435}
1436
Tony Barbour01999182015-04-09 12:58:51 -06001437VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001438{
1439
1440}
1441
Tony Barbour01999182015-04-09 12:58:51 -06001442VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001443{
1444 m_title = copyin.m_title;
1445 m_width = copyin.m_width;
1446 m_height = copyin.m_height;
1447 m_data_size = copyin.m_data_size;
1448 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1449}
1450
Tony Barbour01999182015-04-09 12:58:51 -06001451ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001452{
Tony Barbour01999182015-04-09 12:58:51 -06001453 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1454 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001455 return output;
1456}
1457
Tony Barbour01999182015-04-09 12:58:51 -06001458VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001459{
1460 m_title = rhs.m_title;
1461 m_width = rhs.m_width;
1462 m_height = rhs.m_height;
1463 m_data_size = rhs.m_data_size;
1464 m_data = rhs.m_data;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001465 return *this;
1466}
1467
Tony Barbour01999182015-04-09 12:58:51 -06001468int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001469{
1470 if( this->m_data != rhs.m_data) return 0;
1471 return 1;
1472}
1473
1474// This function is required for built-in STL list functions like sort
Tony Barbour01999182015-04-09 12:58:51 -06001475int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001476{
1477 if( this->m_data_size < rhs.m_data_size ) return 1;
1478 return 0;
1479}
1480