blob: 880fa68e8743e9f6d6c1d71dd1c0b3f6fece601f [file] [log] [blame]
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001// VK tests
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06002//
3// Copyright (C) 2014 LunarG, Inc.
4//
5// Permission is hereby granted, free of charge, to any person obtaining a
6// copy of this software and associated documentation files (the "Software"),
7// to deal in the Software without restriction, including without limitation
8// the rights to use, copy, modify, merge, publish, distribute, sublicense,
9// and/or sell copies of the Software, and to permit persons to whom the
10// Software is furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included
13// in all copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21// DEALINGS IN THE SOFTWARE.
22
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060023#include "vktestframework.h"
24#include "vkrenderframework.h"
Cody Northrop5a95b472015-06-03 13:01:54 -060025#include "SPIRV/GlslangToSpv.h"
26#include "SPIRV/SPVRemapper.h"
Tony Barbour4ab45422014-12-10 17:00:20 -070027#include <limits.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060028#include <math.h>
Chia-I Wuec664fa2014-12-02 11:54:24 +080029#include <wand/MagickWand.h>
Chia-I Wuf8693382015-04-16 22:02:10 +080030#include <xcb/xcb.h>
31#include <vk_wsi_lunarg.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060032
Tony Barbour3d69c9e2015-05-20 16:53:31 -060033#if defined(PATH_MAX) && !defined(MAX_PATH)
34#define MAX_PATH PATH_MAX
35#endif
36
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060037// Command-line options
38enum TOptions {
39 EOptionNone = 0x000,
40 EOptionIntermediate = 0x001,
41 EOptionSuppressInfolog = 0x002,
42 EOptionMemoryLeakMode = 0x004,
43 EOptionRelaxedErrors = 0x008,
44 EOptionGiveWarnings = 0x010,
45 EOptionLinkProgram = 0x020,
46 EOptionMultiThreaded = 0x040,
47 EOptionDumpConfig = 0x080,
48 EOptionDumpReflection = 0x100,
49 EOptionSuppressWarnings = 0x200,
50 EOptionDumpVersions = 0x400,
Cody Northrop3bfd27c2015-03-17 15:55:58 -060051 EOptionSpv = 0x800,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060052 EOptionDefaultDesktop = 0x1000,
53};
54
Chia-I Wuf8693382015-04-16 22:02:10 +080055class TestFrameworkVkPresent
56{
57public:
58 TestFrameworkVkPresent(vk_testing::Device &device);
59
60 void Run();
Jon Ashburn07daee72015-05-21 18:13:33 -060061 void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst);
Chia-I Wuf8693382015-04-16 22:02:10 +080062 void CreateMyWindow();
63 void CreateSwapChain();
64 void TearDown();
Tony Barbour3d69c9e2015-05-20 16:53:31 -060065#ifdef _WIN32
66 static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
67#endif
68
Chia-I Wuf8693382015-04-16 22:02:10 +080069
70protected:
71 vk_testing::Device &m_device;
72 vk_testing::Queue &m_queue;
73 vk_testing::CmdBuffer m_cmdbuf;
74
75private:
Tony Barbour3d69c9e2015-05-20 16:53:31 -060076#ifdef _WIN32
77 HINSTANCE m_connection; // hInstance - Windows Instance
78 HWND m_window; // hWnd - window handle
79
80#else
Chia-I Wuf8693382015-04-16 22:02:10 +080081 xcb_connection_t *m_connection;
82 xcb_screen_t *m_screen;
83 xcb_window_t m_window;
84 xcb_intern_atom_reply_t *m_atom_wm_delete_window;
Tony Barbour3d69c9e2015-05-20 16:53:31 -060085#endif
Courtney Goeltzenleuchterd6079ec2015-04-22 10:09:35 -060086 std::list<VkTestImageRecord> m_images;
Chia-I Wuf8693382015-04-16 22:02:10 +080087
Jon Ashburn07daee72015-05-21 18:13:33 -060088 PFN_vkCreateSwapChainWSI m_fpCreateSwapChainWSI;
89 PFN_vkDestroySwapChainWSI m_fpDestroySwapChainWSI;
90 PFN_vkGetSwapChainInfoWSI m_fpGetSwapChainInfoWSI;
91 PFN_vkQueuePresentWSI m_fpQueuePresentWSI;
92
Chia-I Wuf8693382015-04-16 22:02:10 +080093 VkSwapChainWSI m_swap_chain;
Tony-LunarG399dfca2015-05-19 14:08:26 -060094 std::vector<VkSwapChainImageInfoWSI> m_persistent_images;
95 int m_current_buffer;
Chia-I Wuf8693382015-04-16 22:02:10 +080096
97 bool m_quit;
98 bool m_pause;
99
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600100 int m_width;
101 int m_height;
Chia-I Wuf8693382015-04-16 22:02:10 +0800102
103 std::list<VkTestImageRecord>::iterator m_display_image;
104
105 void Display();
106 void HandleEvent(xcb_generic_event_t *event);
107};
108
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600109#ifndef _WIN32
110
111#include <errno.h>
112
113int fopen_s(
114 FILE** pFile,
115 const char* filename,
116 const char* mode
117)
118{
119 if (!pFile || !filename || !mode) {
120 return EINVAL;
121 }
122
123 FILE* f = fopen(filename, mode);
124 if (! f) {
125 if (errno != 0) {
126 return errno;
127 } else {
128 return ENOENT;
129 }
130 }
131 *pFile = f;
132
133 return 0;
134}
135
136#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600137
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600138
139
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600140// Set up environment for GLSL compiler
141// Must be done once per process
142void TestEnvironment::SetUp()
143{
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600144 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600145 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800146
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600147 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600148}
149
150void TestEnvironment::TearDown()
151{
152 glslang::FinalizeProcess();
153}
154
Tony Barbour6918cd52015-04-09 12:58:51 -0600155VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600156 m_compile_options( 0 ),
157 m_num_shader_strings( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600158{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600159
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600160}
161
Tony Barbour6918cd52015-04-09 12:58:51 -0600162VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600163{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600164
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600165}
166
167// Define all the static elements
Tony Barbour6918cd52015-04-09 12:58:51 -0600168bool VkTestFramework::m_show_images = false;
169bool VkTestFramework::m_save_images = false;
170bool VkTestFramework::m_compare_images = false;
Tony Barbour0dd968a2015-04-02 15:48:24 -0600171#ifdef _WIN32
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600172bool VkTestFramework::m_use_glsl = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600173bool VkTestFramework::m_canonicalize_spv = false;
174bool VkTestFramework::m_strip_spv = false;
175bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour0dd968a2015-04-02 15:48:24 -0600176#else
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600177bool VkTestFramework::m_use_glsl = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600178bool VkTestFramework::m_canonicalize_spv = false;
179bool VkTestFramework::m_strip_spv = false;
180bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour0dd968a2015-04-02 15:48:24 -0600181#endif
Tony Barbour6918cd52015-04-09 12:58:51 -0600182int VkTestFramework::m_width = 0;
183int VkTestFramework::m_height = 0;
184std::list<VkTestImageRecord> VkTestFramework::m_images;
185std::list<VkTestImageRecord>::iterator VkTestFramework::m_display_image;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600186int m_display_image_idx = 0;
187
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600188bool VkTestFramework::optionMatch(const char* option, char* optionLine)
189{
190 if (strncmp(option, optionLine, strlen(option)) == 0)
191 return true;
192 else
193 return false;
194}
195
Tony Barbour6918cd52015-04-09 12:58:51 -0600196void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600197{
198 int i, n;
199
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600200 for (i=1, n=1; i< *argc; i++) {
201 if (optionMatch("--show-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600202 m_show_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600203 else if (optionMatch("--save-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600204 m_save_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600205 else if (optionMatch("--no-SPV", argv[i]))
206 m_use_glsl = true;
207 else if (optionMatch("--strip-SPV", argv[i]))
208 m_strip_spv = true;
209 else if (optionMatch("--canonicalize-SPV", argv[i]))
210 m_canonicalize_spv = true;
211 else if (optionMatch("--compare-images", argv[i]))
Tony Barbour247bf372014-10-30 14:29:04 -0600212 m_compare_images = true;
Tony Barbour247bf372014-10-30 14:29:04 -0600213
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600214 else if (optionMatch("--help", argv[i]) ||
215 optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700216 printf("\nOther options:\n");
217 printf("\t--show-images\n"
218 "\t\tDisplay test images in viewer after tests complete.\n");
219 printf("\t--save-images\n"
220 "\t\tSave tests images as ppm files in current working directory.\n"
221 "\t\tUsed to generate golden images for compare-images.\n");
222 printf("\t--compare-images\n"
223 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barboura98d3932014-12-11 09:52:49 -0700224 "\t\tAlso saves the generated test image in current working\n"
225 "\t\t\tdirectory but only if the image is different from the golden\n"
226 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
227 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700228 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600229 printf("\t--no-SPV\n"
230 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600231 printf("\t--strip-SPV\n"
232 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
233 printf("\t--canonicalize-SPV\n"
234 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
235 exit(0);
236 } else {
237 printf("\nUnrecognized option: %s\n", argv[i]);
238 printf("\nUse --help or -h for option list.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700239 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700240 }
241
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600242 /*
243 * Since the above "consume" inputs, update argv
244 * so that it contains the trimmed list of args for glutInit
245 */
246
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600247 argv[n] = argv[i];
248 n++;
249 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600250}
251
Tony Barbour6918cd52015-04-09 12:58:51 -0600252void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600253{
254 string filename;
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600255 VkResult err;
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600256 uint32_t x, y;
Tony Barbour6918cd52015-04-09 12:58:51 -0600257 VkImageObj displayImage(image->device());
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600258 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbour84d448c2015-04-02 14:02:33 -0600259
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600260 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, VK_IMAGE_TILING_LINEAR, reqs);
Tony Barbour84d448c2015-04-02 14:02:33 -0600261 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600262
263 filename.append(basename);
264 filename.append(".ppm");
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600265
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600266 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600267 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600268 };
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600269 VkSubresourceLayout sr_layout;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600270
Tony Barbour59a47322015-06-24 16:06:58 -0600271 err = vkGetImageSubresourceLayout(image->device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600272 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600273
Tony Barbour84d448c2015-04-02 14:02:33 -0600274 char *ptr;
275 ptr = (char *) displayImage.map();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600276 ptr += sr_layout.offset;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600277 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600278 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
279
280 file << "P6\n";
Tony Barbour84d448c2015-04-02 14:02:33 -0600281 file << displayImage.width() << "\n";
282 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600283 file << 255 << "\n";
284
Tony Barbour84d448c2015-04-02 14:02:33 -0600285 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700286 const int *row = (const int *) ptr;
287 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600288
Tony Barbourd1c35722015-04-16 15:59:00 -0600289 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700290 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600291 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700292 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
293 file.write((char *) &swapped, 3);
294 row++;
295 }
296 }
Tony Barbourd1c35722015-04-16 15:59:00 -0600297 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700298 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600299 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700300 file.write((char *) row, 3);
301 row++;
302 }
303 }
304 else {
305 printf("Unrecognized image format - will not write image files");
306 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600307 }
308
309 ptr += sr_layout.rowPitch;
310 }
311
312 file.close();
Tony Barbour84d448c2015-04-02 14:02:33 -0600313 displayImage.unmap();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600314}
315
Tony Barbour6918cd52015-04-09 12:58:51 -0600316void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour247bf372014-10-30 14:29:04 -0600317{
318
319 MagickWand *magick_wand_1;
320 MagickWand *magick_wand_2;
321 MagickWand *compare_wand;
322 MagickBooleanType status;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600323 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600324 double differenz;
325
Tony Barbour4ab45422014-12-10 17:00:20 -0700326 if (getenv("RENDERTEST_GOLDEN_DIR"))
327 {
328 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
329 }
330
Tony Barbour247bf372014-10-30 14:29:04 -0600331 MagickWandGenesis();
332 magick_wand_1=NewMagickWand();
333 sprintf(testimage,"%s.ppm",basename);
334 status=MagickReadImage(magick_wand_1,testimage);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600335 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour247bf372014-10-30 14:29:04 -0600336
337
338 MagickWandGenesis();
339 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700340 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600341 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600342 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour247bf372014-10-30 14:29:04 -0600343
Tony Barbour247bf372014-10-30 14:29:04 -0600344 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
345 if (differenz != 0.0)
346 {
347 char difference[256];
348
349 sprintf(difference,"%s-diff.ppm",basename);
350 status = MagickWriteImage(compare_wand, difference);
351 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
352 }
353 DestroyMagickWand(compare_wand);
354
355 DestroyMagickWand(magick_wand_1);
356 DestroyMagickWand(magick_wand_2);
357 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700358
359 if (differenz == 0.0)
360 {
361 /*
362 * If test image and golden image match, we do not need to
363 * keep around the test image.
364 */
365 remove(testimage);
366 }
Tony Barbour247bf372014-10-30 14:29:04 -0600367}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600368
Tony Barbour6918cd52015-04-09 12:58:51 -0600369void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600370{
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600371 VkResult err;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600372 VkSubresourceLayout sr_layout;
373 char *ptr;
374 VkTestImageRecord record;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600375 VkImageObj displayImage(image->device());
376 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
377
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600378 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, VK_IMAGE_TILING_LINEAR, reqs);
379 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600380
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600381 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600382 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600383 };
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600384
Tony Barbour59a47322015-06-24 16:06:58 -0600385 err = vkGetImageSubresourceLayout(displayImage.device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600386 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600387
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600388 err = displayImage.MapMemory( (void **) &ptr );
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600389 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600390
391 ptr += sr_layout.offset;
392
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600393 record.m_title.append(comment);
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600394 record.m_width = displayImage.width();
395 record.m_height = displayImage.height();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600396 // TODO: Need to make this more robust to handle different image formats
Tony-LunarG399dfca2015-05-19 14:08:26 -0600397 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600398 record.m_data = malloc(record.m_data_size);
399 memcpy(record.m_data, ptr, record.m_data_size);
400 m_images.push_back(record);
401 m_display_image = --m_images.end();
402
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600403 err = displayImage.UnmapMemory();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600404 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600405}
406
Tony Barbour6918cd52015-04-09 12:58:51 -0600407void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600408{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600409 for (int32_t i = 0; i < images.size(); i++) {
410 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600411 }
412}
413
Tony Barbour6918cd52015-04-09 12:58:51 -0600414void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600415{
416 const ::testing::TestInfo* const test_info =
417 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600418 ostringstream filestream;
419 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600420
Tony Barbour247bf372014-10-30 14:29:04 -0600421 m_width = 40;
422
423 if (strcmp(test_info->name(), m_testName.c_str())) {
424 filestream << test_info->name();
425 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700426 m_frameNum = 2;
427 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600428 }
429 else {
430 filestream << test_info->name() << "-" << m_frameNum;
431 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700432 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600433 }
434
Tony Barbour247bf372014-10-30 14:29:04 -0600435 // ToDo - scrub string for bad characters
436
437 if (m_save_images || m_compare_images) {
438 WritePPM(filename.c_str(), image);
439 if (m_compare_images) {
440 Compare(filename.c_str(), image);
441 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600442 }
443
444 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600445 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600446 }
447}
448
Chia-I Wuf8693382015-04-16 22:02:10 +0800449TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
450 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700451 m_queue(*m_device.graphics_queues()[0]),
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600452 m_cmdbuf(m_device, vk_testing::CmdBuffer::create_info(m_device.graphics_queue_node_index_))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600453{
Tony Barbour96db8822015-02-25 12:28:39 -0700454 m_quit = false;
455 m_pause = false;
456 m_width = 0;
457 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600458}
459
Tony Barbour6918cd52015-04-09 12:58:51 -0600460void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600461{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600462 VkResult U_ASSERT_ONLY err;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600463 vk_testing::Buffer buf;
464 void *dest_ptr;
465
466 if (m_persistent_images.size() != 2) {
467 return;
468 }
469
470 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
471 buf.init(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
472 dest_ptr = buf.map();
473 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
474 buf.unmap();
475
476 m_cmdbuf.begin();
477
478 VkBufferImageCopy region = {};
479 region.imageExtent.height = m_display_image->m_height;
480 region.imageExtent.width = m_display_image->m_width;
481 region.imageExtent.depth = 1;
482
483 vkCmdCopyBufferToImage(m_cmdbuf.obj(),
484 buf.obj(),
485 m_persistent_images[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
486 1, &region);
487 m_cmdbuf.end();
488
489 VkCmdBuffer cmdBufs[1];
490 cmdBufs[0] = m_cmdbuf.obj();
491
492 vkQueueSubmit(m_queue.obj(), 1, cmdBufs, NULL);
493 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700494
Chia-I Wuf8693382015-04-16 22:02:10 +0800495 VkPresentInfoWSI present = {};
496 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_WSI;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600497 present.image = m_persistent_images[m_current_buffer].image;
Chia-I Wuf8693382015-04-16 22:02:10 +0800498 present.flipInterval = 1;
Tony Barbour96db8822015-02-25 12:28:39 -0700499
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600500#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800501 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700502 XCB_PROP_MODE_REPLACE,
503 m_window,
504 XCB_ATOM_WM_NAME,
505 XCB_ATOM_STRING,
506 8,
507 m_display_image->m_title.size(),
508 m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600509#endif
Jon Ashburn07daee72015-05-21 18:13:33 -0600510
511 err = m_fpQueuePresentWSI(m_queue.obj(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700512 assert(!err);
513
514 m_queue.wait();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600515 m_current_buffer = (m_current_buffer + 1) % 2;
Tony Barbour96db8822015-02-25 12:28:39 -0700516
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600517}
518
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600519#ifdef _WIN32
Tony-LunarG399dfca2015-05-19 14:08:26 -0600520# define PREVIOUSLY_DOWN 1<<29
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600521// MS-Windows event handling function:
522LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
523 UINT uMsg,
524 WPARAM wParam,
525 LPARAM lParam)
526{
527
528 switch(uMsg)
529 {
530 case WM_CLOSE:
531 PostQuitMessage(0);
532 break;
533
534 case WM_PAINT:
535 {
536 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
537 if (me) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600538 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600539 me->Display();
540 }
541 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600542 break;
543
544 case WM_KEYDOWN:
545 {
546 if (lParam & (PREVIOUSLY_DOWN)){
547 break;
548 }
549 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
550 // the window, we put the this pointer into the window's user data so we could get it back now
551 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
552 switch (wParam)
553 {
554 case VK_ESCAPE: me->m_quit = true;
555 break;
556
557 case VK_LEFT: // left arrow key
558 if (me->m_display_image == me->m_images.begin()) {
559 me->m_display_image = --me->m_images.end();
560 }
561 else {
562 --me->m_display_image;
563 }
564 break;
565
566 case VK_RIGHT: // right arrow key
567 ++me->m_display_image;
568 if (me->m_display_image == me->m_images.end()) {
569 me->m_display_image = me->m_images.begin();
570 }
571 break;
572
573 default:
574 break;
575 }
576 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
577 me->Display();
578 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600579 }
580 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
581}
582
583void TestFrameworkVkPresent::Run()
584{
585 MSG msg; // message
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600586
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600587 /* main message loop*/
Tony-LunarG399dfca2015-05-19 14:08:26 -0600588 while(! m_quit) {
589 GetMessage(&msg, m_window, 0, 0);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600590 if (msg.message == WM_QUIT) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600591 m_quit = true; //if found, quit app
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600592 } else {
593 /* Translate and dispatch to event queue*/
594 TranslateMessage(&msg);
595 DispatchMessage(&msg);
596 }
597 }
598}
599
600#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600601void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600602{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600603 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700604 switch (event_code) {
605 case XCB_EXPOSE:
606 Display(); // TODO: handle resize
607 break;
608 case XCB_CLIENT_MESSAGE:
609 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
610 (m_atom_wm_delete_window)->atom) {
611 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600612 }
613 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700614 case XCB_KEY_RELEASE:
615 {
616 const xcb_key_release_event_t *key =
617 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600618
Tony Barbour96db8822015-02-25 12:28:39 -0700619 switch (key->detail) {
620 case 0x9: // Escape
621 m_quit = true;
622 break;
623 case 0x71: // left arrow key
624 if (m_display_image == m_images.begin()) {
625 m_display_image = --m_images.end();
626 } else {
627 --m_display_image;
628 }
629 break;
630 case 0x72: // right arrow key
631 ++m_display_image;
632 if (m_display_image == m_images.end()) {
633 m_display_image = m_images.begin();
634 }
635 break;
636 case 0x41:
637 m_pause = !m_pause;
638 break;
639 }
640 Display();
641 }
642 break;
643 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600644 break;
645 }
Tony Barbour96db8822015-02-25 12:28:39 -0700646}
647
Tony Barbour6918cd52015-04-09 12:58:51 -0600648void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700649{
Chia-I Wuf8693382015-04-16 22:02:10 +0800650 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700651
652 while (! m_quit) {
653 xcb_generic_event_t *event;
654
655 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800656 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700657 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800658 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700659 }
660 if (event) {
661 HandleEvent(event);
662 free(event);
663 }
664 }
665}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600666#endif // _WIN32
Tony Barbour96db8822015-02-25 12:28:39 -0700667
Chia-I Wuf8693382015-04-16 22:02:10 +0800668void TestFrameworkVkPresent::CreateSwapChain()
Tony Barbour96db8822015-02-25 12:28:39 -0700669{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600670 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700671
Tony-LunarG399dfca2015-05-19 14:08:26 -0600672 m_display_image = m_images.begin();
673 m_current_buffer = 0;
674
Chia-I Wuf8693382015-04-16 22:02:10 +0800675 VkSwapChainCreateInfoWSI swap_chain = {};
676 swap_chain.sType = VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI;
677 swap_chain.pNativeWindowSystemHandle = (void *) m_connection;
678 swap_chain.pNativeWindowHandle = (void *) (intptr_t) m_window;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600679 swap_chain.imageCount = 2;
Chia-I Wuf8693382015-04-16 22:02:10 +0800680 swap_chain.imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
681 swap_chain.imageExtent.width = m_width;
682 swap_chain.imageExtent.height = m_height;
683 swap_chain.imageArraySize = 1;
684 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT;
685 swap_chain.swapModeFlags = VK_SWAP_MODE_FLIP_BIT_WSI |
686 VK_SWAP_MODE_BLIT_BIT_WSI;
687
Jon Ashburn07daee72015-05-21 18:13:33 -0600688 err = m_fpCreateSwapChainWSI(m_device.obj(), &swap_chain, &m_swap_chain);
Chia-I Wuf8693382015-04-16 22:02:10 +0800689 assert(!err);
690
Tony-LunarG399dfca2015-05-19 14:08:26 -0600691 VkSwapChainImageInfoWSI infos[2];
Courtney Goeltzenleuchter763cc7a2015-06-24 15:02:51 -0600692 size_t size = sizeof(VkSwapChainImageInfoWSI) * m_images.size() * 2;
Jon Ashburn07daee72015-05-21 18:13:33 -0600693 std::vector<VkSwapChainImageInfoWSI> persistent_images;
694 persistent_images.resize(m_images.size());
695 err = m_fpGetSwapChainInfoWSI(m_swap_chain,
Chia-I Wuf8693382015-04-16 22:02:10 +0800696 VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600697 &size, &infos);
698 assert(!err && size == sizeof(VkSwapChainImageInfoWSI) * 2);
699 m_persistent_images.push_back(infos[0]);
700 m_persistent_images.push_back(infos[1]);
Tony Barbour96db8822015-02-25 12:28:39 -0700701}
702
Jon Ashburn07daee72015-05-21 18:13:33 -0600703void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -0700704{
Jon Ashburn07daee72015-05-21 18:13:33 -0600705 m_fpCreateSwapChainWSI = (PFN_vkCreateSwapChainWSI) vkGetInstanceProcAddr(inst, "vkCreateSwapChainWSI");
706 ASSERT_TRUE(m_fpCreateSwapChainWSI != NULL) << "vkGetInstanceProcAddr failed to find vkCreateSwapChainWSI";
707
708 m_fpDestroySwapChainWSI = (PFN_vkDestroySwapChainWSI) vkGetInstanceProcAddr(inst, "vkDestroySwapChainWSI");
709 ASSERT_TRUE(m_fpDestroySwapChainWSI != NULL) << "vkGetInstanceProcAddr failed to find vkDestroySwapChainWSI";
710
711 m_fpGetSwapChainInfoWSI = (PFN_vkGetSwapChainInfoWSI) vkGetInstanceProcAddr(inst, "vkGetSwapChainInfoWSI");
712 ASSERT_TRUE(m_fpGetSwapChainInfoWSI != NULL) << "vkGetInstanceProcAddr failed to find vkGetSwapChainInfoWSI";
713
714 m_fpQueuePresentWSI = (PFN_vkQueuePresentWSI) vkGetInstanceProcAddr(inst, "vkQueuePresentWSI");
715 ASSERT_TRUE(m_fpQueuePresentWSI != NULL) << "vkGetInstanceProcAddr failed to find vkQueuePresentWSI";
716
Tony Barbour96db8822015-02-25 12:28:39 -0700717 m_images = imagesIn;
718}
719
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600720#ifdef _WIN32
721void TestFrameworkVkPresent::CreateMyWindow()
722{
723 WNDCLASSEX win_class;
724 // const ::testing::TestInfo* const test_info =
725 // ::testing::UnitTest::GetInstance()->current_test_info();
726 m_connection = GetModuleHandle(NULL);
727
728 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
729 it != m_images.end(); it++) {
730 if (m_width < it->m_width)
731 m_width = it->m_width;
732 if (m_height < it->m_height)
733 m_height = it->m_height;
734 }
735 // Initialize the window class structure:
736 win_class.cbSize = sizeof(WNDCLASSEX);
737 win_class.style = CS_HREDRAW | CS_VREDRAW;
738 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
739 win_class.cbClsExtra = 0;
740 win_class.cbWndExtra = 0;
741 win_class.hInstance = m_connection; // hInstance
742 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
743 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
744 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
745 win_class.lpszMenuName = NULL;
746 win_class.lpszClassName = "Test";
747 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
748 // Register window class:
749 if (!RegisterClassEx(&win_class)) {
750 // It didn't work, so try to give a useful error:
751 printf("Unexpected error trying to start the application!\n");
752 fflush(stdout);
753 exit(1);
754 }
755 // Create window with the registered class:
756 m_window = CreateWindowEx(0,
757 "Test", // class name
758 "Test", // app name
759 WS_OVERLAPPEDWINDOW | // window style
760 WS_VISIBLE |
761 WS_SYSMENU,
762 100,100, // x/y coords
763 m_width, // width
764 m_height, // height
765 NULL, // handle to parent
766 NULL, // handle to menu
767 m_connection, // hInstance
768 NULL); // no extra parameters
769
770 if (!m_window) {
771 // It didn't work, so try to give a useful error:
772 DWORD error = GetLastError();
773 char message[120];
774 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
775 MessageBox(NULL, message, "Error", MB_OK);
776 exit(1);
777 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600778 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
779 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600780}
781#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600782void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -0700783{
Chia-I Wuf8693382015-04-16 22:02:10 +0800784 const xcb_setup_t *setup;
785 xcb_screen_iterator_t iter;
786 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -0700787 uint32_t value_mask, value_list[32];
788
Chia-I Wuf8693382015-04-16 22:02:10 +0800789 m_connection = xcb_connect(NULL, &scr);
790
791 setup = xcb_get_setup(m_connection);
792 iter = xcb_setup_roots_iterator(setup);
793 while (scr-- > 0)
794 xcb_screen_next(&iter);
795
796 m_screen = iter.data;
797
798 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
799 it != m_images.end(); it++) {
800 if (m_width < it->m_width)
801 m_width = it->m_width;
802 if (m_height < it->m_height)
803 m_height = it->m_height;
804 }
805
806 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700807
808 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +0800809 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -0700810 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
811 XCB_EVENT_MASK_EXPOSURE |
812 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
813
Chia-I Wuf8693382015-04-16 22:02:10 +0800814 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700815 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800816 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -0700817 0, 0, m_width, m_height, 0,
818 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800819 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -0700820 value_mask, value_list);
821
822 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +0800823 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -0700824 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +0800825 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -0700826
Chia-I Wuf8693382015-04-16 22:02:10 +0800827 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
828 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -0700829
Chia-I Wuf8693382015-04-16 22:02:10 +0800830 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -0700831 m_window, (*reply).atom, 4, 32, 1,
832 &(*m_atom_wm_delete_window).atom);
833 free(reply);
834
Chia-I Wuf8693382015-04-16 22:02:10 +0800835 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -0700836}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600837#endif
Tony Barbour96db8822015-02-25 12:28:39 -0700838
Tony Barbour6918cd52015-04-09 12:58:51 -0600839void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -0700840{
Jon Ashburn07daee72015-05-21 18:13:33 -0600841 m_fpDestroySwapChainWSI(m_swap_chain);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600842#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800843 xcb_destroy_window(m_connection, m_window);
844 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600845#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600846}
847
Tony Barbour6918cd52015-04-09 12:58:51 -0600848void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600849{
850 if (m_images.size() == 0) return;
851
Chia-I Wuf8693382015-04-16 22:02:10 +0800852 vk_testing::Environment env;
853 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -0700854 {
Chia-I Wuf8693382015-04-16 22:02:10 +0800855 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -0700856
Jon Ashburn07daee72015-05-21 18:13:33 -0600857 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600858 vkPresent.CreateMyWindow();
Chia-I Wuf8693382015-04-16 22:02:10 +0800859 vkPresent.CreateSwapChain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600860 vkPresent.Run();
861 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -0700862 }
Chia-I Wuf8693382015-04-16 22:02:10 +0800863 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600864}
865
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600866//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600867// These are the default resources for TBuiltInResources, used for both
868// - parsing this string for the case where the user didn't supply one
869// - dumping out a template for user construction of a config file
870//
871static const char* DefaultConfig =
872 "MaxLights 32\n"
873 "MaxClipPlanes 6\n"
874 "MaxTextureUnits 32\n"
875 "MaxTextureCoords 32\n"
876 "MaxVertexAttribs 64\n"
877 "MaxVertexUniformComponents 4096\n"
878 "MaxVaryingFloats 64\n"
879 "MaxVertexTextureImageUnits 32\n"
880 "MaxCombinedTextureImageUnits 80\n"
881 "MaxTextureImageUnits 32\n"
882 "MaxFragmentUniformComponents 4096\n"
883 "MaxDrawBuffers 32\n"
884 "MaxVertexUniformVectors 128\n"
885 "MaxVaryingVectors 8\n"
886 "MaxFragmentUniformVectors 16\n"
887 "MaxVertexOutputVectors 16\n"
888 "MaxFragmentInputVectors 15\n"
889 "MinProgramTexelOffset -8\n"
890 "MaxProgramTexelOffset 7\n"
891 "MaxClipDistances 8\n"
892 "MaxComputeWorkGroupCountX 65535\n"
893 "MaxComputeWorkGroupCountY 65535\n"
894 "MaxComputeWorkGroupCountZ 65535\n"
895 "MaxComputeWorkGroupSizeX 1024\n"
896 "MaxComputeWorkGroupSizeY 1024\n"
897 "MaxComputeWorkGroupSizeZ 64\n"
898 "MaxComputeUniformComponents 1024\n"
899 "MaxComputeTextureImageUnits 16\n"
900 "MaxComputeImageUniforms 8\n"
901 "MaxComputeAtomicCounters 8\n"
902 "MaxComputeAtomicCounterBuffers 1\n"
903 "MaxVaryingComponents 60\n"
904 "MaxVertexOutputComponents 64\n"
905 "MaxGeometryInputComponents 64\n"
906 "MaxGeometryOutputComponents 128\n"
907 "MaxFragmentInputComponents 128\n"
908 "MaxImageUnits 8\n"
909 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
910 "MaxCombinedShaderOutputResources 8\n"
911 "MaxImageSamples 0\n"
912 "MaxVertexImageUniforms 0\n"
913 "MaxTessControlImageUniforms 0\n"
914 "MaxTessEvaluationImageUniforms 0\n"
915 "MaxGeometryImageUniforms 0\n"
916 "MaxFragmentImageUniforms 8\n"
917 "MaxCombinedImageUniforms 8\n"
918 "MaxGeometryTextureImageUnits 16\n"
919 "MaxGeometryOutputVertices 256\n"
920 "MaxGeometryTotalOutputComponents 1024\n"
921 "MaxGeometryUniformComponents 1024\n"
922 "MaxGeometryVaryingComponents 64\n"
923 "MaxTessControlInputComponents 128\n"
924 "MaxTessControlOutputComponents 128\n"
925 "MaxTessControlTextureImageUnits 16\n"
926 "MaxTessControlUniformComponents 1024\n"
927 "MaxTessControlTotalOutputComponents 4096\n"
928 "MaxTessEvaluationInputComponents 128\n"
929 "MaxTessEvaluationOutputComponents 128\n"
930 "MaxTessEvaluationTextureImageUnits 16\n"
931 "MaxTessEvaluationUniformComponents 1024\n"
932 "MaxTessPatchComponents 120\n"
933 "MaxPatchVertices 32\n"
934 "MaxTessGenLevel 64\n"
935 "MaxViewports 16\n"
936 "MaxVertexAtomicCounters 0\n"
937 "MaxTessControlAtomicCounters 0\n"
938 "MaxTessEvaluationAtomicCounters 0\n"
939 "MaxGeometryAtomicCounters 0\n"
940 "MaxFragmentAtomicCounters 8\n"
941 "MaxCombinedAtomicCounters 8\n"
942 "MaxAtomicCounterBindings 1\n"
943 "MaxVertexAtomicCounterBuffers 0\n"
944 "MaxTessControlAtomicCounterBuffers 0\n"
945 "MaxTessEvaluationAtomicCounterBuffers 0\n"
946 "MaxGeometryAtomicCounterBuffers 0\n"
947 "MaxFragmentAtomicCounterBuffers 1\n"
948 "MaxCombinedAtomicCounterBuffers 1\n"
949 "MaxAtomicCounterBufferSize 16384\n"
950 "MaxTransformFeedbackBuffers 4\n"
951 "MaxTransformFeedbackInterleavedComponents 64\n"
952 "MaxCullDistances 8\n"
953 "MaxCombinedClipAndCullDistances 8\n"
954 "MaxSamples 4\n"
955
956 "nonInductiveForLoops 1\n"
957 "whileLoops 1\n"
958 "doWhileLoops 1\n"
959 "generalUniformIndexing 1\n"
960 "generalAttributeMatrixVectorIndexing 1\n"
961 "generalVaryingIndexing 1\n"
962 "generalSamplerIndexing 1\n"
963 "generalVariableIndexing 1\n"
964 "generalConstantMatrixVectorIndexing 1\n"
965 ;
966
967//
968// *.conf => this is a config file that can set limits/resources
969//
Tony Barbour6918cd52015-04-09 12:58:51 -0600970bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600971{
972 if (name.size() < 5)
973 return false;
974
975 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
976 ConfigFile = name;
977 return true;
978 }
979
980 return false;
981}
982
983//
984// Parse either a .conf file provided by the user or the default string above.
985//
Tony Barbour6918cd52015-04-09 12:58:51 -0600986void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600987{
988 char** configStrings = 0;
989 char* config = 0;
990 if (ConfigFile.size() > 0) {
991 configStrings = ReadFileData(ConfigFile.c_str());
992 if (configStrings)
993 config = *configStrings;
994 else {
995 printf("Error opening configuration file; will instead use the default configuration\n");
996 }
997 }
998
999 if (config == 0) {
1000 config = new char[strlen(DefaultConfig) + 1];
1001 strcpy(config, DefaultConfig);
1002 }
1003
1004 const char* delims = " \t\n\r";
1005 const char* token = strtok(config, delims);
1006 while (token) {
1007 const char* valueStr = strtok(0, delims);
1008 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1009 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1010 return;
1011 }
1012 int value = atoi(valueStr);
1013
1014 if (strcmp(token, "MaxLights") == 0)
1015 Resources.maxLights = value;
1016 else if (strcmp(token, "MaxClipPlanes") == 0)
1017 Resources.maxClipPlanes = value;
1018 else if (strcmp(token, "MaxTextureUnits") == 0)
1019 Resources.maxTextureUnits = value;
1020 else if (strcmp(token, "MaxTextureCoords") == 0)
1021 Resources.maxTextureCoords = value;
1022 else if (strcmp(token, "MaxVertexAttribs") == 0)
1023 Resources.maxVertexAttribs = value;
1024 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1025 Resources.maxVertexUniformComponents = value;
1026 else if (strcmp(token, "MaxVaryingFloats") == 0)
1027 Resources.maxVaryingFloats = value;
1028 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1029 Resources.maxVertexTextureImageUnits = value;
1030 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1031 Resources.maxCombinedTextureImageUnits = value;
1032 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1033 Resources.maxTextureImageUnits = value;
1034 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1035 Resources.maxFragmentUniformComponents = value;
1036 else if (strcmp(token, "MaxDrawBuffers") == 0)
1037 Resources.maxDrawBuffers = value;
1038 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1039 Resources.maxVertexUniformVectors = value;
1040 else if (strcmp(token, "MaxVaryingVectors") == 0)
1041 Resources.maxVaryingVectors = value;
1042 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1043 Resources.maxFragmentUniformVectors = value;
1044 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1045 Resources.maxVertexOutputVectors = value;
1046 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1047 Resources.maxFragmentInputVectors = value;
1048 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1049 Resources.minProgramTexelOffset = value;
1050 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1051 Resources.maxProgramTexelOffset = value;
1052 else if (strcmp(token, "MaxClipDistances") == 0)
1053 Resources.maxClipDistances = value;
1054 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1055 Resources.maxComputeWorkGroupCountX = value;
1056 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1057 Resources.maxComputeWorkGroupCountY = value;
1058 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1059 Resources.maxComputeWorkGroupCountZ = value;
1060 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1061 Resources.maxComputeWorkGroupSizeX = value;
1062 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1063 Resources.maxComputeWorkGroupSizeY = value;
1064 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1065 Resources.maxComputeWorkGroupSizeZ = value;
1066 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1067 Resources.maxComputeUniformComponents = value;
1068 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1069 Resources.maxComputeTextureImageUnits = value;
1070 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1071 Resources.maxComputeImageUniforms = value;
1072 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1073 Resources.maxComputeAtomicCounters = value;
1074 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1075 Resources.maxComputeAtomicCounterBuffers = value;
1076 else if (strcmp(token, "MaxVaryingComponents") == 0)
1077 Resources.maxVaryingComponents = value;
1078 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1079 Resources.maxVertexOutputComponents = value;
1080 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1081 Resources.maxGeometryInputComponents = value;
1082 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1083 Resources.maxGeometryOutputComponents = value;
1084 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1085 Resources.maxFragmentInputComponents = value;
1086 else if (strcmp(token, "MaxImageUnits") == 0)
1087 Resources.maxImageUnits = value;
1088 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1089 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1090 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1091 Resources.maxCombinedShaderOutputResources = value;
1092 else if (strcmp(token, "MaxImageSamples") == 0)
1093 Resources.maxImageSamples = value;
1094 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1095 Resources.maxVertexImageUniforms = value;
1096 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1097 Resources.maxTessControlImageUniforms = value;
1098 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1099 Resources.maxTessEvaluationImageUniforms = value;
1100 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1101 Resources.maxGeometryImageUniforms = value;
1102 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1103 Resources.maxFragmentImageUniforms = value;
1104 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1105 Resources.maxCombinedImageUniforms = value;
1106 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1107 Resources.maxGeometryTextureImageUnits = value;
1108 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1109 Resources.maxGeometryOutputVertices = value;
1110 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1111 Resources.maxGeometryTotalOutputComponents = value;
1112 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1113 Resources.maxGeometryUniformComponents = value;
1114 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1115 Resources.maxGeometryVaryingComponents = value;
1116 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1117 Resources.maxTessControlInputComponents = value;
1118 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1119 Resources.maxTessControlOutputComponents = value;
1120 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1121 Resources.maxTessControlTextureImageUnits = value;
1122 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1123 Resources.maxTessControlUniformComponents = value;
1124 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1125 Resources.maxTessControlTotalOutputComponents = value;
1126 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1127 Resources.maxTessEvaluationInputComponents = value;
1128 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1129 Resources.maxTessEvaluationOutputComponents = value;
1130 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1131 Resources.maxTessEvaluationTextureImageUnits = value;
1132 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1133 Resources.maxTessEvaluationUniformComponents = value;
1134 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1135 Resources.maxTessPatchComponents = value;
1136 else if (strcmp(token, "MaxPatchVertices") == 0)
1137 Resources.maxPatchVertices = value;
1138 else if (strcmp(token, "MaxTessGenLevel") == 0)
1139 Resources.maxTessGenLevel = value;
1140 else if (strcmp(token, "MaxViewports") == 0)
1141 Resources.maxViewports = value;
1142 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1143 Resources.maxVertexAtomicCounters = value;
1144 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1145 Resources.maxTessControlAtomicCounters = value;
1146 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1147 Resources.maxTessEvaluationAtomicCounters = value;
1148 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1149 Resources.maxGeometryAtomicCounters = value;
1150 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1151 Resources.maxFragmentAtomicCounters = value;
1152 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1153 Resources.maxCombinedAtomicCounters = value;
1154 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1155 Resources.maxAtomicCounterBindings = value;
1156 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1157 Resources.maxVertexAtomicCounterBuffers = value;
1158 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1159 Resources.maxTessControlAtomicCounterBuffers = value;
1160 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1161 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1162 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1163 Resources.maxGeometryAtomicCounterBuffers = value;
1164 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1165 Resources.maxFragmentAtomicCounterBuffers = value;
1166 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1167 Resources.maxCombinedAtomicCounterBuffers = value;
1168 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1169 Resources.maxAtomicCounterBufferSize = value;
1170 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1171 Resources.maxTransformFeedbackBuffers = value;
1172 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1173 Resources.maxTransformFeedbackInterleavedComponents = value;
1174 else if (strcmp(token, "MaxCullDistances") == 0)
1175 Resources.maxCullDistances = value;
1176 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1177 Resources.maxCombinedClipAndCullDistances = value;
1178 else if (strcmp(token, "MaxSamples") == 0)
1179 Resources.maxSamples = value;
1180
1181 else if (strcmp(token, "nonInductiveForLoops") == 0)
1182 Resources.limits.nonInductiveForLoops = (value != 0);
1183 else if (strcmp(token, "whileLoops") == 0)
1184 Resources.limits.whileLoops = (value != 0);
1185 else if (strcmp(token, "doWhileLoops") == 0)
1186 Resources.limits.doWhileLoops = (value != 0);
1187 else if (strcmp(token, "generalUniformIndexing") == 0)
1188 Resources.limits.generalUniformIndexing = (value != 0);
1189 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1190 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1191 else if (strcmp(token, "generalVaryingIndexing") == 0)
1192 Resources.limits.generalVaryingIndexing = (value != 0);
1193 else if (strcmp(token, "generalSamplerIndexing") == 0)
1194 Resources.limits.generalSamplerIndexing = (value != 0);
1195 else if (strcmp(token, "generalVariableIndexing") == 0)
1196 Resources.limits.generalVariableIndexing = (value != 0);
1197 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1198 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1199 else
1200 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1201
1202 token = strtok(0, delims);
1203 }
1204 if (configStrings)
1205 FreeFileData(configStrings);
1206}
1207
Tony Barbour6918cd52015-04-09 12:58:51 -06001208void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001209{
1210 if (m_compile_options & EOptionRelaxedErrors)
1211 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1212 if (m_compile_options & EOptionIntermediate)
1213 messages = (EShMessages)(messages | EShMsgAST);
1214 if (m_compile_options & EOptionSuppressWarnings)
1215 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1216}
1217
1218//
1219// Malloc a string of sufficient size and read a string into it.
1220//
Tony Barbour6918cd52015-04-09 12:58:51 -06001221char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001222{
1223 FILE *in;
1224 #if defined(_WIN32) && defined(__GNUC__)
1225 in = fopen(fileName, "r");
1226 int errorCode = in ? 0 : 1;
1227 #else
1228 int errorCode = fopen_s(&in, fileName, "r");
1229 #endif
1230
1231 char *fdata;
1232 int count = 0;
1233 const int maxSourceStrings = 5;
1234 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1235
1236 if (errorCode) {
1237 printf("Error: unable to open input file: %s\n", fileName);
1238 return 0;
1239 }
1240
1241 while (fgetc(in) != EOF)
1242 count++;
1243
1244 fseek(in, 0, SEEK_SET);
1245
1246 if (!(fdata = (char*)malloc(count+2))) {
1247 printf("Error allocating memory\n");
1248 return 0;
1249 }
1250 if (fread(fdata,1,count, in)!=count) {
1251 printf("Error reading input file: %s\n", fileName);
1252 return 0;
1253 }
1254 fdata[count] = '\0';
1255 fclose(in);
1256 if (count == 0) {
1257 return_data[0]=(char*)malloc(count+2);
1258 return_data[0][0]='\0';
1259 m_num_shader_strings = 0;
1260 return return_data;
1261 } else
1262 m_num_shader_strings = 1;
1263
1264 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1265 int ptr_len=0,i=0;
1266 while(count>0){
1267 return_data[i]=(char*)malloc(len+2);
1268 memcpy(return_data[i],fdata+ptr_len,len);
1269 return_data[i][len]='\0';
1270 count-=(len);
1271 ptr_len+=(len);
1272 if(count<len){
1273 if(count==0){
1274 m_num_shader_strings=(i+1);
1275 break;
1276 }
1277 len = count;
1278 }
1279 ++i;
1280 }
1281 return return_data;
1282}
1283
Tony Barbour6918cd52015-04-09 12:58:51 -06001284void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001285{
1286 for(int i=0;i<m_num_shader_strings;i++)
1287 free(data[i]);
1288}
1289
1290//
1291// Deduce the language from the filename. Files must end in one of the
1292// following extensions:
1293//
1294// .vert = vertex
1295// .tesc = tessellation control
1296// .tese = tessellation evaluation
1297// .geom = geometry
1298// .frag = fragment
1299// .comp = compute
1300//
Tony Barbour6918cd52015-04-09 12:58:51 -06001301EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001302{
1303 size_t ext = name.rfind('.');
1304 if (ext == std::string::npos) {
1305 return EShLangVertex;
1306 }
1307
1308 std::string suffix = name.substr(ext + 1, std::string::npos);
1309 if (suffix == "vert")
1310 return EShLangVertex;
1311 else if (suffix == "tesc")
1312 return EShLangTessControl;
1313 else if (suffix == "tese")
1314 return EShLangTessEvaluation;
1315 else if (suffix == "geom")
1316 return EShLangGeometry;
1317 else if (suffix == "frag")
1318 return EShLangFragment;
1319 else if (suffix == "comp")
1320 return EShLangCompute;
1321
1322 return EShLangVertex;
1323}
1324
1325//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001326// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001327//
Tony Barbourd1c35722015-04-16 15:59:00 -06001328EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001329{
1330 switch (shader_type) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001331 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001332 return EShLangVertex;
1333
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001334 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001335 return EShLangTessControl;
1336
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001337 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001338 return EShLangTessEvaluation;
1339
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001340 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001341 return EShLangGeometry;
1342
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001343 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001344 return EShLangFragment;
1345
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001346 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001347 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001348
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001349 default:
1350 return EShLangVertex;
1351 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001352}
1353
1354
1355//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001356// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001357// Return value of false means an error was encountered.
1358//
Tony Barbourd1c35722015-04-16 15:59:00 -06001359bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001360 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001361 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001362{
1363 glslang::TProgram& program = *new glslang::TProgram;
1364 const char *shaderStrings[1];
1365
1366 // TODO: Do we want to load a special config file depending on the
1367 // shader source? Optional name maybe?
1368 // SetConfigFile(fileName);
1369
1370 ProcessConfigFile();
1371
1372 EShMessages messages = EShMsgDefault;
1373 SetMessageOptions(messages);
1374
1375 EShLanguage stage = FindLanguage(shader_type);
1376 glslang::TShader* shader = new glslang::TShader(stage);
1377
1378 shaderStrings[0] = pshader;
1379 shader->setStrings(shaderStrings, 1);
1380
1381 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1382
Cody Northrop195d6622014-11-03 12:54:37 -07001383 if (! (m_compile_options & EOptionSuppressInfolog)) {
1384 puts(shader->getInfoLog());
1385 puts(shader->getInfoDebugLog());
1386 }
1387
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001388 return false; // something didn't work
1389 }
1390
1391 program.addShader(shader);
1392
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001393
1394 //
1395 // Program-level processing...
1396 //
1397
Cody Northrop195d6622014-11-03 12:54:37 -07001398 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001399
Cody Northrop195d6622014-11-03 12:54:37 -07001400 if (! (m_compile_options & EOptionSuppressInfolog)) {
1401 puts(shader->getInfoLog());
1402 puts(shader->getInfoDebugLog());
1403 }
1404
1405 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001406 }
1407
1408 if (m_compile_options & EOptionDumpReflection) {
1409 program.buildReflection();
1410 program.dumpReflection();
1411 }
1412
Cody Northrop5a95b472015-06-03 13:01:54 -06001413 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1414
1415 //
1416 // Test the different modes of SPIR-V modification
1417 //
1418 if (this->m_canonicalize_spv) {
1419 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1420 }
1421
1422 if (this->m_strip_spv) {
1423 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1424 }
1425
1426 if (this->m_do_everything_spv) {
1427 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1428 }
1429
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001430
1431 return true;
1432}
1433
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001434
1435
Tony Barbour6918cd52015-04-09 12:58:51 -06001436VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001437 m_width( 0 ),
1438 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001439 m_data( NULL ),
1440 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001441{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001442}
1443
Tony Barbour6918cd52015-04-09 12:58:51 -06001444VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001445{
1446
1447}
1448
Tony Barbour6918cd52015-04-09 12:58:51 -06001449VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001450{
1451 m_title = copyin.m_title;
1452 m_width = copyin.m_width;
1453 m_height = copyin.m_height;
1454 m_data_size = copyin.m_data_size;
1455 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1456}
1457
Tony Barbour6918cd52015-04-09 12:58:51 -06001458ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001459{
Tony Barbour6918cd52015-04-09 12:58:51 -06001460 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1461 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001462 return output;
1463}
1464
Tony Barbour6918cd52015-04-09 12:58:51 -06001465VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001466{
1467 m_title = rhs.m_title;
1468 m_width = rhs.m_width;
1469 m_height = rhs.m_height;
1470 m_data_size = rhs.m_data_size;
1471 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001472 return *this;
1473}
1474
Tony Barbour6918cd52015-04-09 12:58:51 -06001475int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001476{
1477 if( this->m_data != rhs.m_data) return 0;
1478 return 1;
1479}
1480
1481// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001482int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001483{
1484 if( this->m_data_size < rhs.m_data_size ) return 1;
1485 return 0;
1486}
1487