blob: ed2706aeccbd09c7357d8aaacbce26734833f54d [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
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600371 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, VK_IMAGE_TILING_LINEAR, reqs);
372 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600373
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600374 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600375 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600376 };
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600377
Tony Barbour59a47322015-06-24 16:06:58 -0600378 err = vkGetImageSubresourceLayout(displayImage.device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600379 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600380
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600381 err = displayImage.MapMemory( (void **) &ptr );
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600382 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600383
384 ptr += sr_layout.offset;
385
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600386 record.m_title.append(comment);
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600387 record.m_width = displayImage.width();
388 record.m_height = displayImage.height();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600389 // TODO: Need to make this more robust to handle different image formats
Tony-LunarG399dfca2015-05-19 14:08:26 -0600390 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600391 record.m_data = malloc(record.m_data_size);
392 memcpy(record.m_data, ptr, record.m_data_size);
393 m_images.push_back(record);
394 m_display_image = --m_images.end();
395
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600396 err = displayImage.UnmapMemory();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600397 ASSERT_VK_SUCCESS( err );
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;
464 buf.init(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
465 dest_ptr = buf.map();
466 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
467 buf.unmap();
468
469 m_cmdbuf.begin();
470
471 VkBufferImageCopy region = {};
472 region.imageExtent.height = m_display_image->m_height;
473 region.imageExtent.width = m_display_image->m_width;
474 region.imageExtent.depth = 1;
475
476 vkCmdCopyBufferToImage(m_cmdbuf.obj(),
477 buf.obj(),
478 m_persistent_images[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
479 1, &region);
480 m_cmdbuf.end();
481
482 VkCmdBuffer cmdBufs[1];
483 cmdBufs[0] = m_cmdbuf.obj();
484
485 vkQueueSubmit(m_queue.obj(), 1, cmdBufs, NULL);
486 m_queue.wait();
Tony 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
504 err = m_fpQueuePresentWSI(m_queue.obj(), &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;
677 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT;
678 swap_chain.swapModeFlags = VK_SWAP_MODE_FLIP_BIT_WSI |
679 VK_SWAP_MODE_BLIT_BIT_WSI;
680
Jon Ashburn07daee72015-05-21 18:13:33 -0600681 err = m_fpCreateSwapChainWSI(m_device.obj(), &swap_chain, &m_swap_chain);
Chia-I Wuf8693382015-04-16 22:02:10 +0800682 assert(!err);
683
Tony-LunarG399dfca2015-05-19 14:08:26 -0600684 VkSwapChainImageInfoWSI infos[2];
Courtney Goeltzenleuchter763cc7a2015-06-24 15:02:51 -0600685 size_t size = sizeof(VkSwapChainImageInfoWSI) * m_images.size() * 2;
Jon Ashburn07daee72015-05-21 18:13:33 -0600686 std::vector<VkSwapChainImageInfoWSI> persistent_images;
687 persistent_images.resize(m_images.size());
688 err = m_fpGetSwapChainInfoWSI(m_swap_chain,
Chia-I Wuf8693382015-04-16 22:02:10 +0800689 VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600690 &size, &infos);
691 assert(!err && size == sizeof(VkSwapChainImageInfoWSI) * 2);
692 m_persistent_images.push_back(infos[0]);
693 m_persistent_images.push_back(infos[1]);
Tony Barbour96db8822015-02-25 12:28:39 -0700694}
695
Jon Ashburn07daee72015-05-21 18:13:33 -0600696void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -0700697{
Jon Ashburn07daee72015-05-21 18:13:33 -0600698 m_fpCreateSwapChainWSI = (PFN_vkCreateSwapChainWSI) vkGetInstanceProcAddr(inst, "vkCreateSwapChainWSI");
699 ASSERT_TRUE(m_fpCreateSwapChainWSI != NULL) << "vkGetInstanceProcAddr failed to find vkCreateSwapChainWSI";
700
701 m_fpDestroySwapChainWSI = (PFN_vkDestroySwapChainWSI) vkGetInstanceProcAddr(inst, "vkDestroySwapChainWSI");
702 ASSERT_TRUE(m_fpDestroySwapChainWSI != NULL) << "vkGetInstanceProcAddr failed to find vkDestroySwapChainWSI";
703
704 m_fpGetSwapChainInfoWSI = (PFN_vkGetSwapChainInfoWSI) vkGetInstanceProcAddr(inst, "vkGetSwapChainInfoWSI");
705 ASSERT_TRUE(m_fpGetSwapChainInfoWSI != NULL) << "vkGetInstanceProcAddr failed to find vkGetSwapChainInfoWSI";
706
707 m_fpQueuePresentWSI = (PFN_vkQueuePresentWSI) vkGetInstanceProcAddr(inst, "vkQueuePresentWSI");
708 ASSERT_TRUE(m_fpQueuePresentWSI != NULL) << "vkGetInstanceProcAddr failed to find vkQueuePresentWSI";
709
Tony Barbour96db8822015-02-25 12:28:39 -0700710 m_images = imagesIn;
711}
712
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600713#ifdef _WIN32
714void TestFrameworkVkPresent::CreateMyWindow()
715{
716 WNDCLASSEX win_class;
717 // const ::testing::TestInfo* const test_info =
718 // ::testing::UnitTest::GetInstance()->current_test_info();
719 m_connection = GetModuleHandle(NULL);
720
721 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
722 it != m_images.end(); it++) {
723 if (m_width < it->m_width)
724 m_width = it->m_width;
725 if (m_height < it->m_height)
726 m_height = it->m_height;
727 }
728 // Initialize the window class structure:
729 win_class.cbSize = sizeof(WNDCLASSEX);
730 win_class.style = CS_HREDRAW | CS_VREDRAW;
731 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
732 win_class.cbClsExtra = 0;
733 win_class.cbWndExtra = 0;
734 win_class.hInstance = m_connection; // hInstance
735 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
736 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
737 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
738 win_class.lpszMenuName = NULL;
739 win_class.lpszClassName = "Test";
740 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
741 // Register window class:
742 if (!RegisterClassEx(&win_class)) {
743 // It didn't work, so try to give a useful error:
744 printf("Unexpected error trying to start the application!\n");
745 fflush(stdout);
746 exit(1);
747 }
748 // Create window with the registered class:
749 m_window = CreateWindowEx(0,
750 "Test", // class name
751 "Test", // app name
752 WS_OVERLAPPEDWINDOW | // window style
753 WS_VISIBLE |
754 WS_SYSMENU,
755 100,100, // x/y coords
756 m_width, // width
757 m_height, // height
758 NULL, // handle to parent
759 NULL, // handle to menu
760 m_connection, // hInstance
761 NULL); // no extra parameters
762
763 if (!m_window) {
764 // It didn't work, so try to give a useful error:
765 DWORD error = GetLastError();
766 char message[120];
767 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
768 MessageBox(NULL, message, "Error", MB_OK);
769 exit(1);
770 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600771 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
772 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600773}
774#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600775void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -0700776{
Chia-I Wuf8693382015-04-16 22:02:10 +0800777 const xcb_setup_t *setup;
778 xcb_screen_iterator_t iter;
779 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -0700780 uint32_t value_mask, value_list[32];
781
Chia-I Wuf8693382015-04-16 22:02:10 +0800782 m_connection = xcb_connect(NULL, &scr);
783
784 setup = xcb_get_setup(m_connection);
785 iter = xcb_setup_roots_iterator(setup);
786 while (scr-- > 0)
787 xcb_screen_next(&iter);
788
789 m_screen = iter.data;
790
791 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
792 it != m_images.end(); it++) {
793 if (m_width < it->m_width)
794 m_width = it->m_width;
795 if (m_height < it->m_height)
796 m_height = it->m_height;
797 }
798
799 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700800
801 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +0800802 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -0700803 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
804 XCB_EVENT_MASK_EXPOSURE |
805 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
806
Chia-I Wuf8693382015-04-16 22:02:10 +0800807 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700808 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800809 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -0700810 0, 0, m_width, m_height, 0,
811 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800812 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -0700813 value_mask, value_list);
814
815 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +0800816 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -0700817 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +0800818 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -0700819
Chia-I Wuf8693382015-04-16 22:02:10 +0800820 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
821 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -0700822
Chia-I Wuf8693382015-04-16 22:02:10 +0800823 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -0700824 m_window, (*reply).atom, 4, 32, 1,
825 &(*m_atom_wm_delete_window).atom);
826 free(reply);
827
Chia-I Wuf8693382015-04-16 22:02:10 +0800828 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -0700829}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600830#endif
Tony Barbour96db8822015-02-25 12:28:39 -0700831
Tony Barbour6918cd52015-04-09 12:58:51 -0600832void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -0700833{
Jon Ashburn07daee72015-05-21 18:13:33 -0600834 m_fpDestroySwapChainWSI(m_swap_chain);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600835#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800836 xcb_destroy_window(m_connection, m_window);
837 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600838#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600839}
840
Tony Barbour6918cd52015-04-09 12:58:51 -0600841void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600842{
843 if (m_images.size() == 0) return;
844
Chia-I Wuf8693382015-04-16 22:02:10 +0800845 vk_testing::Environment env;
846 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -0700847 {
Chia-I Wuf8693382015-04-16 22:02:10 +0800848 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -0700849
Jon Ashburn07daee72015-05-21 18:13:33 -0600850 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600851 vkPresent.CreateMyWindow();
Chia-I Wuf8693382015-04-16 22:02:10 +0800852 vkPresent.CreateSwapChain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600853 vkPresent.Run();
854 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -0700855 }
Chia-I Wuf8693382015-04-16 22:02:10 +0800856 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600857}
858
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600859//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600860// These are the default resources for TBuiltInResources, used for both
861// - parsing this string for the case where the user didn't supply one
862// - dumping out a template for user construction of a config file
863//
864static const char* DefaultConfig =
865 "MaxLights 32\n"
866 "MaxClipPlanes 6\n"
867 "MaxTextureUnits 32\n"
868 "MaxTextureCoords 32\n"
869 "MaxVertexAttribs 64\n"
870 "MaxVertexUniformComponents 4096\n"
871 "MaxVaryingFloats 64\n"
872 "MaxVertexTextureImageUnits 32\n"
873 "MaxCombinedTextureImageUnits 80\n"
874 "MaxTextureImageUnits 32\n"
875 "MaxFragmentUniformComponents 4096\n"
876 "MaxDrawBuffers 32\n"
877 "MaxVertexUniformVectors 128\n"
878 "MaxVaryingVectors 8\n"
879 "MaxFragmentUniformVectors 16\n"
880 "MaxVertexOutputVectors 16\n"
881 "MaxFragmentInputVectors 15\n"
882 "MinProgramTexelOffset -8\n"
883 "MaxProgramTexelOffset 7\n"
884 "MaxClipDistances 8\n"
885 "MaxComputeWorkGroupCountX 65535\n"
886 "MaxComputeWorkGroupCountY 65535\n"
887 "MaxComputeWorkGroupCountZ 65535\n"
888 "MaxComputeWorkGroupSizeX 1024\n"
889 "MaxComputeWorkGroupSizeY 1024\n"
890 "MaxComputeWorkGroupSizeZ 64\n"
891 "MaxComputeUniformComponents 1024\n"
892 "MaxComputeTextureImageUnits 16\n"
893 "MaxComputeImageUniforms 8\n"
894 "MaxComputeAtomicCounters 8\n"
895 "MaxComputeAtomicCounterBuffers 1\n"
896 "MaxVaryingComponents 60\n"
897 "MaxVertexOutputComponents 64\n"
898 "MaxGeometryInputComponents 64\n"
899 "MaxGeometryOutputComponents 128\n"
900 "MaxFragmentInputComponents 128\n"
901 "MaxImageUnits 8\n"
902 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
903 "MaxCombinedShaderOutputResources 8\n"
904 "MaxImageSamples 0\n"
905 "MaxVertexImageUniforms 0\n"
906 "MaxTessControlImageUniforms 0\n"
907 "MaxTessEvaluationImageUniforms 0\n"
908 "MaxGeometryImageUniforms 0\n"
909 "MaxFragmentImageUniforms 8\n"
910 "MaxCombinedImageUniforms 8\n"
911 "MaxGeometryTextureImageUnits 16\n"
912 "MaxGeometryOutputVertices 256\n"
913 "MaxGeometryTotalOutputComponents 1024\n"
914 "MaxGeometryUniformComponents 1024\n"
915 "MaxGeometryVaryingComponents 64\n"
916 "MaxTessControlInputComponents 128\n"
917 "MaxTessControlOutputComponents 128\n"
918 "MaxTessControlTextureImageUnits 16\n"
919 "MaxTessControlUniformComponents 1024\n"
920 "MaxTessControlTotalOutputComponents 4096\n"
921 "MaxTessEvaluationInputComponents 128\n"
922 "MaxTessEvaluationOutputComponents 128\n"
923 "MaxTessEvaluationTextureImageUnits 16\n"
924 "MaxTessEvaluationUniformComponents 1024\n"
925 "MaxTessPatchComponents 120\n"
926 "MaxPatchVertices 32\n"
927 "MaxTessGenLevel 64\n"
928 "MaxViewports 16\n"
929 "MaxVertexAtomicCounters 0\n"
930 "MaxTessControlAtomicCounters 0\n"
931 "MaxTessEvaluationAtomicCounters 0\n"
932 "MaxGeometryAtomicCounters 0\n"
933 "MaxFragmentAtomicCounters 8\n"
934 "MaxCombinedAtomicCounters 8\n"
935 "MaxAtomicCounterBindings 1\n"
936 "MaxVertexAtomicCounterBuffers 0\n"
937 "MaxTessControlAtomicCounterBuffers 0\n"
938 "MaxTessEvaluationAtomicCounterBuffers 0\n"
939 "MaxGeometryAtomicCounterBuffers 0\n"
940 "MaxFragmentAtomicCounterBuffers 1\n"
941 "MaxCombinedAtomicCounterBuffers 1\n"
942 "MaxAtomicCounterBufferSize 16384\n"
943 "MaxTransformFeedbackBuffers 4\n"
944 "MaxTransformFeedbackInterleavedComponents 64\n"
945 "MaxCullDistances 8\n"
946 "MaxCombinedClipAndCullDistances 8\n"
947 "MaxSamples 4\n"
948
949 "nonInductiveForLoops 1\n"
950 "whileLoops 1\n"
951 "doWhileLoops 1\n"
952 "generalUniformIndexing 1\n"
953 "generalAttributeMatrixVectorIndexing 1\n"
954 "generalVaryingIndexing 1\n"
955 "generalSamplerIndexing 1\n"
956 "generalVariableIndexing 1\n"
957 "generalConstantMatrixVectorIndexing 1\n"
958 ;
959
960//
961// *.conf => this is a config file that can set limits/resources
962//
Tony Barbour6918cd52015-04-09 12:58:51 -0600963bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600964{
965 if (name.size() < 5)
966 return false;
967
968 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
969 ConfigFile = name;
970 return true;
971 }
972
973 return false;
974}
975
976//
977// Parse either a .conf file provided by the user or the default string above.
978//
Tony Barbour6918cd52015-04-09 12:58:51 -0600979void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600980{
981 char** configStrings = 0;
982 char* config = 0;
983 if (ConfigFile.size() > 0) {
984 configStrings = ReadFileData(ConfigFile.c_str());
985 if (configStrings)
986 config = *configStrings;
987 else {
988 printf("Error opening configuration file; will instead use the default configuration\n");
989 }
990 }
991
992 if (config == 0) {
993 config = new char[strlen(DefaultConfig) + 1];
994 strcpy(config, DefaultConfig);
995 }
996
997 const char* delims = " \t\n\r";
998 const char* token = strtok(config, delims);
999 while (token) {
1000 const char* valueStr = strtok(0, delims);
1001 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1002 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1003 return;
1004 }
1005 int value = atoi(valueStr);
1006
1007 if (strcmp(token, "MaxLights") == 0)
1008 Resources.maxLights = value;
1009 else if (strcmp(token, "MaxClipPlanes") == 0)
1010 Resources.maxClipPlanes = value;
1011 else if (strcmp(token, "MaxTextureUnits") == 0)
1012 Resources.maxTextureUnits = value;
1013 else if (strcmp(token, "MaxTextureCoords") == 0)
1014 Resources.maxTextureCoords = value;
1015 else if (strcmp(token, "MaxVertexAttribs") == 0)
1016 Resources.maxVertexAttribs = value;
1017 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1018 Resources.maxVertexUniformComponents = value;
1019 else if (strcmp(token, "MaxVaryingFloats") == 0)
1020 Resources.maxVaryingFloats = value;
1021 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1022 Resources.maxVertexTextureImageUnits = value;
1023 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1024 Resources.maxCombinedTextureImageUnits = value;
1025 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1026 Resources.maxTextureImageUnits = value;
1027 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1028 Resources.maxFragmentUniformComponents = value;
1029 else if (strcmp(token, "MaxDrawBuffers") == 0)
1030 Resources.maxDrawBuffers = value;
1031 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1032 Resources.maxVertexUniformVectors = value;
1033 else if (strcmp(token, "MaxVaryingVectors") == 0)
1034 Resources.maxVaryingVectors = value;
1035 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1036 Resources.maxFragmentUniformVectors = value;
1037 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1038 Resources.maxVertexOutputVectors = value;
1039 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1040 Resources.maxFragmentInputVectors = value;
1041 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1042 Resources.minProgramTexelOffset = value;
1043 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1044 Resources.maxProgramTexelOffset = value;
1045 else if (strcmp(token, "MaxClipDistances") == 0)
1046 Resources.maxClipDistances = value;
1047 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1048 Resources.maxComputeWorkGroupCountX = value;
1049 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1050 Resources.maxComputeWorkGroupCountY = value;
1051 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1052 Resources.maxComputeWorkGroupCountZ = value;
1053 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1054 Resources.maxComputeWorkGroupSizeX = value;
1055 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1056 Resources.maxComputeWorkGroupSizeY = value;
1057 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1058 Resources.maxComputeWorkGroupSizeZ = value;
1059 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1060 Resources.maxComputeUniformComponents = value;
1061 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1062 Resources.maxComputeTextureImageUnits = value;
1063 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1064 Resources.maxComputeImageUniforms = value;
1065 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1066 Resources.maxComputeAtomicCounters = value;
1067 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1068 Resources.maxComputeAtomicCounterBuffers = value;
1069 else if (strcmp(token, "MaxVaryingComponents") == 0)
1070 Resources.maxVaryingComponents = value;
1071 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1072 Resources.maxVertexOutputComponents = value;
1073 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1074 Resources.maxGeometryInputComponents = value;
1075 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1076 Resources.maxGeometryOutputComponents = value;
1077 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1078 Resources.maxFragmentInputComponents = value;
1079 else if (strcmp(token, "MaxImageUnits") == 0)
1080 Resources.maxImageUnits = value;
1081 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1082 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1083 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1084 Resources.maxCombinedShaderOutputResources = value;
1085 else if (strcmp(token, "MaxImageSamples") == 0)
1086 Resources.maxImageSamples = value;
1087 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1088 Resources.maxVertexImageUniforms = value;
1089 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1090 Resources.maxTessControlImageUniforms = value;
1091 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1092 Resources.maxTessEvaluationImageUniforms = value;
1093 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1094 Resources.maxGeometryImageUniforms = value;
1095 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1096 Resources.maxFragmentImageUniforms = value;
1097 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1098 Resources.maxCombinedImageUniforms = value;
1099 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1100 Resources.maxGeometryTextureImageUnits = value;
1101 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1102 Resources.maxGeometryOutputVertices = value;
1103 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1104 Resources.maxGeometryTotalOutputComponents = value;
1105 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1106 Resources.maxGeometryUniformComponents = value;
1107 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1108 Resources.maxGeometryVaryingComponents = value;
1109 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1110 Resources.maxTessControlInputComponents = value;
1111 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1112 Resources.maxTessControlOutputComponents = value;
1113 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1114 Resources.maxTessControlTextureImageUnits = value;
1115 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1116 Resources.maxTessControlUniformComponents = value;
1117 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1118 Resources.maxTessControlTotalOutputComponents = value;
1119 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1120 Resources.maxTessEvaluationInputComponents = value;
1121 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1122 Resources.maxTessEvaluationOutputComponents = value;
1123 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1124 Resources.maxTessEvaluationTextureImageUnits = value;
1125 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1126 Resources.maxTessEvaluationUniformComponents = value;
1127 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1128 Resources.maxTessPatchComponents = value;
1129 else if (strcmp(token, "MaxPatchVertices") == 0)
1130 Resources.maxPatchVertices = value;
1131 else if (strcmp(token, "MaxTessGenLevel") == 0)
1132 Resources.maxTessGenLevel = value;
1133 else if (strcmp(token, "MaxViewports") == 0)
1134 Resources.maxViewports = value;
1135 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1136 Resources.maxVertexAtomicCounters = value;
1137 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1138 Resources.maxTessControlAtomicCounters = value;
1139 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1140 Resources.maxTessEvaluationAtomicCounters = value;
1141 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1142 Resources.maxGeometryAtomicCounters = value;
1143 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1144 Resources.maxFragmentAtomicCounters = value;
1145 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1146 Resources.maxCombinedAtomicCounters = value;
1147 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1148 Resources.maxAtomicCounterBindings = value;
1149 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1150 Resources.maxVertexAtomicCounterBuffers = value;
1151 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1152 Resources.maxTessControlAtomicCounterBuffers = value;
1153 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1154 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1155 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1156 Resources.maxGeometryAtomicCounterBuffers = value;
1157 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1158 Resources.maxFragmentAtomicCounterBuffers = value;
1159 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1160 Resources.maxCombinedAtomicCounterBuffers = value;
1161 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1162 Resources.maxAtomicCounterBufferSize = value;
1163 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1164 Resources.maxTransformFeedbackBuffers = value;
1165 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1166 Resources.maxTransformFeedbackInterleavedComponents = value;
1167 else if (strcmp(token, "MaxCullDistances") == 0)
1168 Resources.maxCullDistances = value;
1169 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1170 Resources.maxCombinedClipAndCullDistances = value;
1171 else if (strcmp(token, "MaxSamples") == 0)
1172 Resources.maxSamples = value;
1173
1174 else if (strcmp(token, "nonInductiveForLoops") == 0)
1175 Resources.limits.nonInductiveForLoops = (value != 0);
1176 else if (strcmp(token, "whileLoops") == 0)
1177 Resources.limits.whileLoops = (value != 0);
1178 else if (strcmp(token, "doWhileLoops") == 0)
1179 Resources.limits.doWhileLoops = (value != 0);
1180 else if (strcmp(token, "generalUniformIndexing") == 0)
1181 Resources.limits.generalUniformIndexing = (value != 0);
1182 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1183 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1184 else if (strcmp(token, "generalVaryingIndexing") == 0)
1185 Resources.limits.generalVaryingIndexing = (value != 0);
1186 else if (strcmp(token, "generalSamplerIndexing") == 0)
1187 Resources.limits.generalSamplerIndexing = (value != 0);
1188 else if (strcmp(token, "generalVariableIndexing") == 0)
1189 Resources.limits.generalVariableIndexing = (value != 0);
1190 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1191 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1192 else
1193 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1194
1195 token = strtok(0, delims);
1196 }
1197 if (configStrings)
1198 FreeFileData(configStrings);
1199}
1200
Tony Barbour6918cd52015-04-09 12:58:51 -06001201void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001202{
1203 if (m_compile_options & EOptionRelaxedErrors)
1204 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1205 if (m_compile_options & EOptionIntermediate)
1206 messages = (EShMessages)(messages | EShMsgAST);
1207 if (m_compile_options & EOptionSuppressWarnings)
1208 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1209}
1210
1211//
1212// Malloc a string of sufficient size and read a string into it.
1213//
Tony Barbour6918cd52015-04-09 12:58:51 -06001214char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001215{
1216 FILE *in;
1217 #if defined(_WIN32) && defined(__GNUC__)
1218 in = fopen(fileName, "r");
1219 int errorCode = in ? 0 : 1;
1220 #else
1221 int errorCode = fopen_s(&in, fileName, "r");
1222 #endif
1223
1224 char *fdata;
1225 int count = 0;
1226 const int maxSourceStrings = 5;
1227 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1228
1229 if (errorCode) {
1230 printf("Error: unable to open input file: %s\n", fileName);
1231 return 0;
1232 }
1233
1234 while (fgetc(in) != EOF)
1235 count++;
1236
1237 fseek(in, 0, SEEK_SET);
1238
1239 if (!(fdata = (char*)malloc(count+2))) {
1240 printf("Error allocating memory\n");
1241 return 0;
1242 }
1243 if (fread(fdata,1,count, in)!=count) {
1244 printf("Error reading input file: %s\n", fileName);
1245 return 0;
1246 }
1247 fdata[count] = '\0';
1248 fclose(in);
1249 if (count == 0) {
1250 return_data[0]=(char*)malloc(count+2);
1251 return_data[0][0]='\0';
1252 m_num_shader_strings = 0;
1253 return return_data;
1254 } else
1255 m_num_shader_strings = 1;
1256
1257 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1258 int ptr_len=0,i=0;
1259 while(count>0){
1260 return_data[i]=(char*)malloc(len+2);
1261 memcpy(return_data[i],fdata+ptr_len,len);
1262 return_data[i][len]='\0';
1263 count-=(len);
1264 ptr_len+=(len);
1265 if(count<len){
1266 if(count==0){
1267 m_num_shader_strings=(i+1);
1268 break;
1269 }
1270 len = count;
1271 }
1272 ++i;
1273 }
1274 return return_data;
1275}
1276
Tony Barbour6918cd52015-04-09 12:58:51 -06001277void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001278{
1279 for(int i=0;i<m_num_shader_strings;i++)
1280 free(data[i]);
1281}
1282
1283//
1284// Deduce the language from the filename. Files must end in one of the
1285// following extensions:
1286//
1287// .vert = vertex
1288// .tesc = tessellation control
1289// .tese = tessellation evaluation
1290// .geom = geometry
1291// .frag = fragment
1292// .comp = compute
1293//
Tony Barbour6918cd52015-04-09 12:58:51 -06001294EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001295{
1296 size_t ext = name.rfind('.');
1297 if (ext == std::string::npos) {
1298 return EShLangVertex;
1299 }
1300
1301 std::string suffix = name.substr(ext + 1, std::string::npos);
1302 if (suffix == "vert")
1303 return EShLangVertex;
1304 else if (suffix == "tesc")
1305 return EShLangTessControl;
1306 else if (suffix == "tese")
1307 return EShLangTessEvaluation;
1308 else if (suffix == "geom")
1309 return EShLangGeometry;
1310 else if (suffix == "frag")
1311 return EShLangFragment;
1312 else if (suffix == "comp")
1313 return EShLangCompute;
1314
1315 return EShLangVertex;
1316}
1317
1318//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001319// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001320//
Tony Barbourd1c35722015-04-16 15:59:00 -06001321EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001322{
1323 switch (shader_type) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001324 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001325 return EShLangVertex;
1326
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001327 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001328 return EShLangTessControl;
1329
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001330 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001331 return EShLangTessEvaluation;
1332
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001333 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001334 return EShLangGeometry;
1335
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001336 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001337 return EShLangFragment;
1338
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001339 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001340 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001341
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001342 default:
1343 return EShLangVertex;
1344 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001345}
1346
1347
1348//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001349// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001350// Return value of false means an error was encountered.
1351//
Tony Barbourd1c35722015-04-16 15:59:00 -06001352bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001353 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001354 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001355{
1356 glslang::TProgram& program = *new glslang::TProgram;
1357 const char *shaderStrings[1];
1358
1359 // TODO: Do we want to load a special config file depending on the
1360 // shader source? Optional name maybe?
1361 // SetConfigFile(fileName);
1362
1363 ProcessConfigFile();
1364
1365 EShMessages messages = EShMsgDefault;
1366 SetMessageOptions(messages);
1367
1368 EShLanguage stage = FindLanguage(shader_type);
1369 glslang::TShader* shader = new glslang::TShader(stage);
1370
1371 shaderStrings[0] = pshader;
1372 shader->setStrings(shaderStrings, 1);
1373
1374 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1375
Cody Northrop195d6622014-11-03 12:54:37 -07001376 if (! (m_compile_options & EOptionSuppressInfolog)) {
1377 puts(shader->getInfoLog());
1378 puts(shader->getInfoDebugLog());
1379 }
1380
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001381 return false; // something didn't work
1382 }
1383
1384 program.addShader(shader);
1385
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001386
1387 //
1388 // Program-level processing...
1389 //
1390
Cody Northrop195d6622014-11-03 12:54:37 -07001391 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001392
Cody Northrop195d6622014-11-03 12:54:37 -07001393 if (! (m_compile_options & EOptionSuppressInfolog)) {
1394 puts(shader->getInfoLog());
1395 puts(shader->getInfoDebugLog());
1396 }
1397
1398 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001399 }
1400
1401 if (m_compile_options & EOptionDumpReflection) {
1402 program.buildReflection();
1403 program.dumpReflection();
1404 }
1405
Cody Northrop5a95b472015-06-03 13:01:54 -06001406 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1407
1408 //
1409 // Test the different modes of SPIR-V modification
1410 //
1411 if (this->m_canonicalize_spv) {
1412 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1413 }
1414
1415 if (this->m_strip_spv) {
1416 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1417 }
1418
1419 if (this->m_do_everything_spv) {
1420 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1421 }
1422
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001423
1424 return true;
1425}
1426
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001427
1428
Tony Barbour6918cd52015-04-09 12:58:51 -06001429VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001430 m_width( 0 ),
1431 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001432 m_data( NULL ),
1433 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001434{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001435}
1436
Tony Barbour6918cd52015-04-09 12:58:51 -06001437VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001438{
1439
1440}
1441
Tony Barbour6918cd52015-04-09 12:58:51 -06001442VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001443{
1444 m_title = copyin.m_title;
1445 m_width = copyin.m_width;
1446 m_height = copyin.m_height;
1447 m_data_size = copyin.m_data_size;
1448 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1449}
1450
Tony Barbour6918cd52015-04-09 12:58:51 -06001451ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001452{
Tony Barbour6918cd52015-04-09 12:58:51 -06001453 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1454 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001455 return output;
1456}
1457
Tony Barbour6918cd52015-04-09 12:58:51 -06001458VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001459{
1460 m_title = rhs.m_title;
1461 m_width = rhs.m_width;
1462 m_height = rhs.m_height;
1463 m_data_size = rhs.m_data_size;
1464 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001465 return *this;
1466}
1467
Tony Barbour6918cd52015-04-09 12:58:51 -06001468int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001469{
1470 if( this->m_data != rhs.m_data) return 0;
1471 return 1;
1472}
1473
1474// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001475int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001476{
1477 if( this->m_data_size < rhs.m_data_size ) return 1;
1478 return 0;
1479}
1480