blob: 2b8fc6b713ef2f0b916550b3d42d7e21d3c444cf [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
Cody Northropa3673cf2015-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 Northrop5a95b472015-06-03 13:01:54 -0600174bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour6918cd52015-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 Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600179int m_display_image_idx = 0;
180
Cody Northrop50a2a4b2015-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 Barbour6918cd52015-04-09 12:58:51 -0600189void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600190{
191 int i, n;
192
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600193 for (i=1, n=1; i< *argc; i++) {
194 if (optionMatch("--show-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600195 m_show_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600196 else if (optionMatch("--save-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600197 m_save_images = true;
Cody Northrop50a2a4b2015-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 Barbour247bf372014-10-30 14:29:04 -0600205 m_compare_images = true;
Tony Barbour247bf372014-10-30 14:29:04 -0600206
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600207 else if (optionMatch("--help", argv[i]) ||
208 optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchter31144b72014-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 Barboura98d3932014-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 Goeltzenleuchter31144b72014-12-02 13:13:10 -0700221 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-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 Northrop50a2a4b2015-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 Barbour4ab45422014-12-10 17:00:20 -0700232 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700233 }
234
Cody Northrop50a2a4b2015-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 Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600240 argv[n] = argv[i];
241 n++;
242 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600243}
244
Tony Barbour6918cd52015-04-09 12:58:51 -0600245void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600246{
247 string filename;
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600248 VkResult err;
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600249 uint32_t x, y;
Tony Barbour6918cd52015-04-09 12:58:51 -0600250 VkImageObj displayImage(image->device());
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600251 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbour84d448c2015-04-02 14:02:33 -0600252
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600253 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, VK_IMAGE_TILING_LINEAR, reqs);
Tony Barbour84d448c2015-04-02 14:02:33 -0600254 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600255
256 filename.append(basename);
257 filename.append(".ppm");
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600258
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600259 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600260 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600261 };
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600262 VkSubresourceLayout sr_layout;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600263
Tony Barbour59a47322015-06-24 16:06:58 -0600264 err = vkGetImageSubresourceLayout(image->device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600265 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600266
Tony Barbour84d448c2015-04-02 14:02:33 -0600267 char *ptr;
268 ptr = (char *) displayImage.map();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600269 ptr += sr_layout.offset;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600270 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600271 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
272
273 file << "P6\n";
Tony Barbour84d448c2015-04-02 14:02:33 -0600274 file << displayImage.width() << "\n";
275 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600276 file << 255 << "\n";
277
Tony Barbour84d448c2015-04-02 14:02:33 -0600278 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700279 const int *row = (const int *) ptr;
280 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600281
Tony Barbourd1c35722015-04-16 15:59:00 -0600282 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700283 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600284 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-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 Barbourd1c35722015-04-16 15:59:00 -0600290 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700291 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600292 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-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 Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600300 }
301
302 ptr += sr_layout.rowPitch;
303 }
304
305 file.close();
Tony Barbour84d448c2015-04-02 14:02:33 -0600306 displayImage.unmap();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600307}
308
Tony Barbour6918cd52015-04-09 12:58:51 -0600309void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour247bf372014-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 Barbour3d69c9e2015-05-20 16:53:31 -0600316 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600317 double differenz;
318
Tony Barbour4ab45422014-12-10 17:00:20 -0700319 if (getenv("RENDERTEST_GOLDEN_DIR"))
320 {
321 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
322 }
323
Tony Barbour247bf372014-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 Barbour7ea6aa22015-05-22 09:44:58 -0600328 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour247bf372014-10-30 14:29:04 -0600329
330
331 MagickWandGenesis();
332 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700333 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600334 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600335 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour247bf372014-10-30 14:29:04 -0600336
Tony Barbour247bf372014-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 Goeltzenleuchterfcda72d2014-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 Barbour247bf372014-10-30 14:29:04 -0600360}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600361
Tony Barbour6918cd52015-04-09 12:58:51 -0600362void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600363{
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600364 VkResult err;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600365 VkSubresourceLayout sr_layout;
366 char *ptr;
367 VkTestImageRecord record;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600368 VkImageObj displayImage(image->device());
369 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
370
Cody Northropc9a69912015-06-18 17:05:15 -0600371 displayImage.init(image->extent().width, image->extent().height, image->format(), VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT, VK_IMAGE_TILING_LINEAR, reqs);
372
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600373 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600374
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600375 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600376 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600377 };
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600378
Tony Barbour59a47322015-06-24 16:06:58 -0600379 err = vkGetImageSubresourceLayout(displayImage.device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600380 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600381
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600382 err = displayImage.MapMemory( (void **) &ptr );
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600383 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600384
385 ptr += sr_layout.offset;
386
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600387 record.m_title.append(comment);
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600388 record.m_width = displayImage.width();
389 record.m_height = displayImage.height();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600390 // TODO: Need to make this more robust to handle different image formats
Tony-LunarG399dfca2015-05-19 14:08:26 -0600391 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600392 record.m_data = malloc(record.m_data_size);
393 memcpy(record.m_data, ptr, record.m_data_size);
394 m_images.push_back(record);
395 m_display_image = --m_images.end();
396
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600397 err = displayImage.UnmapMemory();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600398 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600399}
400
Tony Barbour6918cd52015-04-09 12:58:51 -0600401void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600402{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600403 for (int32_t i = 0; i < images.size(); i++) {
404 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600405 }
406}
407
Tony Barbour6918cd52015-04-09 12:58:51 -0600408void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600409{
410 const ::testing::TestInfo* const test_info =
411 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600412 ostringstream filestream;
413 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600414
Tony Barbour247bf372014-10-30 14:29:04 -0600415 m_width = 40;
416
417 if (strcmp(test_info->name(), m_testName.c_str())) {
418 filestream << test_info->name();
419 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700420 m_frameNum = 2;
421 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600422 }
423 else {
424 filestream << test_info->name() << "-" << m_frameNum;
425 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700426 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600427 }
428
Tony Barbour247bf372014-10-30 14:29:04 -0600429 // ToDo - scrub string for bad characters
430
431 if (m_save_images || m_compare_images) {
432 WritePPM(filename.c_str(), image);
433 if (m_compare_images) {
434 Compare(filename.c_str(), image);
435 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600436 }
437
438 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600439 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600440 }
441}
442
Chia-I Wuf8693382015-04-16 22:02:10 +0800443TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
444 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700445 m_queue(*m_device.graphics_queues()[0]),
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600446 m_cmdbuf(m_device, vk_testing::CmdBuffer::create_info(m_device.graphics_queue_node_index_))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600447{
Tony Barbour96db8822015-02-25 12:28:39 -0700448 m_quit = false;
449 m_pause = false;
450 m_width = 0;
451 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600452}
453
Tony Barbour6918cd52015-04-09 12:58:51 -0600454void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600455{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600456 VkResult U_ASSERT_ONLY err;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600457 vk_testing::Buffer buf;
458 void *dest_ptr;
459
460 if (m_persistent_images.size() != 2) {
461 return;
462 }
463
464 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Cody Northrop21ed9cd2015-06-17 08:29:35 -0600465 flags |= VK_BUFFER_USAGE_TRANSFER_SOURCE_BIT;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600466 buf.init(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
467 dest_ptr = buf.map();
468 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
469 buf.unmap();
470
471 m_cmdbuf.begin();
472
473 VkBufferImageCopy region = {};
474 region.imageExtent.height = m_display_image->m_height;
475 region.imageExtent.width = m_display_image->m_width;
476 region.imageExtent.depth = 1;
477
478 vkCmdCopyBufferToImage(m_cmdbuf.obj(),
479 buf.obj(),
480 m_persistent_images[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
481 1, &region);
482 m_cmdbuf.end();
483
484 VkCmdBuffer cmdBufs[1];
485 cmdBufs[0] = m_cmdbuf.obj();
486
487 vkQueueSubmit(m_queue.obj(), 1, cmdBufs, NULL);
488 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700489
Chia-I Wuf8693382015-04-16 22:02:10 +0800490 VkPresentInfoWSI present = {};
491 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_WSI;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600492 present.image = m_persistent_images[m_current_buffer].image;
Chia-I Wuf8693382015-04-16 22:02:10 +0800493 present.flipInterval = 1;
Tony Barbour96db8822015-02-25 12:28:39 -0700494
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600495#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800496 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700497 XCB_PROP_MODE_REPLACE,
498 m_window,
499 XCB_ATOM_WM_NAME,
500 XCB_ATOM_STRING,
501 8,
502 m_display_image->m_title.size(),
503 m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600504#endif
Jon Ashburn07daee72015-05-21 18:13:33 -0600505
506 err = m_fpQueuePresentWSI(m_queue.obj(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700507 assert(!err);
508
509 m_queue.wait();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600510 m_current_buffer = (m_current_buffer + 1) % 2;
Tony Barbour96db8822015-02-25 12:28:39 -0700511
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600512}
513
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600514#ifdef _WIN32
Tony-LunarG399dfca2015-05-19 14:08:26 -0600515# define PREVIOUSLY_DOWN 1<<29
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600516// MS-Windows event handling function:
517LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
518 UINT uMsg,
519 WPARAM wParam,
520 LPARAM lParam)
521{
522
523 switch(uMsg)
524 {
525 case WM_CLOSE:
526 PostQuitMessage(0);
527 break;
528
529 case WM_PAINT:
530 {
531 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
532 if (me) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600533 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600534 me->Display();
535 }
536 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600537 break;
538
539 case WM_KEYDOWN:
540 {
541 if (lParam & (PREVIOUSLY_DOWN)){
542 break;
543 }
544 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
545 // the window, we put the this pointer into the window's user data so we could get it back now
546 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
547 switch (wParam)
548 {
549 case VK_ESCAPE: me->m_quit = true;
550 break;
551
552 case VK_LEFT: // left arrow key
553 if (me->m_display_image == me->m_images.begin()) {
554 me->m_display_image = --me->m_images.end();
555 }
556 else {
557 --me->m_display_image;
558 }
559 break;
560
561 case VK_RIGHT: // right arrow key
562 ++me->m_display_image;
563 if (me->m_display_image == me->m_images.end()) {
564 me->m_display_image = me->m_images.begin();
565 }
566 break;
567
568 default:
569 break;
570 }
571 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
572 me->Display();
573 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600574 }
575 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
576}
577
578void TestFrameworkVkPresent::Run()
579{
580 MSG msg; // message
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600581
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600582 /* main message loop*/
Tony-LunarG399dfca2015-05-19 14:08:26 -0600583 while(! m_quit) {
584 GetMessage(&msg, m_window, 0, 0);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600585 if (msg.message == WM_QUIT) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600586 m_quit = true; //if found, quit app
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600587 } else {
588 /* Translate and dispatch to event queue*/
589 TranslateMessage(&msg);
590 DispatchMessage(&msg);
591 }
592 }
593}
594
595#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600596void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600597{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600598 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700599 switch (event_code) {
600 case XCB_EXPOSE:
601 Display(); // TODO: handle resize
602 break;
603 case XCB_CLIENT_MESSAGE:
604 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
605 (m_atom_wm_delete_window)->atom) {
606 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600607 }
608 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700609 case XCB_KEY_RELEASE:
610 {
611 const xcb_key_release_event_t *key =
612 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600613
Tony Barbour96db8822015-02-25 12:28:39 -0700614 switch (key->detail) {
615 case 0x9: // Escape
616 m_quit = true;
617 break;
618 case 0x71: // left arrow key
619 if (m_display_image == m_images.begin()) {
620 m_display_image = --m_images.end();
621 } else {
622 --m_display_image;
623 }
624 break;
625 case 0x72: // right arrow key
626 ++m_display_image;
627 if (m_display_image == m_images.end()) {
628 m_display_image = m_images.begin();
629 }
630 break;
631 case 0x41:
632 m_pause = !m_pause;
633 break;
634 }
635 Display();
636 }
637 break;
638 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600639 break;
640 }
Tony Barbour96db8822015-02-25 12:28:39 -0700641}
642
Tony Barbour6918cd52015-04-09 12:58:51 -0600643void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700644{
Chia-I Wuf8693382015-04-16 22:02:10 +0800645 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700646
647 while (! m_quit) {
648 xcb_generic_event_t *event;
649
650 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800651 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700652 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800653 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700654 }
655 if (event) {
656 HandleEvent(event);
657 free(event);
658 }
659 }
660}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600661#endif // _WIN32
Tony Barbour96db8822015-02-25 12:28:39 -0700662
Chia-I Wuf8693382015-04-16 22:02:10 +0800663void TestFrameworkVkPresent::CreateSwapChain()
Tony Barbour96db8822015-02-25 12:28:39 -0700664{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600665 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700666
Tony-LunarG399dfca2015-05-19 14:08:26 -0600667 m_display_image = m_images.begin();
668 m_current_buffer = 0;
669
Chia-I Wuf8693382015-04-16 22:02:10 +0800670 VkSwapChainCreateInfoWSI swap_chain = {};
671 swap_chain.sType = VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI;
672 swap_chain.pNativeWindowSystemHandle = (void *) m_connection;
673 swap_chain.pNativeWindowHandle = (void *) (intptr_t) m_window;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600674 swap_chain.imageCount = 2;
Chia-I Wuf8693382015-04-16 22:02:10 +0800675 swap_chain.imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
676 swap_chain.imageExtent.width = m_width;
677 swap_chain.imageExtent.height = m_height;
678 swap_chain.imageArraySize = 1;
679 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT;
680 swap_chain.swapModeFlags = VK_SWAP_MODE_FLIP_BIT_WSI |
681 VK_SWAP_MODE_BLIT_BIT_WSI;
682
Jon Ashburn07daee72015-05-21 18:13:33 -0600683 err = m_fpCreateSwapChainWSI(m_device.obj(), &swap_chain, &m_swap_chain);
Chia-I Wuf8693382015-04-16 22:02:10 +0800684 assert(!err);
685
Tony-LunarG399dfca2015-05-19 14:08:26 -0600686 VkSwapChainImageInfoWSI infos[2];
Courtney Goeltzenleuchter763cc7a2015-06-24 15:02:51 -0600687 size_t size = sizeof(VkSwapChainImageInfoWSI) * m_images.size() * 2;
Jon Ashburn07daee72015-05-21 18:13:33 -0600688 std::vector<VkSwapChainImageInfoWSI> persistent_images;
689 persistent_images.resize(m_images.size());
690 err = m_fpGetSwapChainInfoWSI(m_swap_chain,
Chia-I Wuf8693382015-04-16 22:02:10 +0800691 VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600692 &size, &infos);
693 assert(!err && size == sizeof(VkSwapChainImageInfoWSI) * 2);
694 m_persistent_images.push_back(infos[0]);
695 m_persistent_images.push_back(infos[1]);
Tony Barbour96db8822015-02-25 12:28:39 -0700696}
697
Jon Ashburn07daee72015-05-21 18:13:33 -0600698void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -0700699{
Jon Ashburn07daee72015-05-21 18:13:33 -0600700 m_fpCreateSwapChainWSI = (PFN_vkCreateSwapChainWSI) vkGetInstanceProcAddr(inst, "vkCreateSwapChainWSI");
701 ASSERT_TRUE(m_fpCreateSwapChainWSI != NULL) << "vkGetInstanceProcAddr failed to find vkCreateSwapChainWSI";
702
703 m_fpDestroySwapChainWSI = (PFN_vkDestroySwapChainWSI) vkGetInstanceProcAddr(inst, "vkDestroySwapChainWSI");
704 ASSERT_TRUE(m_fpDestroySwapChainWSI != NULL) << "vkGetInstanceProcAddr failed to find vkDestroySwapChainWSI";
705
706 m_fpGetSwapChainInfoWSI = (PFN_vkGetSwapChainInfoWSI) vkGetInstanceProcAddr(inst, "vkGetSwapChainInfoWSI");
707 ASSERT_TRUE(m_fpGetSwapChainInfoWSI != NULL) << "vkGetInstanceProcAddr failed to find vkGetSwapChainInfoWSI";
708
709 m_fpQueuePresentWSI = (PFN_vkQueuePresentWSI) vkGetInstanceProcAddr(inst, "vkQueuePresentWSI");
710 ASSERT_TRUE(m_fpQueuePresentWSI != NULL) << "vkGetInstanceProcAddr failed to find vkQueuePresentWSI";
711
Tony Barbour96db8822015-02-25 12:28:39 -0700712 m_images = imagesIn;
713}
714
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600715#ifdef _WIN32
716void TestFrameworkVkPresent::CreateMyWindow()
717{
718 WNDCLASSEX win_class;
719 // const ::testing::TestInfo* const test_info =
720 // ::testing::UnitTest::GetInstance()->current_test_info();
721 m_connection = GetModuleHandle(NULL);
722
723 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
724 it != m_images.end(); it++) {
725 if (m_width < it->m_width)
726 m_width = it->m_width;
727 if (m_height < it->m_height)
728 m_height = it->m_height;
729 }
730 // Initialize the window class structure:
731 win_class.cbSize = sizeof(WNDCLASSEX);
732 win_class.style = CS_HREDRAW | CS_VREDRAW;
733 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
734 win_class.cbClsExtra = 0;
735 win_class.cbWndExtra = 0;
736 win_class.hInstance = m_connection; // hInstance
737 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
738 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
739 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
740 win_class.lpszMenuName = NULL;
741 win_class.lpszClassName = "Test";
742 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
743 // Register window class:
744 if (!RegisterClassEx(&win_class)) {
745 // It didn't work, so try to give a useful error:
746 printf("Unexpected error trying to start the application!\n");
747 fflush(stdout);
748 exit(1);
749 }
750 // Create window with the registered class:
751 m_window = CreateWindowEx(0,
752 "Test", // class name
753 "Test", // app name
754 WS_OVERLAPPEDWINDOW | // window style
755 WS_VISIBLE |
756 WS_SYSMENU,
757 100,100, // x/y coords
758 m_width, // width
759 m_height, // height
760 NULL, // handle to parent
761 NULL, // handle to menu
762 m_connection, // hInstance
763 NULL); // no extra parameters
764
765 if (!m_window) {
766 // It didn't work, so try to give a useful error:
767 DWORD error = GetLastError();
768 char message[120];
769 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
770 MessageBox(NULL, message, "Error", MB_OK);
771 exit(1);
772 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600773 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
774 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600775}
776#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600777void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -0700778{
Chia-I Wuf8693382015-04-16 22:02:10 +0800779 const xcb_setup_t *setup;
780 xcb_screen_iterator_t iter;
781 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -0700782 uint32_t value_mask, value_list[32];
783
Chia-I Wuf8693382015-04-16 22:02:10 +0800784 m_connection = xcb_connect(NULL, &scr);
785
786 setup = xcb_get_setup(m_connection);
787 iter = xcb_setup_roots_iterator(setup);
788 while (scr-- > 0)
789 xcb_screen_next(&iter);
790
791 m_screen = iter.data;
792
793 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
794 it != m_images.end(); it++) {
795 if (m_width < it->m_width)
796 m_width = it->m_width;
797 if (m_height < it->m_height)
798 m_height = it->m_height;
799 }
800
801 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700802
803 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +0800804 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -0700805 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
806 XCB_EVENT_MASK_EXPOSURE |
807 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
808
Chia-I Wuf8693382015-04-16 22:02:10 +0800809 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700810 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800811 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -0700812 0, 0, m_width, m_height, 0,
813 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800814 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -0700815 value_mask, value_list);
816
817 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +0800818 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -0700819 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +0800820 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -0700821
Chia-I Wuf8693382015-04-16 22:02:10 +0800822 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
823 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -0700824
Chia-I Wuf8693382015-04-16 22:02:10 +0800825 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -0700826 m_window, (*reply).atom, 4, 32, 1,
827 &(*m_atom_wm_delete_window).atom);
828 free(reply);
829
Chia-I Wuf8693382015-04-16 22:02:10 +0800830 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -0700831}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600832#endif
Tony Barbour96db8822015-02-25 12:28:39 -0700833
Tony Barbour6918cd52015-04-09 12:58:51 -0600834void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -0700835{
Jon Ashburn07daee72015-05-21 18:13:33 -0600836 m_fpDestroySwapChainWSI(m_swap_chain);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600837#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800838 xcb_destroy_window(m_connection, m_window);
839 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600840#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600841}
842
Tony Barbour6918cd52015-04-09 12:58:51 -0600843void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600844{
845 if (m_images.size() == 0) return;
846
Chia-I Wuf8693382015-04-16 22:02:10 +0800847 vk_testing::Environment env;
848 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -0700849 {
Chia-I Wuf8693382015-04-16 22:02:10 +0800850 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -0700851
Jon Ashburn07daee72015-05-21 18:13:33 -0600852 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600853 vkPresent.CreateMyWindow();
Chia-I Wuf8693382015-04-16 22:02:10 +0800854 vkPresent.CreateSwapChain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600855 vkPresent.Run();
856 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -0700857 }
Chia-I Wuf8693382015-04-16 22:02:10 +0800858 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600859}
860
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600861//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600862// These are the default resources for TBuiltInResources, used for both
863// - parsing this string for the case where the user didn't supply one
864// - dumping out a template for user construction of a config file
865//
866static const char* DefaultConfig =
867 "MaxLights 32\n"
868 "MaxClipPlanes 6\n"
869 "MaxTextureUnits 32\n"
870 "MaxTextureCoords 32\n"
871 "MaxVertexAttribs 64\n"
872 "MaxVertexUniformComponents 4096\n"
873 "MaxVaryingFloats 64\n"
874 "MaxVertexTextureImageUnits 32\n"
875 "MaxCombinedTextureImageUnits 80\n"
876 "MaxTextureImageUnits 32\n"
877 "MaxFragmentUniformComponents 4096\n"
878 "MaxDrawBuffers 32\n"
879 "MaxVertexUniformVectors 128\n"
880 "MaxVaryingVectors 8\n"
881 "MaxFragmentUniformVectors 16\n"
882 "MaxVertexOutputVectors 16\n"
883 "MaxFragmentInputVectors 15\n"
884 "MinProgramTexelOffset -8\n"
885 "MaxProgramTexelOffset 7\n"
886 "MaxClipDistances 8\n"
887 "MaxComputeWorkGroupCountX 65535\n"
888 "MaxComputeWorkGroupCountY 65535\n"
889 "MaxComputeWorkGroupCountZ 65535\n"
890 "MaxComputeWorkGroupSizeX 1024\n"
891 "MaxComputeWorkGroupSizeY 1024\n"
892 "MaxComputeWorkGroupSizeZ 64\n"
893 "MaxComputeUniformComponents 1024\n"
894 "MaxComputeTextureImageUnits 16\n"
895 "MaxComputeImageUniforms 8\n"
896 "MaxComputeAtomicCounters 8\n"
897 "MaxComputeAtomicCounterBuffers 1\n"
898 "MaxVaryingComponents 60\n"
899 "MaxVertexOutputComponents 64\n"
900 "MaxGeometryInputComponents 64\n"
901 "MaxGeometryOutputComponents 128\n"
902 "MaxFragmentInputComponents 128\n"
903 "MaxImageUnits 8\n"
904 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
905 "MaxCombinedShaderOutputResources 8\n"
906 "MaxImageSamples 0\n"
907 "MaxVertexImageUniforms 0\n"
908 "MaxTessControlImageUniforms 0\n"
909 "MaxTessEvaluationImageUniforms 0\n"
910 "MaxGeometryImageUniforms 0\n"
911 "MaxFragmentImageUniforms 8\n"
912 "MaxCombinedImageUniforms 8\n"
913 "MaxGeometryTextureImageUnits 16\n"
914 "MaxGeometryOutputVertices 256\n"
915 "MaxGeometryTotalOutputComponents 1024\n"
916 "MaxGeometryUniformComponents 1024\n"
917 "MaxGeometryVaryingComponents 64\n"
918 "MaxTessControlInputComponents 128\n"
919 "MaxTessControlOutputComponents 128\n"
920 "MaxTessControlTextureImageUnits 16\n"
921 "MaxTessControlUniformComponents 1024\n"
922 "MaxTessControlTotalOutputComponents 4096\n"
923 "MaxTessEvaluationInputComponents 128\n"
924 "MaxTessEvaluationOutputComponents 128\n"
925 "MaxTessEvaluationTextureImageUnits 16\n"
926 "MaxTessEvaluationUniformComponents 1024\n"
927 "MaxTessPatchComponents 120\n"
928 "MaxPatchVertices 32\n"
929 "MaxTessGenLevel 64\n"
930 "MaxViewports 16\n"
931 "MaxVertexAtomicCounters 0\n"
932 "MaxTessControlAtomicCounters 0\n"
933 "MaxTessEvaluationAtomicCounters 0\n"
934 "MaxGeometryAtomicCounters 0\n"
935 "MaxFragmentAtomicCounters 8\n"
936 "MaxCombinedAtomicCounters 8\n"
937 "MaxAtomicCounterBindings 1\n"
938 "MaxVertexAtomicCounterBuffers 0\n"
939 "MaxTessControlAtomicCounterBuffers 0\n"
940 "MaxTessEvaluationAtomicCounterBuffers 0\n"
941 "MaxGeometryAtomicCounterBuffers 0\n"
942 "MaxFragmentAtomicCounterBuffers 1\n"
943 "MaxCombinedAtomicCounterBuffers 1\n"
944 "MaxAtomicCounterBufferSize 16384\n"
945 "MaxTransformFeedbackBuffers 4\n"
946 "MaxTransformFeedbackInterleavedComponents 64\n"
947 "MaxCullDistances 8\n"
948 "MaxCombinedClipAndCullDistances 8\n"
949 "MaxSamples 4\n"
950
951 "nonInductiveForLoops 1\n"
952 "whileLoops 1\n"
953 "doWhileLoops 1\n"
954 "generalUniformIndexing 1\n"
955 "generalAttributeMatrixVectorIndexing 1\n"
956 "generalVaryingIndexing 1\n"
957 "generalSamplerIndexing 1\n"
958 "generalVariableIndexing 1\n"
959 "generalConstantMatrixVectorIndexing 1\n"
960 ;
961
962//
963// *.conf => this is a config file that can set limits/resources
964//
Tony Barbour6918cd52015-04-09 12:58:51 -0600965bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600966{
967 if (name.size() < 5)
968 return false;
969
970 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
971 ConfigFile = name;
972 return true;
973 }
974
975 return false;
976}
977
978//
979// Parse either a .conf file provided by the user or the default string above.
980//
Tony Barbour6918cd52015-04-09 12:58:51 -0600981void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600982{
983 char** configStrings = 0;
984 char* config = 0;
985 if (ConfigFile.size() > 0) {
986 configStrings = ReadFileData(ConfigFile.c_str());
987 if (configStrings)
988 config = *configStrings;
989 else {
990 printf("Error opening configuration file; will instead use the default configuration\n");
991 }
992 }
993
994 if (config == 0) {
995 config = new char[strlen(DefaultConfig) + 1];
996 strcpy(config, DefaultConfig);
997 }
998
999 const char* delims = " \t\n\r";
1000 const char* token = strtok(config, delims);
1001 while (token) {
1002 const char* valueStr = strtok(0, delims);
1003 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1004 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1005 return;
1006 }
1007 int value = atoi(valueStr);
1008
1009 if (strcmp(token, "MaxLights") == 0)
1010 Resources.maxLights = value;
1011 else if (strcmp(token, "MaxClipPlanes") == 0)
1012 Resources.maxClipPlanes = value;
1013 else if (strcmp(token, "MaxTextureUnits") == 0)
1014 Resources.maxTextureUnits = value;
1015 else if (strcmp(token, "MaxTextureCoords") == 0)
1016 Resources.maxTextureCoords = value;
1017 else if (strcmp(token, "MaxVertexAttribs") == 0)
1018 Resources.maxVertexAttribs = value;
1019 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1020 Resources.maxVertexUniformComponents = value;
1021 else if (strcmp(token, "MaxVaryingFloats") == 0)
1022 Resources.maxVaryingFloats = value;
1023 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1024 Resources.maxVertexTextureImageUnits = value;
1025 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1026 Resources.maxCombinedTextureImageUnits = value;
1027 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1028 Resources.maxTextureImageUnits = value;
1029 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1030 Resources.maxFragmentUniformComponents = value;
1031 else if (strcmp(token, "MaxDrawBuffers") == 0)
1032 Resources.maxDrawBuffers = value;
1033 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1034 Resources.maxVertexUniformVectors = value;
1035 else if (strcmp(token, "MaxVaryingVectors") == 0)
1036 Resources.maxVaryingVectors = value;
1037 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1038 Resources.maxFragmentUniformVectors = value;
1039 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1040 Resources.maxVertexOutputVectors = value;
1041 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1042 Resources.maxFragmentInputVectors = value;
1043 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1044 Resources.minProgramTexelOffset = value;
1045 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1046 Resources.maxProgramTexelOffset = value;
1047 else if (strcmp(token, "MaxClipDistances") == 0)
1048 Resources.maxClipDistances = value;
1049 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1050 Resources.maxComputeWorkGroupCountX = value;
1051 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1052 Resources.maxComputeWorkGroupCountY = value;
1053 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1054 Resources.maxComputeWorkGroupCountZ = value;
1055 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1056 Resources.maxComputeWorkGroupSizeX = value;
1057 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1058 Resources.maxComputeWorkGroupSizeY = value;
1059 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1060 Resources.maxComputeWorkGroupSizeZ = value;
1061 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1062 Resources.maxComputeUniformComponents = value;
1063 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1064 Resources.maxComputeTextureImageUnits = value;
1065 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1066 Resources.maxComputeImageUniforms = value;
1067 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1068 Resources.maxComputeAtomicCounters = value;
1069 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1070 Resources.maxComputeAtomicCounterBuffers = value;
1071 else if (strcmp(token, "MaxVaryingComponents") == 0)
1072 Resources.maxVaryingComponents = value;
1073 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1074 Resources.maxVertexOutputComponents = value;
1075 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1076 Resources.maxGeometryInputComponents = value;
1077 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1078 Resources.maxGeometryOutputComponents = value;
1079 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1080 Resources.maxFragmentInputComponents = value;
1081 else if (strcmp(token, "MaxImageUnits") == 0)
1082 Resources.maxImageUnits = value;
1083 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1084 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1085 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1086 Resources.maxCombinedShaderOutputResources = value;
1087 else if (strcmp(token, "MaxImageSamples") == 0)
1088 Resources.maxImageSamples = value;
1089 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1090 Resources.maxVertexImageUniforms = value;
1091 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1092 Resources.maxTessControlImageUniforms = value;
1093 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1094 Resources.maxTessEvaluationImageUniforms = value;
1095 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1096 Resources.maxGeometryImageUniforms = value;
1097 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1098 Resources.maxFragmentImageUniforms = value;
1099 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1100 Resources.maxCombinedImageUniforms = value;
1101 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1102 Resources.maxGeometryTextureImageUnits = value;
1103 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1104 Resources.maxGeometryOutputVertices = value;
1105 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1106 Resources.maxGeometryTotalOutputComponents = value;
1107 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1108 Resources.maxGeometryUniformComponents = value;
1109 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1110 Resources.maxGeometryVaryingComponents = value;
1111 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1112 Resources.maxTessControlInputComponents = value;
1113 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1114 Resources.maxTessControlOutputComponents = value;
1115 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1116 Resources.maxTessControlTextureImageUnits = value;
1117 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1118 Resources.maxTessControlUniformComponents = value;
1119 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1120 Resources.maxTessControlTotalOutputComponents = value;
1121 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1122 Resources.maxTessEvaluationInputComponents = value;
1123 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1124 Resources.maxTessEvaluationOutputComponents = value;
1125 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1126 Resources.maxTessEvaluationTextureImageUnits = value;
1127 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1128 Resources.maxTessEvaluationUniformComponents = value;
1129 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1130 Resources.maxTessPatchComponents = value;
1131 else if (strcmp(token, "MaxPatchVertices") == 0)
1132 Resources.maxPatchVertices = value;
1133 else if (strcmp(token, "MaxTessGenLevel") == 0)
1134 Resources.maxTessGenLevel = value;
1135 else if (strcmp(token, "MaxViewports") == 0)
1136 Resources.maxViewports = value;
1137 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1138 Resources.maxVertexAtomicCounters = value;
1139 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1140 Resources.maxTessControlAtomicCounters = value;
1141 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1142 Resources.maxTessEvaluationAtomicCounters = value;
1143 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1144 Resources.maxGeometryAtomicCounters = value;
1145 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1146 Resources.maxFragmentAtomicCounters = value;
1147 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1148 Resources.maxCombinedAtomicCounters = value;
1149 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1150 Resources.maxAtomicCounterBindings = value;
1151 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1152 Resources.maxVertexAtomicCounterBuffers = value;
1153 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1154 Resources.maxTessControlAtomicCounterBuffers = value;
1155 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1156 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1157 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1158 Resources.maxGeometryAtomicCounterBuffers = value;
1159 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1160 Resources.maxFragmentAtomicCounterBuffers = value;
1161 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1162 Resources.maxCombinedAtomicCounterBuffers = value;
1163 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1164 Resources.maxAtomicCounterBufferSize = value;
1165 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1166 Resources.maxTransformFeedbackBuffers = value;
1167 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1168 Resources.maxTransformFeedbackInterleavedComponents = value;
1169 else if (strcmp(token, "MaxCullDistances") == 0)
1170 Resources.maxCullDistances = value;
1171 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1172 Resources.maxCombinedClipAndCullDistances = value;
1173 else if (strcmp(token, "MaxSamples") == 0)
1174 Resources.maxSamples = value;
1175
1176 else if (strcmp(token, "nonInductiveForLoops") == 0)
1177 Resources.limits.nonInductiveForLoops = (value != 0);
1178 else if (strcmp(token, "whileLoops") == 0)
1179 Resources.limits.whileLoops = (value != 0);
1180 else if (strcmp(token, "doWhileLoops") == 0)
1181 Resources.limits.doWhileLoops = (value != 0);
1182 else if (strcmp(token, "generalUniformIndexing") == 0)
1183 Resources.limits.generalUniformIndexing = (value != 0);
1184 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1185 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1186 else if (strcmp(token, "generalVaryingIndexing") == 0)
1187 Resources.limits.generalVaryingIndexing = (value != 0);
1188 else if (strcmp(token, "generalSamplerIndexing") == 0)
1189 Resources.limits.generalSamplerIndexing = (value != 0);
1190 else if (strcmp(token, "generalVariableIndexing") == 0)
1191 Resources.limits.generalVariableIndexing = (value != 0);
1192 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1193 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1194 else
1195 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1196
1197 token = strtok(0, delims);
1198 }
1199 if (configStrings)
1200 FreeFileData(configStrings);
1201}
1202
Tony Barbour6918cd52015-04-09 12:58:51 -06001203void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001204{
1205 if (m_compile_options & EOptionRelaxedErrors)
1206 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1207 if (m_compile_options & EOptionIntermediate)
1208 messages = (EShMessages)(messages | EShMsgAST);
1209 if (m_compile_options & EOptionSuppressWarnings)
1210 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1211}
1212
1213//
1214// Malloc a string of sufficient size and read a string into it.
1215//
Tony Barbour6918cd52015-04-09 12:58:51 -06001216char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001217{
1218 FILE *in;
1219 #if defined(_WIN32) && defined(__GNUC__)
1220 in = fopen(fileName, "r");
1221 int errorCode = in ? 0 : 1;
1222 #else
1223 int errorCode = fopen_s(&in, fileName, "r");
1224 #endif
1225
1226 char *fdata;
1227 int count = 0;
1228 const int maxSourceStrings = 5;
1229 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1230
1231 if (errorCode) {
1232 printf("Error: unable to open input file: %s\n", fileName);
1233 return 0;
1234 }
1235
1236 while (fgetc(in) != EOF)
1237 count++;
1238
1239 fseek(in, 0, SEEK_SET);
1240
1241 if (!(fdata = (char*)malloc(count+2))) {
1242 printf("Error allocating memory\n");
1243 return 0;
1244 }
1245 if (fread(fdata,1,count, in)!=count) {
1246 printf("Error reading input file: %s\n", fileName);
1247 return 0;
1248 }
1249 fdata[count] = '\0';
1250 fclose(in);
1251 if (count == 0) {
1252 return_data[0]=(char*)malloc(count+2);
1253 return_data[0][0]='\0';
1254 m_num_shader_strings = 0;
1255 return return_data;
1256 } else
1257 m_num_shader_strings = 1;
1258
1259 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1260 int ptr_len=0,i=0;
1261 while(count>0){
1262 return_data[i]=(char*)malloc(len+2);
1263 memcpy(return_data[i],fdata+ptr_len,len);
1264 return_data[i][len]='\0';
1265 count-=(len);
1266 ptr_len+=(len);
1267 if(count<len){
1268 if(count==0){
1269 m_num_shader_strings=(i+1);
1270 break;
1271 }
1272 len = count;
1273 }
1274 ++i;
1275 }
1276 return return_data;
1277}
1278
Tony Barbour6918cd52015-04-09 12:58:51 -06001279void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001280{
1281 for(int i=0;i<m_num_shader_strings;i++)
1282 free(data[i]);
1283}
1284
1285//
1286// Deduce the language from the filename. Files must end in one of the
1287// following extensions:
1288//
1289// .vert = vertex
1290// .tesc = tessellation control
1291// .tese = tessellation evaluation
1292// .geom = geometry
1293// .frag = fragment
1294// .comp = compute
1295//
Tony Barbour6918cd52015-04-09 12:58:51 -06001296EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001297{
1298 size_t ext = name.rfind('.');
1299 if (ext == std::string::npos) {
1300 return EShLangVertex;
1301 }
1302
1303 std::string suffix = name.substr(ext + 1, std::string::npos);
1304 if (suffix == "vert")
1305 return EShLangVertex;
1306 else if (suffix == "tesc")
1307 return EShLangTessControl;
1308 else if (suffix == "tese")
1309 return EShLangTessEvaluation;
1310 else if (suffix == "geom")
1311 return EShLangGeometry;
1312 else if (suffix == "frag")
1313 return EShLangFragment;
1314 else if (suffix == "comp")
1315 return EShLangCompute;
1316
1317 return EShLangVertex;
1318}
1319
1320//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001321// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001322//
Tony Barbourd1c35722015-04-16 15:59:00 -06001323EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001324{
1325 switch (shader_type) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001326 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001327 return EShLangVertex;
1328
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001329 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001330 return EShLangTessControl;
1331
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001332 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001333 return EShLangTessEvaluation;
1334
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001335 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001336 return EShLangGeometry;
1337
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001338 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001339 return EShLangFragment;
1340
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001341 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001342 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001343
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001344 default:
1345 return EShLangVertex;
1346 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001347}
1348
1349
1350//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001351// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001352// Return value of false means an error was encountered.
1353//
Tony Barbourd1c35722015-04-16 15:59:00 -06001354bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001355 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001356 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001357{
1358 glslang::TProgram& program = *new glslang::TProgram;
1359 const char *shaderStrings[1];
1360
1361 // TODO: Do we want to load a special config file depending on the
1362 // shader source? Optional name maybe?
1363 // SetConfigFile(fileName);
1364
1365 ProcessConfigFile();
1366
1367 EShMessages messages = EShMsgDefault;
1368 SetMessageOptions(messages);
1369
1370 EShLanguage stage = FindLanguage(shader_type);
1371 glslang::TShader* shader = new glslang::TShader(stage);
1372
1373 shaderStrings[0] = pshader;
1374 shader->setStrings(shaderStrings, 1);
1375
1376 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1377
Cody Northrop195d6622014-11-03 12:54:37 -07001378 if (! (m_compile_options & EOptionSuppressInfolog)) {
1379 puts(shader->getInfoLog());
1380 puts(shader->getInfoDebugLog());
1381 }
1382
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001383 return false; // something didn't work
1384 }
1385
1386 program.addShader(shader);
1387
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001388
1389 //
1390 // Program-level processing...
1391 //
1392
Cody Northrop195d6622014-11-03 12:54:37 -07001393 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001394
Cody Northrop195d6622014-11-03 12:54:37 -07001395 if (! (m_compile_options & EOptionSuppressInfolog)) {
1396 puts(shader->getInfoLog());
1397 puts(shader->getInfoDebugLog());
1398 }
1399
1400 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001401 }
1402
1403 if (m_compile_options & EOptionDumpReflection) {
1404 program.buildReflection();
1405 program.dumpReflection();
1406 }
1407
Cody Northrop5a95b472015-06-03 13:01:54 -06001408 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1409
1410 //
1411 // Test the different modes of SPIR-V modification
1412 //
1413 if (this->m_canonicalize_spv) {
1414 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1415 }
1416
1417 if (this->m_strip_spv) {
1418 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1419 }
1420
1421 if (this->m_do_everything_spv) {
1422 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1423 }
1424
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001425
1426 return true;
1427}
1428
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001429
1430
Tony Barbour6918cd52015-04-09 12:58:51 -06001431VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001432 m_width( 0 ),
1433 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001434 m_data( NULL ),
1435 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001436{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001437}
1438
Tony Barbour6918cd52015-04-09 12:58:51 -06001439VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001440{
1441
1442}
1443
Tony Barbour6918cd52015-04-09 12:58:51 -06001444VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001445{
1446 m_title = copyin.m_title;
1447 m_width = copyin.m_width;
1448 m_height = copyin.m_height;
1449 m_data_size = copyin.m_data_size;
1450 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1451}
1452
Tony Barbour6918cd52015-04-09 12:58:51 -06001453ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001454{
Tony Barbour6918cd52015-04-09 12:58:51 -06001455 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1456 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001457 return output;
1458}
1459
Tony Barbour6918cd52015-04-09 12:58:51 -06001460VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001461{
1462 m_title = rhs.m_title;
1463 m_width = rhs.m_width;
1464 m_height = rhs.m_height;
1465 m_data_size = rhs.m_data_size;
1466 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001467 return *this;
1468}
1469
Tony Barbour6918cd52015-04-09 12:58:51 -06001470int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001471{
1472 if( this->m_data != rhs.m_data) return 0;
1473 return 1;
1474}
1475
1476// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001477int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001478{
1479 if( this->m_data_size < rhs.m_data_size ) return 1;
1480 return 0;
1481}
1482