blob: 1b8315bac54e2270d2e99e356461edb74718ce3b [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"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600225 "\t\tStrip SPIR-V debug information (line numbers, names, etc).\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600226 printf("\t--canonicalize-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600227 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600228 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;
Chia-I Wu681d7a02015-07-03 13:44:34 +0800268 ptr = (char *) displayImage.MapMemory();
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();
Chia-I Wu681d7a02015-07-03 13:44:34 +0800306 displayImage.UnmapMemory();
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
Chia-I Wu681d7a02015-07-03 13:44:34 +0800382 ptr = (char *) displayImage.MapMemory();
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
Chia-I Wu681d7a02015-07-03 13:44:34 +0800397 displayImage.UnmapMemory();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600398}
399
Tony Barbour6918cd52015-04-09 12:58:51 -0600400void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600401{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600402 for (int32_t i = 0; i < images.size(); i++) {
403 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600404 }
405}
406
Tony Barbour6918cd52015-04-09 12:58:51 -0600407void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600408{
409 const ::testing::TestInfo* const test_info =
410 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600411 ostringstream filestream;
412 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600413
Tony Barbour247bf372014-10-30 14:29:04 -0600414 m_width = 40;
415
416 if (strcmp(test_info->name(), m_testName.c_str())) {
417 filestream << test_info->name();
418 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700419 m_frameNum = 2;
420 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600421 }
422 else {
423 filestream << test_info->name() << "-" << m_frameNum;
424 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700425 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600426 }
427
Tony Barbour247bf372014-10-30 14:29:04 -0600428 // ToDo - scrub string for bad characters
429
430 if (m_save_images || m_compare_images) {
431 WritePPM(filename.c_str(), image);
432 if (m_compare_images) {
433 Compare(filename.c_str(), image);
434 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600435 }
436
437 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600438 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600439 }
440}
441
Chia-I Wuf8693382015-04-16 22:02:10 +0800442TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
443 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700444 m_queue(*m_device.graphics_queues()[0]),
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600445 m_cmdbuf(m_device, vk_testing::CmdBuffer::create_info(m_device.graphics_queue_node_index_))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600446{
Tony Barbour96db8822015-02-25 12:28:39 -0700447 m_quit = false;
448 m_pause = false;
449 m_width = 0;
450 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600451}
452
Tony Barbour6918cd52015-04-09 12:58:51 -0600453void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600454{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600455 VkResult U_ASSERT_ONLY err;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600456 vk_testing::Buffer buf;
457 void *dest_ptr;
458
459 if (m_persistent_images.size() != 2) {
460 return;
461 }
462
463 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Cody Northrop7fb43862015-06-22 14:56:14 -0600464 buf.init_as_src(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800465 dest_ptr = buf.memory().map();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600466 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
Chia-I Wu681d7a02015-07-03 13:44:34 +0800467 buf.memory().unmap();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600468
469 m_cmdbuf.begin();
470
471 VkBufferImageCopy region = {};
472 region.imageExtent.height = m_display_image->m_height;
473 region.imageExtent.width = m_display_image->m_width;
474 region.imageExtent.depth = 1;
475
Chia-I Wube2b9172015-07-03 11:49:42 +0800476 vkCmdCopyBufferToImage(m_cmdbuf.handle(),
Chia-I Wu681d7a02015-07-03 13:44:34 +0800477 buf.handle(),
Tony-LunarG399dfca2015-05-19 14:08:26 -0600478 m_persistent_images[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
479 1, &region);
480 m_cmdbuf.end();
481
482 VkCmdBuffer cmdBufs[1];
Chia-I Wube2b9172015-07-03 11:49:42 +0800483 cmdBufs[0] = m_cmdbuf.handle();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600484
Chia-I Wudf12ffd2015-07-03 10:53:18 +0800485 vkQueueSubmit(m_queue.handle(), 1, cmdBufs, NULL);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600486 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700487
Chia-I Wuf8693382015-04-16 22:02:10 +0800488 VkPresentInfoWSI present = {};
489 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_WSI;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600490 present.image = m_persistent_images[m_current_buffer].image;
Chia-I Wuf8693382015-04-16 22:02:10 +0800491 present.flipInterval = 1;
Tony Barbour96db8822015-02-25 12:28:39 -0700492
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600493#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800494 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700495 XCB_PROP_MODE_REPLACE,
496 m_window,
497 XCB_ATOM_WM_NAME,
498 XCB_ATOM_STRING,
499 8,
500 m_display_image->m_title.size(),
501 m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600502#endif
Jon Ashburn07daee72015-05-21 18:13:33 -0600503
Chia-I Wudf12ffd2015-07-03 10:53:18 +0800504 err = m_fpQueuePresentWSI(m_queue.handle(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700505 assert(!err);
506
507 m_queue.wait();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600508 m_current_buffer = (m_current_buffer + 1) % 2;
Tony Barbour96db8822015-02-25 12:28:39 -0700509
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600510}
511
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600512#ifdef _WIN32
Tony-LunarG399dfca2015-05-19 14:08:26 -0600513# define PREVIOUSLY_DOWN 1<<29
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600514// MS-Windows event handling function:
515LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
516 UINT uMsg,
517 WPARAM wParam,
518 LPARAM lParam)
519{
520
521 switch(uMsg)
522 {
523 case WM_CLOSE:
524 PostQuitMessage(0);
525 break;
526
527 case WM_PAINT:
528 {
529 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
530 if (me) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600531 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600532 me->Display();
533 }
534 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600535 break;
536
537 case WM_KEYDOWN:
538 {
539 if (lParam & (PREVIOUSLY_DOWN)){
540 break;
541 }
542 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
543 // the window, we put the this pointer into the window's user data so we could get it back now
544 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
545 switch (wParam)
546 {
547 case VK_ESCAPE: me->m_quit = true;
548 break;
549
550 case VK_LEFT: // left arrow key
551 if (me->m_display_image == me->m_images.begin()) {
552 me->m_display_image = --me->m_images.end();
553 }
554 else {
555 --me->m_display_image;
556 }
557 break;
558
559 case VK_RIGHT: // right arrow key
560 ++me->m_display_image;
561 if (me->m_display_image == me->m_images.end()) {
562 me->m_display_image = me->m_images.begin();
563 }
564 break;
565
566 default:
567 break;
568 }
569 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
570 me->Display();
571 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600572 }
573 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
574}
575
576void TestFrameworkVkPresent::Run()
577{
578 MSG msg; // message
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600579
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600580 /* main message loop*/
Tony-LunarG399dfca2015-05-19 14:08:26 -0600581 while(! m_quit) {
582 GetMessage(&msg, m_window, 0, 0);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600583 if (msg.message == WM_QUIT) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600584 m_quit = true; //if found, quit app
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600585 } else {
586 /* Translate and dispatch to event queue*/
587 TranslateMessage(&msg);
588 DispatchMessage(&msg);
589 }
590 }
591}
592
593#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600594void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600595{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600596 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700597 switch (event_code) {
598 case XCB_EXPOSE:
599 Display(); // TODO: handle resize
600 break;
601 case XCB_CLIENT_MESSAGE:
602 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
603 (m_atom_wm_delete_window)->atom) {
604 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600605 }
606 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700607 case XCB_KEY_RELEASE:
608 {
609 const xcb_key_release_event_t *key =
610 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600611
Tony Barbour96db8822015-02-25 12:28:39 -0700612 switch (key->detail) {
613 case 0x9: // Escape
614 m_quit = true;
615 break;
616 case 0x71: // left arrow key
617 if (m_display_image == m_images.begin()) {
618 m_display_image = --m_images.end();
619 } else {
620 --m_display_image;
621 }
622 break;
623 case 0x72: // right arrow key
624 ++m_display_image;
625 if (m_display_image == m_images.end()) {
626 m_display_image = m_images.begin();
627 }
628 break;
629 case 0x41:
630 m_pause = !m_pause;
631 break;
632 }
633 Display();
634 }
635 break;
636 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600637 break;
638 }
Tony Barbour96db8822015-02-25 12:28:39 -0700639}
640
Tony Barbour6918cd52015-04-09 12:58:51 -0600641void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700642{
Chia-I Wuf8693382015-04-16 22:02:10 +0800643 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700644
645 while (! m_quit) {
646 xcb_generic_event_t *event;
647
648 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800649 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700650 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800651 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700652 }
653 if (event) {
654 HandleEvent(event);
655 free(event);
656 }
657 }
658}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600659#endif // _WIN32
Tony Barbour96db8822015-02-25 12:28:39 -0700660
Chia-I Wuf8693382015-04-16 22:02:10 +0800661void TestFrameworkVkPresent::CreateSwapChain()
Tony Barbour96db8822015-02-25 12:28:39 -0700662{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600663 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700664
Tony-LunarG399dfca2015-05-19 14:08:26 -0600665 m_display_image = m_images.begin();
666 m_current_buffer = 0;
667
Chia-I Wuf8693382015-04-16 22:02:10 +0800668 VkSwapChainCreateInfoWSI swap_chain = {};
669 swap_chain.sType = VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI;
670 swap_chain.pNativeWindowSystemHandle = (void *) m_connection;
671 swap_chain.pNativeWindowHandle = (void *) (intptr_t) m_window;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600672 swap_chain.imageCount = 2;
Chia-I Wuf8693382015-04-16 22:02:10 +0800673 swap_chain.imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
674 swap_chain.imageExtent.width = m_width;
675 swap_chain.imageExtent.height = m_height;
676 swap_chain.imageArraySize = 1;
Cody Northrope2baad22015-06-09 15:56:56 -0600677 // Note: Addition of color attachment is a workaround needed for some implementations
678 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT |
679 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
Chia-I Wuf8693382015-04-16 22:02:10 +0800680 swap_chain.swapModeFlags = VK_SWAP_MODE_FLIP_BIT_WSI |
681 VK_SWAP_MODE_BLIT_BIT_WSI;
682
Chia-I Wuf368b602015-07-03 10:41:20 +0800683 err = m_fpCreateSwapChainWSI(m_device.handle(), &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