blob: be39d2d5d216ab8dc63ff7fb4456a96f4bada81a [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;
Cody Northrope2baad22015-06-09 15:56:56 -0600679 // Note: Addition of color attachment is a workaround needed for some implementations
680 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT |
681 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
Chia-I Wuf8693382015-04-16 22:02:10 +0800682 swap_chain.swapModeFlags = VK_SWAP_MODE_FLIP_BIT_WSI |
683 VK_SWAP_MODE_BLIT_BIT_WSI;
684
Jon Ashburn07daee72015-05-21 18:13:33 -0600685 err = m_fpCreateSwapChainWSI(m_device.obj(), &swap_chain, &m_swap_chain);
Chia-I Wuf8693382015-04-16 22:02:10 +0800686 assert(!err);
687
Tony-LunarG399dfca2015-05-19 14:08:26 -0600688 VkSwapChainImageInfoWSI infos[2];
Courtney Goeltzenleuchter763cc7a2015-06-24 15:02:51 -0600689 size_t size = sizeof(VkSwapChainImageInfoWSI) * m_images.size() * 2;
Jon Ashburn07daee72015-05-21 18:13:33 -0600690 std::vector<VkSwapChainImageInfoWSI> persistent_images;
691 persistent_images.resize(m_images.size());
692 err = m_fpGetSwapChainInfoWSI(m_swap_chain,
Chia-I Wuf8693382015-04-16 22:02:10 +0800693 VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600694 &size, &infos);
695 assert(!err && size == sizeof(VkSwapChainImageInfoWSI) * 2);
696 m_persistent_images.push_back(infos[0]);
697 m_persistent_images.push_back(infos[1]);
Tony Barbour96db8822015-02-25 12:28:39 -0700698}
699
Jon Ashburn07daee72015-05-21 18:13:33 -0600700void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -0700701{
Jon Ashburn07daee72015-05-21 18:13:33 -0600702 m_fpCreateSwapChainWSI = (PFN_vkCreateSwapChainWSI) vkGetInstanceProcAddr(inst, "vkCreateSwapChainWSI");
703 ASSERT_TRUE(m_fpCreateSwapChainWSI != NULL) << "vkGetInstanceProcAddr failed to find vkCreateSwapChainWSI";
704
705 m_fpDestroySwapChainWSI = (PFN_vkDestroySwapChainWSI) vkGetInstanceProcAddr(inst, "vkDestroySwapChainWSI");
706 ASSERT_TRUE(m_fpDestroySwapChainWSI != NULL) << "vkGetInstanceProcAddr failed to find vkDestroySwapChainWSI";
707
708 m_fpGetSwapChainInfoWSI = (PFN_vkGetSwapChainInfoWSI) vkGetInstanceProcAddr(inst, "vkGetSwapChainInfoWSI");
709 ASSERT_TRUE(m_fpGetSwapChainInfoWSI != NULL) << "vkGetInstanceProcAddr failed to find vkGetSwapChainInfoWSI";
710
711 m_fpQueuePresentWSI = (PFN_vkQueuePresentWSI) vkGetInstanceProcAddr(inst, "vkQueuePresentWSI");
712 ASSERT_TRUE(m_fpQueuePresentWSI != NULL) << "vkGetInstanceProcAddr failed to find vkQueuePresentWSI";
713
Tony Barbour96db8822015-02-25 12:28:39 -0700714 m_images = imagesIn;
715}
716
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600717#ifdef _WIN32
718void TestFrameworkVkPresent::CreateMyWindow()
719{
720 WNDCLASSEX win_class;
721 // const ::testing::TestInfo* const test_info =
722 // ::testing::UnitTest::GetInstance()->current_test_info();
723 m_connection = GetModuleHandle(NULL);
724
725 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
726 it != m_images.end(); it++) {
727 if (m_width < it->m_width)
728 m_width = it->m_width;
729 if (m_height < it->m_height)
730 m_height = it->m_height;
731 }
732 // Initialize the window class structure:
733 win_class.cbSize = sizeof(WNDCLASSEX);
734 win_class.style = CS_HREDRAW | CS_VREDRAW;
735 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
736 win_class.cbClsExtra = 0;
737 win_class.cbWndExtra = 0;
738 win_class.hInstance = m_connection; // hInstance
739 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
740 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
741 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
742 win_class.lpszMenuName = NULL;
743 win_class.lpszClassName = "Test";
744 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
745 // Register window class:
746 if (!RegisterClassEx(&win_class)) {
747 // It didn't work, so try to give a useful error:
748 printf("Unexpected error trying to start the application!\n");
749 fflush(stdout);
750 exit(1);
751 }
752 // Create window with the registered class:
753 m_window = CreateWindowEx(0,
754 "Test", // class name
755 "Test", // app name
756 WS_OVERLAPPEDWINDOW | // window style
757 WS_VISIBLE |
758 WS_SYSMENU,
759 100,100, // x/y coords
760 m_width, // width
761 m_height, // height
762 NULL, // handle to parent
763 NULL, // handle to menu
764 m_connection, // hInstance
765 NULL); // no extra parameters
766
767 if (!m_window) {
768 // It didn't work, so try to give a useful error:
769 DWORD error = GetLastError();
770 char message[120];
771 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
772 MessageBox(NULL, message, "Error", MB_OK);
773 exit(1);
774 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600775 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
776 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600777}
778#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600779void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -0700780{
Chia-I Wuf8693382015-04-16 22:02:10 +0800781 const xcb_setup_t *setup;
782 xcb_screen_iterator_t iter;
783 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -0700784 uint32_t value_mask, value_list[32];
785
Chia-I Wuf8693382015-04-16 22:02:10 +0800786 m_connection = xcb_connect(NULL, &scr);
787
788 setup = xcb_get_setup(m_connection);
789 iter = xcb_setup_roots_iterator(setup);
790 while (scr-- > 0)
791 xcb_screen_next(&iter);
792
793 m_screen = iter.data;
794
795 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
796 it != m_images.end(); it++) {
797 if (m_width < it->m_width)
798 m_width = it->m_width;
799 if (m_height < it->m_height)
800 m_height = it->m_height;
801 }
802
803 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700804
805 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +0800806 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -0700807 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
808 XCB_EVENT_MASK_EXPOSURE |
809 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
810
Chia-I Wuf8693382015-04-16 22:02:10 +0800811 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700812 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800813 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -0700814 0, 0, m_width, m_height, 0,
815 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800816 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -0700817 value_mask, value_list);
818
819 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +0800820 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -0700821 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +0800822 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -0700823
Chia-I Wuf8693382015-04-16 22:02:10 +0800824 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
825 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -0700826
Chia-I Wuf8693382015-04-16 22:02:10 +0800827 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -0700828 m_window, (*reply).atom, 4, 32, 1,
829 &(*m_atom_wm_delete_window).atom);
830 free(reply);
831
Chia-I Wuf8693382015-04-16 22:02:10 +0800832 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -0700833}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600834#endif
Tony Barbour96db8822015-02-25 12:28:39 -0700835
Tony Barbour6918cd52015-04-09 12:58:51 -0600836void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -0700837{
Jon Ashburn07daee72015-05-21 18:13:33 -0600838 m_fpDestroySwapChainWSI(m_swap_chain);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600839#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800840 xcb_destroy_window(m_connection, m_window);
841 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600842#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600843}
844
Tony Barbour6918cd52015-04-09 12:58:51 -0600845void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600846{
847 if (m_images.size() == 0) return;
848
Chia-I Wuf8693382015-04-16 22:02:10 +0800849 vk_testing::Environment env;
850 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -0700851 {
Chia-I Wuf8693382015-04-16 22:02:10 +0800852 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -0700853
Jon Ashburn07daee72015-05-21 18:13:33 -0600854 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600855 vkPresent.CreateMyWindow();
Chia-I Wuf8693382015-04-16 22:02:10 +0800856 vkPresent.CreateSwapChain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600857 vkPresent.Run();
858 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -0700859 }
Chia-I Wuf8693382015-04-16 22:02:10 +0800860 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600861}
862
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600863//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600864// These are the default resources for TBuiltInResources, used for both
865// - parsing this string for the case where the user didn't supply one
866// - dumping out a template for user construction of a config file
867//
868static const char* DefaultConfig =
869 "MaxLights 32\n"
870 "MaxClipPlanes 6\n"
871 "MaxTextureUnits 32\n"
872 "MaxTextureCoords 32\n"
873 "MaxVertexAttribs 64\n"
874 "MaxVertexUniformComponents 4096\n"
875 "MaxVaryingFloats 64\n"
876 "MaxVertexTextureImageUnits 32\n"
877 "MaxCombinedTextureImageUnits 80\n"
878 "MaxTextureImageUnits 32\n"
879 "MaxFragmentUniformComponents 4096\n"
880 "MaxDrawBuffers 32\n"
881 "MaxVertexUniformVectors 128\n"
882 "MaxVaryingVectors 8\n"
883 "MaxFragmentUniformVectors 16\n"
884 "MaxVertexOutputVectors 16\n"
885 "MaxFragmentInputVectors 15\n"
886 "MinProgramTexelOffset -8\n"
887 "MaxProgramTexelOffset 7\n"
888 "MaxClipDistances 8\n"
889 "MaxComputeWorkGroupCountX 65535\n"
890 "MaxComputeWorkGroupCountY 65535\n"
891 "MaxComputeWorkGroupCountZ 65535\n"
892 "MaxComputeWorkGroupSizeX 1024\n"
893 "MaxComputeWorkGroupSizeY 1024\n"
894 "MaxComputeWorkGroupSizeZ 64\n"
895 "MaxComputeUniformComponents 1024\n"
896 "MaxComputeTextureImageUnits 16\n"
897 "MaxComputeImageUniforms 8\n"
898 "MaxComputeAtomicCounters 8\n"
899 "MaxComputeAtomicCounterBuffers 1\n"
900 "MaxVaryingComponents 60\n"
901 "MaxVertexOutputComponents 64\n"
902 "MaxGeometryInputComponents 64\n"
903 "MaxGeometryOutputComponents 128\n"
904 "MaxFragmentInputComponents 128\n"
905 "MaxImageUnits 8\n"
906 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
907 "MaxCombinedShaderOutputResources 8\n"
908 "MaxImageSamples 0\n"
909 "MaxVertexImageUniforms 0\n"
910 "MaxTessControlImageUniforms 0\n"
911 "MaxTessEvaluationImageUniforms 0\n"
912 "MaxGeometryImageUniforms 0\n"
913 "MaxFragmentImageUniforms 8\n"
914 "MaxCombinedImageUniforms 8\n"
915 "MaxGeometryTextureImageUnits 16\n"
916 "MaxGeometryOutputVertices 256\n"
917 "MaxGeometryTotalOutputComponents 1024\n"
918 "MaxGeometryUniformComponents 1024\n"
919 "MaxGeometryVaryingComponents 64\n"
920 "MaxTessControlInputComponents 128\n"
921 "MaxTessControlOutputComponents 128\n"
922 "MaxTessControlTextureImageUnits 16\n"
923 "MaxTessControlUniformComponents 1024\n"
924 "MaxTessControlTotalOutputComponents 4096\n"
925 "MaxTessEvaluationInputComponents 128\n"
926 "MaxTessEvaluationOutputComponents 128\n"
927 "MaxTessEvaluationTextureImageUnits 16\n"
928 "MaxTessEvaluationUniformComponents 1024\n"
929 "MaxTessPatchComponents 120\n"
930 "MaxPatchVertices 32\n"
931 "MaxTessGenLevel 64\n"
932 "MaxViewports 16\n"
933 "MaxVertexAtomicCounters 0\n"
934 "MaxTessControlAtomicCounters 0\n"
935 "MaxTessEvaluationAtomicCounters 0\n"
936 "MaxGeometryAtomicCounters 0\n"
937 "MaxFragmentAtomicCounters 8\n"
938 "MaxCombinedAtomicCounters 8\n"
939 "MaxAtomicCounterBindings 1\n"
940 "MaxVertexAtomicCounterBuffers 0\n"
941 "MaxTessControlAtomicCounterBuffers 0\n"
942 "MaxTessEvaluationAtomicCounterBuffers 0\n"
943 "MaxGeometryAtomicCounterBuffers 0\n"
944 "MaxFragmentAtomicCounterBuffers 1\n"
945 "MaxCombinedAtomicCounterBuffers 1\n"
946 "MaxAtomicCounterBufferSize 16384\n"
947 "MaxTransformFeedbackBuffers 4\n"
948 "MaxTransformFeedbackInterleavedComponents 64\n"
949 "MaxCullDistances 8\n"
950 "MaxCombinedClipAndCullDistances 8\n"
951 "MaxSamples 4\n"
952
953 "nonInductiveForLoops 1\n"
954 "whileLoops 1\n"
955 "doWhileLoops 1\n"
956 "generalUniformIndexing 1\n"
957 "generalAttributeMatrixVectorIndexing 1\n"
958 "generalVaryingIndexing 1\n"
959 "generalSamplerIndexing 1\n"
960 "generalVariableIndexing 1\n"
961 "generalConstantMatrixVectorIndexing 1\n"
962 ;
963
964//
965// *.conf => this is a config file that can set limits/resources
966//
Tony Barbour6918cd52015-04-09 12:58:51 -0600967bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600968{
969 if (name.size() < 5)
970 return false;
971
972 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
973 ConfigFile = name;
974 return true;
975 }
976
977 return false;
978}
979
980//
981// Parse either a .conf file provided by the user or the default string above.
982//
Tony Barbour6918cd52015-04-09 12:58:51 -0600983void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600984{
985 char** configStrings = 0;
986 char* config = 0;
987 if (ConfigFile.size() > 0) {
988 configStrings = ReadFileData(ConfigFile.c_str());
989 if (configStrings)
990 config = *configStrings;
991 else {
992 printf("Error opening configuration file; will instead use the default configuration\n");
993 }
994 }
995
996 if (config == 0) {
997 config = new char[strlen(DefaultConfig) + 1];
998 strcpy(config, DefaultConfig);
999 }
1000
1001 const char* delims = " \t\n\r";
1002 const char* token = strtok(config, delims);
1003 while (token) {
1004 const char* valueStr = strtok(0, delims);
1005 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1006 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1007 return;
1008 }
1009 int value = atoi(valueStr);
1010
1011 if (strcmp(token, "MaxLights") == 0)
1012 Resources.maxLights = value;
1013 else if (strcmp(token, "MaxClipPlanes") == 0)
1014 Resources.maxClipPlanes = value;
1015 else if (strcmp(token, "MaxTextureUnits") == 0)
1016 Resources.maxTextureUnits = value;
1017 else if (strcmp(token, "MaxTextureCoords") == 0)
1018 Resources.maxTextureCoords = value;
1019 else if (strcmp(token, "MaxVertexAttribs") == 0)
1020 Resources.maxVertexAttribs = value;
1021 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1022 Resources.maxVertexUniformComponents = value;
1023 else if (strcmp(token, "MaxVaryingFloats") == 0)
1024 Resources.maxVaryingFloats = value;
1025 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1026 Resources.maxVertexTextureImageUnits = value;
1027 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1028 Resources.maxCombinedTextureImageUnits = value;
1029 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1030 Resources.maxTextureImageUnits = value;
1031 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1032 Resources.maxFragmentUniformComponents = value;
1033 else if (strcmp(token, "MaxDrawBuffers") == 0)
1034 Resources.maxDrawBuffers = value;
1035 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1036 Resources.maxVertexUniformVectors = value;
1037 else if (strcmp(token, "MaxVaryingVectors") == 0)
1038 Resources.maxVaryingVectors = value;
1039 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1040 Resources.maxFragmentUniformVectors = value;
1041 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1042 Resources.maxVertexOutputVectors = value;
1043 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1044 Resources.maxFragmentInputVectors = value;
1045 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1046 Resources.minProgramTexelOffset = value;
1047 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1048 Resources.maxProgramTexelOffset = value;
1049 else if (strcmp(token, "MaxClipDistances") == 0)
1050 Resources.maxClipDistances = value;
1051 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1052 Resources.maxComputeWorkGroupCountX = value;
1053 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1054 Resources.maxComputeWorkGroupCountY = value;
1055 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1056 Resources.maxComputeWorkGroupCountZ = value;
1057 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1058 Resources.maxComputeWorkGroupSizeX = value;
1059 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1060 Resources.maxComputeWorkGroupSizeY = value;
1061 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1062 Resources.maxComputeWorkGroupSizeZ = value;
1063 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1064 Resources.maxComputeUniformComponents = value;
1065 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1066 Resources.maxComputeTextureImageUnits = value;
1067 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1068 Resources.maxComputeImageUniforms = value;
1069 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1070 Resources.maxComputeAtomicCounters = value;
1071 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1072 Resources.maxComputeAtomicCounterBuffers = value;
1073 else if (strcmp(token, "MaxVaryingComponents") == 0)
1074 Resources.maxVaryingComponents = value;
1075 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1076 Resources.maxVertexOutputComponents = value;
1077 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1078 Resources.maxGeometryInputComponents = value;
1079 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1080 Resources.maxGeometryOutputComponents = value;
1081 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1082 Resources.maxFragmentInputComponents = value;
1083 else if (strcmp(token, "MaxImageUnits") == 0)
1084 Resources.maxImageUnits = value;
1085 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1086 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1087 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1088 Resources.maxCombinedShaderOutputResources = value;
1089 else if (strcmp(token, "MaxImageSamples") == 0)
1090 Resources.maxImageSamples = value;
1091 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1092 Resources.maxVertexImageUniforms = value;
1093 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1094 Resources.maxTessControlImageUniforms = value;
1095 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1096 Resources.maxTessEvaluationImageUniforms = value;
1097 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1098 Resources.maxGeometryImageUniforms = value;
1099 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1100 Resources.maxFragmentImageUniforms = value;
1101 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1102 Resources.maxCombinedImageUniforms = value;
1103 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1104 Resources.maxGeometryTextureImageUnits = value;
1105 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1106 Resources.maxGeometryOutputVertices = value;
1107 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1108 Resources.maxGeometryTotalOutputComponents = value;
1109 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1110 Resources.maxGeometryUniformComponents = value;
1111 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1112 Resources.maxGeometryVaryingComponents = value;
1113 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1114 Resources.maxTessControlInputComponents = value;
1115 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1116 Resources.maxTessControlOutputComponents = value;
1117 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1118 Resources.maxTessControlTextureImageUnits = value;
1119 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1120 Resources.maxTessControlUniformComponents = value;
1121 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1122 Resources.maxTessControlTotalOutputComponents = value;
1123 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1124 Resources.maxTessEvaluationInputComponents = value;
1125 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1126 Resources.maxTessEvaluationOutputComponents = value;
1127 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1128 Resources.maxTessEvaluationTextureImageUnits = value;
1129 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1130 Resources.maxTessEvaluationUniformComponents = value;
1131 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1132 Resources.maxTessPatchComponents = value;
1133 else if (strcmp(token, "MaxPatchVertices") == 0)
1134 Resources.maxPatchVertices = value;
1135 else if (strcmp(token, "MaxTessGenLevel") == 0)
1136 Resources.maxTessGenLevel = value;
1137 else if (strcmp(token, "MaxViewports") == 0)
1138 Resources.maxViewports = value;
1139 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1140 Resources.maxVertexAtomicCounters = value;
1141 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1142 Resources.maxTessControlAtomicCounters = value;
1143 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1144 Resources.maxTessEvaluationAtomicCounters = value;
1145 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1146 Resources.maxGeometryAtomicCounters = value;
1147 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1148 Resources.maxFragmentAtomicCounters = value;
1149 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1150 Resources.maxCombinedAtomicCounters = value;
1151 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1152 Resources.maxAtomicCounterBindings = value;
1153 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1154 Resources.maxVertexAtomicCounterBuffers = value;
1155 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1156 Resources.maxTessControlAtomicCounterBuffers = value;
1157 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1158 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1159 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1160 Resources.maxGeometryAtomicCounterBuffers = value;
1161 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1162 Resources.maxFragmentAtomicCounterBuffers = value;
1163 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1164 Resources.maxCombinedAtomicCounterBuffers = value;
1165 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1166 Resources.maxAtomicCounterBufferSize = value;
1167 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1168 Resources.maxTransformFeedbackBuffers = value;
1169 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1170 Resources.maxTransformFeedbackInterleavedComponents = value;
1171 else if (strcmp(token, "MaxCullDistances") == 0)
1172 Resources.maxCullDistances = value;
1173 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1174 Resources.maxCombinedClipAndCullDistances = value;
1175 else if (strcmp(token, "MaxSamples") == 0)
1176 Resources.maxSamples = value;
1177
1178 else if (strcmp(token, "nonInductiveForLoops") == 0)
1179 Resources.limits.nonInductiveForLoops = (value != 0);
1180 else if (strcmp(token, "whileLoops") == 0)
1181 Resources.limits.whileLoops = (value != 0);
1182 else if (strcmp(token, "doWhileLoops") == 0)
1183 Resources.limits.doWhileLoops = (value != 0);
1184 else if (strcmp(token, "generalUniformIndexing") == 0)
1185 Resources.limits.generalUniformIndexing = (value != 0);
1186 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1187 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1188 else if (strcmp(token, "generalVaryingIndexing") == 0)
1189 Resources.limits.generalVaryingIndexing = (value != 0);
1190 else if (strcmp(token, "generalSamplerIndexing") == 0)
1191 Resources.limits.generalSamplerIndexing = (value != 0);
1192 else if (strcmp(token, "generalVariableIndexing") == 0)
1193 Resources.limits.generalVariableIndexing = (value != 0);
1194 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1195 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1196 else
1197 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1198
1199 token = strtok(0, delims);
1200 }
1201 if (configStrings)
1202 FreeFileData(configStrings);
1203}
1204
Tony Barbour6918cd52015-04-09 12:58:51 -06001205void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001206{
1207 if (m_compile_options & EOptionRelaxedErrors)
1208 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1209 if (m_compile_options & EOptionIntermediate)
1210 messages = (EShMessages)(messages | EShMsgAST);
1211 if (m_compile_options & EOptionSuppressWarnings)
1212 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1213}
1214
1215//
1216// Malloc a string of sufficient size and read a string into it.
1217//
Tony Barbour6918cd52015-04-09 12:58:51 -06001218char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001219{
1220 FILE *in;
1221 #if defined(_WIN32) && defined(__GNUC__)
1222 in = fopen(fileName, "r");
1223 int errorCode = in ? 0 : 1;
1224 #else
1225 int errorCode = fopen_s(&in, fileName, "r");
1226 #endif
1227
1228 char *fdata;
1229 int count = 0;
1230 const int maxSourceStrings = 5;
1231 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1232
1233 if (errorCode) {
1234 printf("Error: unable to open input file: %s\n", fileName);
1235 return 0;
1236 }
1237
1238 while (fgetc(in) != EOF)
1239 count++;
1240
1241 fseek(in, 0, SEEK_SET);
1242
1243 if (!(fdata = (char*)malloc(count+2))) {
1244 printf("Error allocating memory\n");
1245 return 0;
1246 }
1247 if (fread(fdata,1,count, in)!=count) {
1248 printf("Error reading input file: %s\n", fileName);
1249 return 0;
1250 }
1251 fdata[count] = '\0';
1252 fclose(in);
1253 if (count == 0) {
1254 return_data[0]=(char*)malloc(count+2);
1255 return_data[0][0]='\0';
1256 m_num_shader_strings = 0;
1257 return return_data;
1258 } else
1259 m_num_shader_strings = 1;
1260
1261 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1262 int ptr_len=0,i=0;
1263 while(count>0){
1264 return_data[i]=(char*)malloc(len+2);
1265 memcpy(return_data[i],fdata+ptr_len,len);
1266 return_data[i][len]='\0';
1267 count-=(len);
1268 ptr_len+=(len);
1269 if(count<len){
1270 if(count==0){
1271 m_num_shader_strings=(i+1);
1272 break;
1273 }
1274 len = count;
1275 }
1276 ++i;
1277 }
1278 return return_data;
1279}
1280
Tony Barbour6918cd52015-04-09 12:58:51 -06001281void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001282{
1283 for(int i=0;i<m_num_shader_strings;i++)
1284 free(data[i]);
1285}
1286
1287//
1288// Deduce the language from the filename. Files must end in one of the
1289// following extensions:
1290//
1291// .vert = vertex
1292// .tesc = tessellation control
1293// .tese = tessellation evaluation
1294// .geom = geometry
1295// .frag = fragment
1296// .comp = compute
1297//
Tony Barbour6918cd52015-04-09 12:58:51 -06001298EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001299{
1300 size_t ext = name.rfind('.');
1301 if (ext == std::string::npos) {
1302 return EShLangVertex;
1303 }
1304
1305 std::string suffix = name.substr(ext + 1, std::string::npos);
1306 if (suffix == "vert")
1307 return EShLangVertex;
1308 else if (suffix == "tesc")
1309 return EShLangTessControl;
1310 else if (suffix == "tese")
1311 return EShLangTessEvaluation;
1312 else if (suffix == "geom")
1313 return EShLangGeometry;
1314 else if (suffix == "frag")
1315 return EShLangFragment;
1316 else if (suffix == "comp")
1317 return EShLangCompute;
1318
1319 return EShLangVertex;
1320}
1321
1322//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001323// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001324//
Tony Barbourd1c35722015-04-16 15:59:00 -06001325EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001326{
1327 switch (shader_type) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001328 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001329 return EShLangVertex;
1330
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001331 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001332 return EShLangTessControl;
1333
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001334 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001335 return EShLangTessEvaluation;
1336
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001337 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001338 return EShLangGeometry;
1339
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001340 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001341 return EShLangFragment;
1342
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001343 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001344 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001345
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001346 default:
1347 return EShLangVertex;
1348 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001349}
1350
1351
1352//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001353// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001354// Return value of false means an error was encountered.
1355//
Tony Barbourd1c35722015-04-16 15:59:00 -06001356bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001357 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001358 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001359{
1360 glslang::TProgram& program = *new glslang::TProgram;
1361 const char *shaderStrings[1];
1362
1363 // TODO: Do we want to load a special config file depending on the
1364 // shader source? Optional name maybe?
1365 // SetConfigFile(fileName);
1366
1367 ProcessConfigFile();
1368
1369 EShMessages messages = EShMsgDefault;
1370 SetMessageOptions(messages);
1371
1372 EShLanguage stage = FindLanguage(shader_type);
1373 glslang::TShader* shader = new glslang::TShader(stage);
1374
1375 shaderStrings[0] = pshader;
1376 shader->setStrings(shaderStrings, 1);
1377
1378 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1379
Cody Northrop195d6622014-11-03 12:54:37 -07001380 if (! (m_compile_options & EOptionSuppressInfolog)) {
1381 puts(shader->getInfoLog());
1382 puts(shader->getInfoDebugLog());
1383 }
1384
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001385 return false; // something didn't work
1386 }
1387
1388 program.addShader(shader);
1389
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001390
1391 //
1392 // Program-level processing...
1393 //
1394
Cody Northrop195d6622014-11-03 12:54:37 -07001395 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001396
Cody Northrop195d6622014-11-03 12:54:37 -07001397 if (! (m_compile_options & EOptionSuppressInfolog)) {
1398 puts(shader->getInfoLog());
1399 puts(shader->getInfoDebugLog());
1400 }
1401
1402 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001403 }
1404
1405 if (m_compile_options & EOptionDumpReflection) {
1406 program.buildReflection();
1407 program.dumpReflection();
1408 }
1409
Cody Northrop5a95b472015-06-03 13:01:54 -06001410 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1411
1412 //
1413 // Test the different modes of SPIR-V modification
1414 //
1415 if (this->m_canonicalize_spv) {
1416 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1417 }
1418
1419 if (this->m_strip_spv) {
1420 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1421 }
1422
1423 if (this->m_do_everything_spv) {
1424 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1425 }
1426
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001427
1428 return true;
1429}
1430
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001431
1432
Tony Barbour6918cd52015-04-09 12:58:51 -06001433VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001434 m_width( 0 ),
1435 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001436 m_data( NULL ),
1437 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001438{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001439}
1440
Tony Barbour6918cd52015-04-09 12:58:51 -06001441VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001442{
1443
1444}
1445
Tony Barbour6918cd52015-04-09 12:58:51 -06001446VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001447{
1448 m_title = copyin.m_title;
1449 m_width = copyin.m_width;
1450 m_height = copyin.m_height;
1451 m_data_size = copyin.m_data_size;
1452 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1453}
1454
Tony Barbour6918cd52015-04-09 12:58:51 -06001455ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001456{
Tony Barbour6918cd52015-04-09 12:58:51 -06001457 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1458 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001459 return output;
1460}
1461
Tony Barbour6918cd52015-04-09 12:58:51 -06001462VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001463{
1464 m_title = rhs.m_title;
1465 m_width = rhs.m_width;
1466 m_height = rhs.m_height;
1467 m_data_size = rhs.m_data_size;
1468 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001469 return *this;
1470}
1471
Tony Barbour6918cd52015-04-09 12:58:51 -06001472int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001473{
1474 if( this->m_data != rhs.m_data) return 0;
1475 return 1;
1476}
1477
1478// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001479int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001480{
1481 if( this->m_data_size < rhs.m_data_size ) return 1;
1482 return 0;
1483}
1484