blob: fb5ded6e7b79cf77bf12c64216c96ae738232c38 [file] [log] [blame]
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001// VK tests
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06002//
3// Copyright (C) 2014 LunarG, Inc.
4//
5// Permission is hereby granted, free of charge, to any person obtaining a
6// copy of this software and associated documentation files (the "Software"),
7// to deal in the Software without restriction, including without limitation
8// the rights to use, copy, modify, merge, publish, distribute, sublicense,
9// and/or sell copies of the Software, and to permit persons to whom the
10// Software is furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included
13// in all copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21// DEALINGS IN THE SOFTWARE.
22
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060023#include "vktestframework.h"
24#include "vkrenderframework.h"
Cody Northrop5a95b472015-06-03 13:01:54 -060025#include "SPIRV/GlslangToSpv.h"
26#include "SPIRV/SPVRemapper.h"
Tony Barbour4ab45422014-12-10 17:00:20 -070027#include <limits.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060028#include <math.h>
Chia-I Wuec664fa2014-12-02 11:54:24 +080029#include <wand/MagickWand.h>
Chia-I Wuf8693382015-04-16 22:02:10 +080030#include <xcb/xcb.h>
31#include <vk_wsi_lunarg.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060032
Tony Barbour3d69c9e2015-05-20 16:53:31 -060033#if defined(PATH_MAX) && !defined(MAX_PATH)
34#define MAX_PATH PATH_MAX
35#endif
36
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060037// Command-line options
38enum TOptions {
39 EOptionNone = 0x000,
40 EOptionIntermediate = 0x001,
41 EOptionSuppressInfolog = 0x002,
42 EOptionMemoryLeakMode = 0x004,
43 EOptionRelaxedErrors = 0x008,
44 EOptionGiveWarnings = 0x010,
45 EOptionLinkProgram = 0x020,
46 EOptionMultiThreaded = 0x040,
47 EOptionDumpConfig = 0x080,
48 EOptionDumpReflection = 0x100,
49 EOptionSuppressWarnings = 0x200,
50 EOptionDumpVersions = 0x400,
Cody Northrop3bfd27c2015-03-17 15:55:58 -060051 EOptionSpv = 0x800,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060052 EOptionDefaultDesktop = 0x1000,
53};
54
Chia-I Wuf8693382015-04-16 22:02:10 +080055class TestFrameworkVkPresent
56{
57public:
58 TestFrameworkVkPresent(vk_testing::Device &device);
59
60 void Run();
Jon Ashburn07daee72015-05-21 18:13:33 -060061 void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst);
Chia-I Wuf8693382015-04-16 22:02:10 +080062 void CreateMyWindow();
63 void CreateSwapChain();
64 void TearDown();
Tony Barbour3d69c9e2015-05-20 16:53:31 -060065#ifdef _WIN32
66 static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
67#endif
68
Chia-I Wuf8693382015-04-16 22:02:10 +080069
70protected:
71 vk_testing::Device &m_device;
72 vk_testing::Queue &m_queue;
73 vk_testing::CmdBuffer m_cmdbuf;
74
75private:
Tony Barbour3d69c9e2015-05-20 16:53:31 -060076#ifdef _WIN32
77 HINSTANCE m_connection; // hInstance - Windows Instance
78 HWND m_window; // hWnd - window handle
79
80#else
Chia-I Wuf8693382015-04-16 22:02:10 +080081 xcb_connection_t *m_connection;
82 xcb_screen_t *m_screen;
83 xcb_window_t m_window;
84 xcb_intern_atom_reply_t *m_atom_wm_delete_window;
Tony Barbour3d69c9e2015-05-20 16:53:31 -060085#endif
Courtney Goeltzenleuchterd6079ec2015-04-22 10:09:35 -060086 std::list<VkTestImageRecord> m_images;
Chia-I Wuf8693382015-04-16 22:02:10 +080087
Jon Ashburn07daee72015-05-21 18:13:33 -060088 PFN_vkCreateSwapChainWSI m_fpCreateSwapChainWSI;
89 PFN_vkDestroySwapChainWSI m_fpDestroySwapChainWSI;
90 PFN_vkGetSwapChainInfoWSI m_fpGetSwapChainInfoWSI;
91 PFN_vkQueuePresentWSI m_fpQueuePresentWSI;
92
Chia-I Wuf8693382015-04-16 22:02:10 +080093 VkSwapChainWSI m_swap_chain;
Tony-LunarG399dfca2015-05-19 14:08:26 -060094 std::vector<VkSwapChainImageInfoWSI> m_persistent_images;
95 int m_current_buffer;
Chia-I Wuf8693382015-04-16 22:02:10 +080096
97 bool m_quit;
98 bool m_pause;
99
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600100 int m_width;
101 int m_height;
Chia-I Wuf8693382015-04-16 22:02:10 +0800102
103 std::list<VkTestImageRecord>::iterator m_display_image;
104
105 void Display();
106 void HandleEvent(xcb_generic_event_t *event);
107};
108
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600109#ifndef _WIN32
110
111#include <errno.h>
112
113int fopen_s(
114 FILE** pFile,
115 const char* filename,
116 const char* mode
117)
118{
119 if (!pFile || !filename || !mode) {
120 return EINVAL;
121 }
122
123 FILE* f = fopen(filename, mode);
124 if (! f) {
125 if (errno != 0) {
126 return errno;
127 } else {
128 return ENOENT;
129 }
130 }
131 *pFile = f;
132
133 return 0;
134}
135
136#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600137
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600138
139
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600140// Set up environment for GLSL compiler
141// Must be done once per process
142void TestEnvironment::SetUp()
143{
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600144 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600145 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800146
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600147 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600148}
149
150void TestEnvironment::TearDown()
151{
152 glslang::FinalizeProcess();
153}
154
Tony Barbour6918cd52015-04-09 12:58:51 -0600155VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600156 m_compile_options( 0 ),
157 m_num_shader_strings( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600158{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600159
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600160}
161
Tony Barbour6918cd52015-04-09 12:58:51 -0600162VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600163{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600164
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600165}
166
167// Define all the static elements
Cody Northropa3673cf2015-06-09 13:00:45 -0600168bool VkTestFramework::m_show_images = false;
169bool VkTestFramework::m_save_images = false;
170bool VkTestFramework::m_compare_images = false;
171bool VkTestFramework::m_use_glsl = false;
172bool VkTestFramework::m_canonicalize_spv = false;
173bool VkTestFramework::m_strip_spv = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600174bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour6918cd52015-04-09 12:58:51 -0600175int VkTestFramework::m_width = 0;
176int VkTestFramework::m_height = 0;
177std::list<VkTestImageRecord> VkTestFramework::m_images;
178std::list<VkTestImageRecord>::iterator VkTestFramework::m_display_image;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600179int m_display_image_idx = 0;
180
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600181bool VkTestFramework::optionMatch(const char* option, char* optionLine)
182{
183 if (strncmp(option, optionLine, strlen(option)) == 0)
184 return true;
185 else
186 return false;
187}
188
Tony Barbour6918cd52015-04-09 12:58:51 -0600189void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600190{
191 int i, n;
192
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600193 for (i=1, n=1; i< *argc; i++) {
194 if (optionMatch("--show-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600195 m_show_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600196 else if (optionMatch("--save-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600197 m_save_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600198 else if (optionMatch("--no-SPV", argv[i]))
199 m_use_glsl = true;
200 else if (optionMatch("--strip-SPV", argv[i]))
201 m_strip_spv = true;
202 else if (optionMatch("--canonicalize-SPV", argv[i]))
203 m_canonicalize_spv = true;
204 else if (optionMatch("--compare-images", argv[i]))
Tony Barbour247bf372014-10-30 14:29:04 -0600205 m_compare_images = true;
Tony Barbour247bf372014-10-30 14:29:04 -0600206
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600207 else if (optionMatch("--help", argv[i]) ||
208 optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700209 printf("\nOther options:\n");
210 printf("\t--show-images\n"
211 "\t\tDisplay test images in viewer after tests complete.\n");
212 printf("\t--save-images\n"
213 "\t\tSave tests images as ppm files in current working directory.\n"
214 "\t\tUsed to generate golden images for compare-images.\n");
215 printf("\t--compare-images\n"
216 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barboura98d3932014-12-11 09:52:49 -0700217 "\t\tAlso saves the generated test image in current working\n"
218 "\t\t\tdirectory but only if the image is different from the golden\n"
219 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
220 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700221 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600222 printf("\t--no-SPV\n"
223 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600224 printf("\t--strip-SPV\n"
225 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
226 printf("\t--canonicalize-SPV\n"
227 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
228 exit(0);
229 } else {
230 printf("\nUnrecognized option: %s\n", argv[i]);
231 printf("\nUse --help or -h for option list.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700232 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700233 }
234
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600235 /*
236 * Since the above "consume" inputs, update argv
237 * so that it contains the trimmed list of args for glutInit
238 */
239
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600240 argv[n] = argv[i];
241 n++;
242 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600243}
244
Tony Barbour6918cd52015-04-09 12:58:51 -0600245void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600246{
247 string filename;
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600248 VkResult err;
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600249 uint32_t x, y;
Tony Barbour6918cd52015-04-09 12:58:51 -0600250 VkImageObj displayImage(image->device());
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600251 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbour84d448c2015-04-02 14:02:33 -0600252
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600253 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, VK_IMAGE_TILING_LINEAR, reqs);
Tony Barbour84d448c2015-04-02 14:02:33 -0600254 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600255
256 filename.append(basename);
257 filename.append(".ppm");
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600258
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600259 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600260 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600261 };
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600262 VkSubresourceLayout sr_layout;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600263
Tony Barbour59a47322015-06-24 16:06:58 -0600264 err = vkGetImageSubresourceLayout(image->device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600265 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600266
Tony Barbour84d448c2015-04-02 14:02:33 -0600267 char *ptr;
268 ptr = (char *) displayImage.map();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600269 ptr += sr_layout.offset;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600270 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600271 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
272
273 file << "P6\n";
Tony Barbour84d448c2015-04-02 14:02:33 -0600274 file << displayImage.width() << "\n";
275 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600276 file << 255 << "\n";
277
Tony Barbour84d448c2015-04-02 14:02:33 -0600278 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700279 const int *row = (const int *) ptr;
280 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600281
Tony Barbourd1c35722015-04-16 15:59:00 -0600282 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700283 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600284 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700285 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
286 file.write((char *) &swapped, 3);
287 row++;
288 }
289 }
Tony Barbourd1c35722015-04-16 15:59:00 -0600290 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700291 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600292 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700293 file.write((char *) row, 3);
294 row++;
295 }
296 }
297 else {
298 printf("Unrecognized image format - will not write image files");
299 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600300 }
301
302 ptr += sr_layout.rowPitch;
303 }
304
305 file.close();
Tony Barbour84d448c2015-04-02 14:02:33 -0600306 displayImage.unmap();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600307}
308
Tony Barbour6918cd52015-04-09 12:58:51 -0600309void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour247bf372014-10-30 14:29:04 -0600310{
311
312 MagickWand *magick_wand_1;
313 MagickWand *magick_wand_2;
314 MagickWand *compare_wand;
315 MagickBooleanType status;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600316 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600317 double differenz;
318
Tony Barbour4ab45422014-12-10 17:00:20 -0700319 if (getenv("RENDERTEST_GOLDEN_DIR"))
320 {
321 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
322 }
323
Tony Barbour247bf372014-10-30 14:29:04 -0600324 MagickWandGenesis();
325 magick_wand_1=NewMagickWand();
326 sprintf(testimage,"%s.ppm",basename);
327 status=MagickReadImage(magick_wand_1,testimage);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600328 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour247bf372014-10-30 14:29:04 -0600329
330
331 MagickWandGenesis();
332 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700333 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600334 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600335 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour247bf372014-10-30 14:29:04 -0600336
Tony Barbour247bf372014-10-30 14:29:04 -0600337 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
338 if (differenz != 0.0)
339 {
340 char difference[256];
341
342 sprintf(difference,"%s-diff.ppm",basename);
343 status = MagickWriteImage(compare_wand, difference);
344 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
345 }
346 DestroyMagickWand(compare_wand);
347
348 DestroyMagickWand(magick_wand_1);
349 DestroyMagickWand(magick_wand_2);
350 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700351
352 if (differenz == 0.0)
353 {
354 /*
355 * If test image and golden image match, we do not need to
356 * keep around the test image.
357 */
358 remove(testimage);
359 }
Tony Barbour247bf372014-10-30 14:29:04 -0600360}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600361
Tony Barbour6918cd52015-04-09 12:58:51 -0600362void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600363{
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600364 VkResult err;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600365 VkSubresourceLayout sr_layout;
366 char *ptr;
367 VkTestImageRecord record;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600368 VkImageObj displayImage(image->device());
369 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
370
Cody Northropc9a69912015-06-18 17:05:15 -0600371 displayImage.init(image->extent().width, image->extent().height, image->format(), VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT, VK_IMAGE_TILING_LINEAR, reqs);
372
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600373 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600374
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600375 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600376 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600377 };
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600378
Tony Barbour59a47322015-06-24 16:06:58 -0600379 err = vkGetImageSubresourceLayout(displayImage.device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600380 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600381
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600382 err = displayImage.MapMemory( (void **) &ptr );
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600383 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600384
385 ptr += sr_layout.offset;
386
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600387 record.m_title.append(comment);
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600388 record.m_width = displayImage.width();
389 record.m_height = displayImage.height();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600390 // TODO: Need to make this more robust to handle different image formats
Tony-LunarG399dfca2015-05-19 14:08:26 -0600391 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600392 record.m_data = malloc(record.m_data_size);
393 memcpy(record.m_data, ptr, record.m_data_size);
394 m_images.push_back(record);
395 m_display_image = --m_images.end();
396
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600397 err = displayImage.UnmapMemory();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600398 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600399}
400
Tony Barbour6918cd52015-04-09 12:58:51 -0600401void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600402{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600403 for (int32_t i = 0; i < images.size(); i++) {
404 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600405 }
406}
407
Tony Barbour6918cd52015-04-09 12:58:51 -0600408void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600409{
410 const ::testing::TestInfo* const test_info =
411 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600412 ostringstream filestream;
413 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600414
Tony Barbour247bf372014-10-30 14:29:04 -0600415 m_width = 40;
416
417 if (strcmp(test_info->name(), m_testName.c_str())) {
418 filestream << test_info->name();
419 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700420 m_frameNum = 2;
421 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600422 }
423 else {
424 filestream << test_info->name() << "-" << m_frameNum;
425 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700426 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600427 }
428
Tony Barbour247bf372014-10-30 14:29:04 -0600429 // ToDo - scrub string for bad characters
430
431 if (m_save_images || m_compare_images) {
432 WritePPM(filename.c_str(), image);
433 if (m_compare_images) {
434 Compare(filename.c_str(), image);
435 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600436 }
437
438 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600439 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600440 }
441}
442
Chia-I Wuf8693382015-04-16 22:02:10 +0800443TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
444 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700445 m_queue(*m_device.graphics_queues()[0]),
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600446 m_cmdbuf(m_device, vk_testing::CmdBuffer::create_info(m_device.graphics_queue_node_index_))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600447{
Tony Barbour96db8822015-02-25 12:28:39 -0700448 m_quit = false;
449 m_pause = false;
450 m_width = 0;
451 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600452}
453
Tony Barbour6918cd52015-04-09 12:58:51 -0600454void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600455{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600456 VkResult U_ASSERT_ONLY err;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600457 vk_testing::Buffer buf;
458 void *dest_ptr;
459
460 if (m_persistent_images.size() != 2) {
461 return;
462 }
463
464 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Cody Northrop7fb43862015-06-22 14:56:14 -0600465 buf.init_as_src(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
Tony-LunarG399dfca2015-05-19 14:08:26 -0600466 dest_ptr = buf.map();
467 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
468 buf.unmap();
469
470 m_cmdbuf.begin();
471
472 VkBufferImageCopy region = {};
473 region.imageExtent.height = m_display_image->m_height;
474 region.imageExtent.width = m_display_image->m_width;
475 region.imageExtent.depth = 1;
476
477 vkCmdCopyBufferToImage(m_cmdbuf.obj(),
478 buf.obj(),
479 m_persistent_images[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
480 1, &region);
481 m_cmdbuf.end();
482
483 VkCmdBuffer cmdBufs[1];
484 cmdBufs[0] = m_cmdbuf.obj();
485
486 vkQueueSubmit(m_queue.obj(), 1, cmdBufs, NULL);
487 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700488
Chia-I Wuf8693382015-04-16 22:02:10 +0800489 VkPresentInfoWSI present = {};
490 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_WSI;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600491 present.image = m_persistent_images[m_current_buffer].image;
Chia-I Wuf8693382015-04-16 22:02:10 +0800492 present.flipInterval = 1;
Tony Barbour96db8822015-02-25 12:28:39 -0700493
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600494#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800495 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700496 XCB_PROP_MODE_REPLACE,
497 m_window,
498 XCB_ATOM_WM_NAME,
499 XCB_ATOM_STRING,
500 8,
501 m_display_image->m_title.size(),
502 m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600503#endif
Jon Ashburn07daee72015-05-21 18:13:33 -0600504
505 err = m_fpQueuePresentWSI(m_queue.obj(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700506 assert(!err);
507
508 m_queue.wait();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600509 m_current_buffer = (m_current_buffer + 1) % 2;
Tony Barbour96db8822015-02-25 12:28:39 -0700510
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600511}
512
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600513#ifdef _WIN32
Tony-LunarG399dfca2015-05-19 14:08:26 -0600514# define PREVIOUSLY_DOWN 1<<29
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600515// MS-Windows event handling function:
516LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
517 UINT uMsg,
518 WPARAM wParam,
519 LPARAM lParam)
520{
521
522 switch(uMsg)
523 {
524 case WM_CLOSE:
525 PostQuitMessage(0);
526 break;
527
528 case WM_PAINT:
529 {
530 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
531 if (me) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600532 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600533 me->Display();
534 }
535 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600536 break;
537
538 case WM_KEYDOWN:
539 {
540 if (lParam & (PREVIOUSLY_DOWN)){
541 break;
542 }
543 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
544 // the window, we put the this pointer into the window's user data so we could get it back now
545 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
546 switch (wParam)
547 {
548 case VK_ESCAPE: me->m_quit = true;
549 break;
550
551 case VK_LEFT: // left arrow key
552 if (me->m_display_image == me->m_images.begin()) {
553 me->m_display_image = --me->m_images.end();
554 }
555 else {
556 --me->m_display_image;
557 }
558 break;
559
560 case VK_RIGHT: // right arrow key
561 ++me->m_display_image;
562 if (me->m_display_image == me->m_images.end()) {
563 me->m_display_image = me->m_images.begin();
564 }
565 break;
566
567 default:
568 break;
569 }
570 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
571 me->Display();
572 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600573 }
574 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
575}
576
577void TestFrameworkVkPresent::Run()
578{
579 MSG msg; // message
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600580
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600581 /* main message loop*/
Tony-LunarG399dfca2015-05-19 14:08:26 -0600582 while(! m_quit) {
583 GetMessage(&msg, m_window, 0, 0);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600584 if (msg.message == WM_QUIT) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600585 m_quit = true; //if found, quit app
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600586 } else {
587 /* Translate and dispatch to event queue*/
588 TranslateMessage(&msg);
589 DispatchMessage(&msg);
590 }
591 }
592}
593
594#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600595void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600596{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600597 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700598 switch (event_code) {
599 case XCB_EXPOSE:
600 Display(); // TODO: handle resize
601 break;
602 case XCB_CLIENT_MESSAGE:
603 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
604 (m_atom_wm_delete_window)->atom) {
605 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600606 }
607 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700608 case XCB_KEY_RELEASE:
609 {
610 const xcb_key_release_event_t *key =
611 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600612
Tony Barbour96db8822015-02-25 12:28:39 -0700613 switch (key->detail) {
614 case 0x9: // Escape
615 m_quit = true;
616 break;
617 case 0x71: // left arrow key
618 if (m_display_image == m_images.begin()) {
619 m_display_image = --m_images.end();
620 } else {
621 --m_display_image;
622 }
623 break;
624 case 0x72: // right arrow key
625 ++m_display_image;
626 if (m_display_image == m_images.end()) {
627 m_display_image = m_images.begin();
628 }
629 break;
630 case 0x41:
631 m_pause = !m_pause;
632 break;
633 }
634 Display();
635 }
636 break;
637 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600638 break;
639 }
Tony Barbour96db8822015-02-25 12:28:39 -0700640}
641
Tony Barbour6918cd52015-04-09 12:58:51 -0600642void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700643{
Chia-I Wuf8693382015-04-16 22:02:10 +0800644 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700645
646 while (! m_quit) {
647 xcb_generic_event_t *event;
648
649 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800650 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700651 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800652 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700653 }
654 if (event) {
655 HandleEvent(event);
656 free(event);
657 }
658 }
659}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600660#endif // _WIN32
Tony Barbour96db8822015-02-25 12:28:39 -0700661
Chia-I Wuf8693382015-04-16 22:02:10 +0800662void TestFrameworkVkPresent::CreateSwapChain()
Tony Barbour96db8822015-02-25 12:28:39 -0700663{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600664 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700665
Tony-LunarG399dfca2015-05-19 14:08:26 -0600666 m_display_image = m_images.begin();
667 m_current_buffer = 0;
668
Chia-I Wuf8693382015-04-16 22:02:10 +0800669 VkSwapChainCreateInfoWSI swap_chain = {};
670 swap_chain.sType = VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI;
671 swap_chain.pNativeWindowSystemHandle = (void *) m_connection;
672 swap_chain.pNativeWindowHandle = (void *) (intptr_t) m_window;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600673 swap_chain.imageCount = 2;
Chia-I Wuf8693382015-04-16 22:02:10 +0800674 swap_chain.imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
675 swap_chain.imageExtent.width = m_width;
676 swap_chain.imageExtent.height = m_height;
677 swap_chain.imageArraySize = 1;
Cody Northrope2baad22015-06-09 15:56:56 -0600678 // Note: Addition of color attachment is a workaround needed for some implementations
679 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT |
680 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
Chia-I Wuf8693382015-04-16 22:02:10 +0800681 swap_chain.swapModeFlags = VK_SWAP_MODE_FLIP_BIT_WSI |
682 VK_SWAP_MODE_BLIT_BIT_WSI;
683
Jon Ashburn07daee72015-05-21 18:13:33 -0600684 err = m_fpCreateSwapChainWSI(m_device.obj(), &swap_chain, &m_swap_chain);
Chia-I Wuf8693382015-04-16 22:02:10 +0800685 assert(!err);
686
Tony-LunarG399dfca2015-05-19 14:08:26 -0600687 VkSwapChainImageInfoWSI infos[2];
Courtney Goeltzenleuchter763cc7a2015-06-24 15:02:51 -0600688 size_t size = sizeof(VkSwapChainImageInfoWSI) * m_images.size() * 2;
Jon Ashburn07daee72015-05-21 18:13:33 -0600689 std::vector<VkSwapChainImageInfoWSI> persistent_images;
690 persistent_images.resize(m_images.size());
691 err = m_fpGetSwapChainInfoWSI(m_swap_chain,
Chia-I Wuf8693382015-04-16 22:02:10 +0800692 VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600693 &size, &infos);
694 assert(!err && size == sizeof(VkSwapChainImageInfoWSI) * 2);
695 m_persistent_images.push_back(infos[0]);
696 m_persistent_images.push_back(infos[1]);
Tony Barbour96db8822015-02-25 12:28:39 -0700697}
698
Jon Ashburn07daee72015-05-21 18:13:33 -0600699void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbour96db8822015-02-25 12:28:39 -0700700{
Jon Ashburn07daee72015-05-21 18:13:33 -0600701 m_fpCreateSwapChainWSI = (PFN_vkCreateSwapChainWSI) vkGetInstanceProcAddr(inst, "vkCreateSwapChainWSI");
702 ASSERT_TRUE(m_fpCreateSwapChainWSI != NULL) << "vkGetInstanceProcAddr failed to find vkCreateSwapChainWSI";
703
704 m_fpDestroySwapChainWSI = (PFN_vkDestroySwapChainWSI) vkGetInstanceProcAddr(inst, "vkDestroySwapChainWSI");
705 ASSERT_TRUE(m_fpDestroySwapChainWSI != NULL) << "vkGetInstanceProcAddr failed to find vkDestroySwapChainWSI";
706
707 m_fpGetSwapChainInfoWSI = (PFN_vkGetSwapChainInfoWSI) vkGetInstanceProcAddr(inst, "vkGetSwapChainInfoWSI");
708 ASSERT_TRUE(m_fpGetSwapChainInfoWSI != NULL) << "vkGetInstanceProcAddr failed to find vkGetSwapChainInfoWSI";
709
710 m_fpQueuePresentWSI = (PFN_vkQueuePresentWSI) vkGetInstanceProcAddr(inst, "vkQueuePresentWSI");
711 ASSERT_TRUE(m_fpQueuePresentWSI != NULL) << "vkGetInstanceProcAddr failed to find vkQueuePresentWSI";
712
Tony Barbour96db8822015-02-25 12:28:39 -0700713 m_images = imagesIn;
714}
715
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600716#ifdef _WIN32
717void TestFrameworkVkPresent::CreateMyWindow()
718{
719 WNDCLASSEX win_class;
720 // const ::testing::TestInfo* const test_info =
721 // ::testing::UnitTest::GetInstance()->current_test_info();
722 m_connection = GetModuleHandle(NULL);
723
724 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
725 it != m_images.end(); it++) {
726 if (m_width < it->m_width)
727 m_width = it->m_width;
728 if (m_height < it->m_height)
729 m_height = it->m_height;
730 }
731 // Initialize the window class structure:
732 win_class.cbSize = sizeof(WNDCLASSEX);
733 win_class.style = CS_HREDRAW | CS_VREDRAW;
734 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
735 win_class.cbClsExtra = 0;
736 win_class.cbWndExtra = 0;
737 win_class.hInstance = m_connection; // hInstance
738 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
739 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
740 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
741 win_class.lpszMenuName = NULL;
742 win_class.lpszClassName = "Test";
743 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
744 // Register window class:
745 if (!RegisterClassEx(&win_class)) {
746 // It didn't work, so try to give a useful error:
747 printf("Unexpected error trying to start the application!\n");
748 fflush(stdout);
749 exit(1);
750 }
751 // Create window with the registered class:
752 m_window = CreateWindowEx(0,
753 "Test", // class name
754 "Test", // app name
755 WS_OVERLAPPEDWINDOW | // window style
756 WS_VISIBLE |
757 WS_SYSMENU,
758 100,100, // x/y coords
759 m_width, // width
760 m_height, // height
761 NULL, // handle to parent
762 NULL, // handle to menu
763 m_connection, // hInstance
764 NULL); // no extra parameters
765
766 if (!m_window) {
767 // It didn't work, so try to give a useful error:
768 DWORD error = GetLastError();
769 char message[120];
770 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
771 MessageBox(NULL, message, "Error", MB_OK);
772 exit(1);
773 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600774 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
775 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600776}
777#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600778void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -0700779{
Chia-I Wuf8693382015-04-16 22:02:10 +0800780 const xcb_setup_t *setup;
781 xcb_screen_iterator_t iter;
782 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -0700783 uint32_t value_mask, value_list[32];
784
Chia-I Wuf8693382015-04-16 22:02:10 +0800785 m_connection = xcb_connect(NULL, &scr);
786
787 setup = xcb_get_setup(m_connection);
788 iter = xcb_setup_roots_iterator(setup);
789 while (scr-- > 0)
790 xcb_screen_next(&iter);
791
792 m_screen = iter.data;
793
794 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
795 it != m_images.end(); it++) {
796 if (m_width < it->m_width)
797 m_width = it->m_width;
798 if (m_height < it->m_height)
799 m_height = it->m_height;
800 }
801
802 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700803
804 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +0800805 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -0700806 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
807 XCB_EVENT_MASK_EXPOSURE |
808 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
809
Chia-I Wuf8693382015-04-16 22:02:10 +0800810 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700811 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800812 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -0700813 0, 0, m_width, m_height, 0,
814 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800815 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -0700816 value_mask, value_list);
817
818 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +0800819 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -0700820 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +0800821 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -0700822
Chia-I Wuf8693382015-04-16 22:02:10 +0800823 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
824 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -0700825
Chia-I Wuf8693382015-04-16 22:02:10 +0800826 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -0700827 m_window, (*reply).atom, 4, 32, 1,
828 &(*m_atom_wm_delete_window).atom);
829 free(reply);
830
Chia-I Wuf8693382015-04-16 22:02:10 +0800831 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -0700832}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600833#endif
Tony Barbour96db8822015-02-25 12:28:39 -0700834
Tony Barbour6918cd52015-04-09 12:58:51 -0600835void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -0700836{
Jon Ashburn07daee72015-05-21 18:13:33 -0600837 m_fpDestroySwapChainWSI(m_swap_chain);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600838#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800839 xcb_destroy_window(m_connection, m_window);
840 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600841#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600842}
843
Tony Barbour6918cd52015-04-09 12:58:51 -0600844void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600845{
846 if (m_images.size() == 0) return;
847
Chia-I Wuf8693382015-04-16 22:02:10 +0800848 vk_testing::Environment env;
849 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -0700850 {
Chia-I Wuf8693382015-04-16 22:02:10 +0800851 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -0700852
Jon Ashburn07daee72015-05-21 18:13:33 -0600853 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600854 vkPresent.CreateMyWindow();
Chia-I Wuf8693382015-04-16 22:02:10 +0800855 vkPresent.CreateSwapChain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600856 vkPresent.Run();
857 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -0700858 }
Chia-I Wuf8693382015-04-16 22:02:10 +0800859 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600860}
861
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600862//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600863// These are the default resources for TBuiltInResources, used for both
864// - parsing this string for the case where the user didn't supply one
865// - dumping out a template for user construction of a config file
866//
867static const char* DefaultConfig =
868 "MaxLights 32\n"
869 "MaxClipPlanes 6\n"
870 "MaxTextureUnits 32\n"
871 "MaxTextureCoords 32\n"
872 "MaxVertexAttribs 64\n"
873 "MaxVertexUniformComponents 4096\n"
874 "MaxVaryingFloats 64\n"
875 "MaxVertexTextureImageUnits 32\n"
876 "MaxCombinedTextureImageUnits 80\n"
877 "MaxTextureImageUnits 32\n"
878 "MaxFragmentUniformComponents 4096\n"
879 "MaxDrawBuffers 32\n"
880 "MaxVertexUniformVectors 128\n"
881 "MaxVaryingVectors 8\n"
882 "MaxFragmentUniformVectors 16\n"
883 "MaxVertexOutputVectors 16\n"
884 "MaxFragmentInputVectors 15\n"
885 "MinProgramTexelOffset -8\n"
886 "MaxProgramTexelOffset 7\n"
887 "MaxClipDistances 8\n"
888 "MaxComputeWorkGroupCountX 65535\n"
889 "MaxComputeWorkGroupCountY 65535\n"
890 "MaxComputeWorkGroupCountZ 65535\n"
891 "MaxComputeWorkGroupSizeX 1024\n"
892 "MaxComputeWorkGroupSizeY 1024\n"
893 "MaxComputeWorkGroupSizeZ 64\n"
894 "MaxComputeUniformComponents 1024\n"
895 "MaxComputeTextureImageUnits 16\n"
896 "MaxComputeImageUniforms 8\n"
897 "MaxComputeAtomicCounters 8\n"
898 "MaxComputeAtomicCounterBuffers 1\n"
899 "MaxVaryingComponents 60\n"
900 "MaxVertexOutputComponents 64\n"
901 "MaxGeometryInputComponents 64\n"
902 "MaxGeometryOutputComponents 128\n"
903 "MaxFragmentInputComponents 128\n"
904 "MaxImageUnits 8\n"
905 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
906 "MaxCombinedShaderOutputResources 8\n"
907 "MaxImageSamples 0\n"
908 "MaxVertexImageUniforms 0\n"
909 "MaxTessControlImageUniforms 0\n"
910 "MaxTessEvaluationImageUniforms 0\n"
911 "MaxGeometryImageUniforms 0\n"
912 "MaxFragmentImageUniforms 8\n"
913 "MaxCombinedImageUniforms 8\n"
914 "MaxGeometryTextureImageUnits 16\n"
915 "MaxGeometryOutputVertices 256\n"
916 "MaxGeometryTotalOutputComponents 1024\n"
917 "MaxGeometryUniformComponents 1024\n"
918 "MaxGeometryVaryingComponents 64\n"
919 "MaxTessControlInputComponents 128\n"
920 "MaxTessControlOutputComponents 128\n"
921 "MaxTessControlTextureImageUnits 16\n"
922 "MaxTessControlUniformComponents 1024\n"
923 "MaxTessControlTotalOutputComponents 4096\n"
924 "MaxTessEvaluationInputComponents 128\n"
925 "MaxTessEvaluationOutputComponents 128\n"
926 "MaxTessEvaluationTextureImageUnits 16\n"
927 "MaxTessEvaluationUniformComponents 1024\n"
928 "MaxTessPatchComponents 120\n"
929 "MaxPatchVertices 32\n"
930 "MaxTessGenLevel 64\n"
931 "MaxViewports 16\n"
932 "MaxVertexAtomicCounters 0\n"
933 "MaxTessControlAtomicCounters 0\n"
934 "MaxTessEvaluationAtomicCounters 0\n"
935 "MaxGeometryAtomicCounters 0\n"
936 "MaxFragmentAtomicCounters 8\n"
937 "MaxCombinedAtomicCounters 8\n"
938 "MaxAtomicCounterBindings 1\n"
939 "MaxVertexAtomicCounterBuffers 0\n"
940 "MaxTessControlAtomicCounterBuffers 0\n"
941 "MaxTessEvaluationAtomicCounterBuffers 0\n"
942 "MaxGeometryAtomicCounterBuffers 0\n"
943 "MaxFragmentAtomicCounterBuffers 1\n"
944 "MaxCombinedAtomicCounterBuffers 1\n"
945 "MaxAtomicCounterBufferSize 16384\n"
946 "MaxTransformFeedbackBuffers 4\n"
947 "MaxTransformFeedbackInterleavedComponents 64\n"
948 "MaxCullDistances 8\n"
949 "MaxCombinedClipAndCullDistances 8\n"
950 "MaxSamples 4\n"
951
952 "nonInductiveForLoops 1\n"
953 "whileLoops 1\n"
954 "doWhileLoops 1\n"
955 "generalUniformIndexing 1\n"
956 "generalAttributeMatrixVectorIndexing 1\n"
957 "generalVaryingIndexing 1\n"
958 "generalSamplerIndexing 1\n"
959 "generalVariableIndexing 1\n"
960 "generalConstantMatrixVectorIndexing 1\n"
961 ;
962
963//
964// *.conf => this is a config file that can set limits/resources
965//
Tony Barbour6918cd52015-04-09 12:58:51 -0600966bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600967{
968 if (name.size() < 5)
969 return false;
970
971 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
972 ConfigFile = name;
973 return true;
974 }
975
976 return false;
977}
978
979//
980// Parse either a .conf file provided by the user or the default string above.
981//
Tony Barbour6918cd52015-04-09 12:58:51 -0600982void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600983{
984 char** configStrings = 0;
985 char* config = 0;
986 if (ConfigFile.size() > 0) {
987 configStrings = ReadFileData(ConfigFile.c_str());
988 if (configStrings)
989 config = *configStrings;
990 else {
991 printf("Error opening configuration file; will instead use the default configuration\n");
992 }
993 }
994
995 if (config == 0) {
996 config = new char[strlen(DefaultConfig) + 1];
997 strcpy(config, DefaultConfig);
998 }
999
1000 const char* delims = " \t\n\r";
1001 const char* token = strtok(config, delims);
1002 while (token) {
1003 const char* valueStr = strtok(0, delims);
1004 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1005 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1006 return;
1007 }
1008 int value = atoi(valueStr);
1009
1010 if (strcmp(token, "MaxLights") == 0)
1011 Resources.maxLights = value;
1012 else if (strcmp(token, "MaxClipPlanes") == 0)
1013 Resources.maxClipPlanes = value;
1014 else if (strcmp(token, "MaxTextureUnits") == 0)
1015 Resources.maxTextureUnits = value;
1016 else if (strcmp(token, "MaxTextureCoords") == 0)
1017 Resources.maxTextureCoords = value;
1018 else if (strcmp(token, "MaxVertexAttribs") == 0)
1019 Resources.maxVertexAttribs = value;
1020 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1021 Resources.maxVertexUniformComponents = value;
1022 else if (strcmp(token, "MaxVaryingFloats") == 0)
1023 Resources.maxVaryingFloats = value;
1024 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1025 Resources.maxVertexTextureImageUnits = value;
1026 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1027 Resources.maxCombinedTextureImageUnits = value;
1028 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1029 Resources.maxTextureImageUnits = value;
1030 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1031 Resources.maxFragmentUniformComponents = value;
1032 else if (strcmp(token, "MaxDrawBuffers") == 0)
1033 Resources.maxDrawBuffers = value;
1034 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1035 Resources.maxVertexUniformVectors = value;
1036 else if (strcmp(token, "MaxVaryingVectors") == 0)
1037 Resources.maxVaryingVectors = value;
1038 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1039 Resources.maxFragmentUniformVectors = value;
1040 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1041 Resources.maxVertexOutputVectors = value;
1042 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1043 Resources.maxFragmentInputVectors = value;
1044 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1045 Resources.minProgramTexelOffset = value;
1046 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1047 Resources.maxProgramTexelOffset = value;
1048 else if (strcmp(token, "MaxClipDistances") == 0)
1049 Resources.maxClipDistances = value;
1050 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1051 Resources.maxComputeWorkGroupCountX = value;
1052 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1053 Resources.maxComputeWorkGroupCountY = value;
1054 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1055 Resources.maxComputeWorkGroupCountZ = value;
1056 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1057 Resources.maxComputeWorkGroupSizeX = value;
1058 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1059 Resources.maxComputeWorkGroupSizeY = value;
1060 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1061 Resources.maxComputeWorkGroupSizeZ = value;
1062 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1063 Resources.maxComputeUniformComponents = value;
1064 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1065 Resources.maxComputeTextureImageUnits = value;
1066 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1067 Resources.maxComputeImageUniforms = value;
1068 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1069 Resources.maxComputeAtomicCounters = value;
1070 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1071 Resources.maxComputeAtomicCounterBuffers = value;
1072 else if (strcmp(token, "MaxVaryingComponents") == 0)
1073 Resources.maxVaryingComponents = value;
1074 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1075 Resources.maxVertexOutputComponents = value;
1076 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1077 Resources.maxGeometryInputComponents = value;
1078 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1079 Resources.maxGeometryOutputComponents = value;
1080 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1081 Resources.maxFragmentInputComponents = value;
1082 else if (strcmp(token, "MaxImageUnits") == 0)
1083 Resources.maxImageUnits = value;
1084 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1085 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1086 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1087 Resources.maxCombinedShaderOutputResources = value;
1088 else if (strcmp(token, "MaxImageSamples") == 0)
1089 Resources.maxImageSamples = value;
1090 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1091 Resources.maxVertexImageUniforms = value;
1092 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1093 Resources.maxTessControlImageUniforms = value;
1094 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1095 Resources.maxTessEvaluationImageUniforms = value;
1096 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1097 Resources.maxGeometryImageUniforms = value;
1098 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1099 Resources.maxFragmentImageUniforms = value;
1100 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1101 Resources.maxCombinedImageUniforms = value;
1102 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1103 Resources.maxGeometryTextureImageUnits = value;
1104 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1105 Resources.maxGeometryOutputVertices = value;
1106 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1107 Resources.maxGeometryTotalOutputComponents = value;
1108 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1109 Resources.maxGeometryUniformComponents = value;
1110 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1111 Resources.maxGeometryVaryingComponents = value;
1112 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1113 Resources.maxTessControlInputComponents = value;
1114 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1115 Resources.maxTessControlOutputComponents = value;
1116 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1117 Resources.maxTessControlTextureImageUnits = value;
1118 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1119 Resources.maxTessControlUniformComponents = value;
1120 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1121 Resources.maxTessControlTotalOutputComponents = value;
1122 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1123 Resources.maxTessEvaluationInputComponents = value;
1124 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1125 Resources.maxTessEvaluationOutputComponents = value;
1126 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1127 Resources.maxTessEvaluationTextureImageUnits = value;
1128 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1129 Resources.maxTessEvaluationUniformComponents = value;
1130 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1131 Resources.maxTessPatchComponents = value;
1132 else if (strcmp(token, "MaxPatchVertices") == 0)
1133 Resources.maxPatchVertices = value;
1134 else if (strcmp(token, "MaxTessGenLevel") == 0)
1135 Resources.maxTessGenLevel = value;
1136 else if (strcmp(token, "MaxViewports") == 0)
1137 Resources.maxViewports = value;
1138 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1139 Resources.maxVertexAtomicCounters = value;
1140 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1141 Resources.maxTessControlAtomicCounters = value;
1142 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1143 Resources.maxTessEvaluationAtomicCounters = value;
1144 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1145 Resources.maxGeometryAtomicCounters = value;
1146 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1147 Resources.maxFragmentAtomicCounters = value;
1148 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1149 Resources.maxCombinedAtomicCounters = value;
1150 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1151 Resources.maxAtomicCounterBindings = value;
1152 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1153 Resources.maxVertexAtomicCounterBuffers = value;
1154 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1155 Resources.maxTessControlAtomicCounterBuffers = value;
1156 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1157 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1158 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1159 Resources.maxGeometryAtomicCounterBuffers = value;
1160 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1161 Resources.maxFragmentAtomicCounterBuffers = value;
1162 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1163 Resources.maxCombinedAtomicCounterBuffers = value;
1164 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1165 Resources.maxAtomicCounterBufferSize = value;
1166 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1167 Resources.maxTransformFeedbackBuffers = value;
1168 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1169 Resources.maxTransformFeedbackInterleavedComponents = value;
1170 else if (strcmp(token, "MaxCullDistances") == 0)
1171 Resources.maxCullDistances = value;
1172 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1173 Resources.maxCombinedClipAndCullDistances = value;
1174 else if (strcmp(token, "MaxSamples") == 0)
1175 Resources.maxSamples = value;
1176
1177 else if (strcmp(token, "nonInductiveForLoops") == 0)
1178 Resources.limits.nonInductiveForLoops = (value != 0);
1179 else if (strcmp(token, "whileLoops") == 0)
1180 Resources.limits.whileLoops = (value != 0);
1181 else if (strcmp(token, "doWhileLoops") == 0)
1182 Resources.limits.doWhileLoops = (value != 0);
1183 else if (strcmp(token, "generalUniformIndexing") == 0)
1184 Resources.limits.generalUniformIndexing = (value != 0);
1185 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1186 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1187 else if (strcmp(token, "generalVaryingIndexing") == 0)
1188 Resources.limits.generalVaryingIndexing = (value != 0);
1189 else if (strcmp(token, "generalSamplerIndexing") == 0)
1190 Resources.limits.generalSamplerIndexing = (value != 0);
1191 else if (strcmp(token, "generalVariableIndexing") == 0)
1192 Resources.limits.generalVariableIndexing = (value != 0);
1193 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1194 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1195 else
1196 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1197
1198 token = strtok(0, delims);
1199 }
1200 if (configStrings)
1201 FreeFileData(configStrings);
1202}
1203
Tony Barbour6918cd52015-04-09 12:58:51 -06001204void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001205{
1206 if (m_compile_options & EOptionRelaxedErrors)
1207 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1208 if (m_compile_options & EOptionIntermediate)
1209 messages = (EShMessages)(messages | EShMsgAST);
1210 if (m_compile_options & EOptionSuppressWarnings)
1211 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1212}
1213
1214//
1215// Malloc a string of sufficient size and read a string into it.
1216//
Tony Barbour6918cd52015-04-09 12:58:51 -06001217char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001218{
1219 FILE *in;
1220 #if defined(_WIN32) && defined(__GNUC__)
1221 in = fopen(fileName, "r");
1222 int errorCode = in ? 0 : 1;
1223 #else
1224 int errorCode = fopen_s(&in, fileName, "r");
1225 #endif
1226
1227 char *fdata;
1228 int count = 0;
1229 const int maxSourceStrings = 5;
1230 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1231
1232 if (errorCode) {
1233 printf("Error: unable to open input file: %s\n", fileName);
1234 return 0;
1235 }
1236
1237 while (fgetc(in) != EOF)
1238 count++;
1239
1240 fseek(in, 0, SEEK_SET);
1241
1242 if (!(fdata = (char*)malloc(count+2))) {
1243 printf("Error allocating memory\n");
1244 return 0;
1245 }
1246 if (fread(fdata,1,count, in)!=count) {
1247 printf("Error reading input file: %s\n", fileName);
1248 return 0;
1249 }
1250 fdata[count] = '\0';
1251 fclose(in);
1252 if (count == 0) {
1253 return_data[0]=(char*)malloc(count+2);
1254 return_data[0][0]='\0';
1255 m_num_shader_strings = 0;
1256 return return_data;
1257 } else
1258 m_num_shader_strings = 1;
1259
1260 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1261 int ptr_len=0,i=0;
1262 while(count>0){
1263 return_data[i]=(char*)malloc(len+2);
1264 memcpy(return_data[i],fdata+ptr_len,len);
1265 return_data[i][len]='\0';
1266 count-=(len);
1267 ptr_len+=(len);
1268 if(count<len){
1269 if(count==0){
1270 m_num_shader_strings=(i+1);
1271 break;
1272 }
1273 len = count;
1274 }
1275 ++i;
1276 }
1277 return return_data;
1278}
1279
Tony Barbour6918cd52015-04-09 12:58:51 -06001280void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001281{
1282 for(int i=0;i<m_num_shader_strings;i++)
1283 free(data[i]);
1284}
1285
1286//
1287// Deduce the language from the filename. Files must end in one of the
1288// following extensions:
1289//
1290// .vert = vertex
1291// .tesc = tessellation control
1292// .tese = tessellation evaluation
1293// .geom = geometry
1294// .frag = fragment
1295// .comp = compute
1296//
Tony Barbour6918cd52015-04-09 12:58:51 -06001297EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001298{
1299 size_t ext = name.rfind('.');
1300 if (ext == std::string::npos) {
1301 return EShLangVertex;
1302 }
1303
1304 std::string suffix = name.substr(ext + 1, std::string::npos);
1305 if (suffix == "vert")
1306 return EShLangVertex;
1307 else if (suffix == "tesc")
1308 return EShLangTessControl;
1309 else if (suffix == "tese")
1310 return EShLangTessEvaluation;
1311 else if (suffix == "geom")
1312 return EShLangGeometry;
1313 else if (suffix == "frag")
1314 return EShLangFragment;
1315 else if (suffix == "comp")
1316 return EShLangCompute;
1317
1318 return EShLangVertex;
1319}
1320
1321//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001322// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001323//
Tony Barbourd1c35722015-04-16 15:59:00 -06001324EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001325{
1326 switch (shader_type) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001327 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001328 return EShLangVertex;
1329
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001330 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001331 return EShLangTessControl;
1332
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001333 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001334 return EShLangTessEvaluation;
1335
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001336 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001337 return EShLangGeometry;
1338
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001339 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001340 return EShLangFragment;
1341
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001342 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001343 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001344
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001345 default:
1346 return EShLangVertex;
1347 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001348}
1349
1350
1351//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001352// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001353// Return value of false means an error was encountered.
1354//
Tony Barbourd1c35722015-04-16 15:59:00 -06001355bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001356 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001357 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001358{
1359 glslang::TProgram& program = *new glslang::TProgram;
1360 const char *shaderStrings[1];
1361
1362 // TODO: Do we want to load a special config file depending on the
1363 // shader source? Optional name maybe?
1364 // SetConfigFile(fileName);
1365
1366 ProcessConfigFile();
1367
1368 EShMessages messages = EShMsgDefault;
1369 SetMessageOptions(messages);
1370
1371 EShLanguage stage = FindLanguage(shader_type);
1372 glslang::TShader* shader = new glslang::TShader(stage);
1373
1374 shaderStrings[0] = pshader;
1375 shader->setStrings(shaderStrings, 1);
1376
1377 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1378
Cody Northrop195d6622014-11-03 12:54:37 -07001379 if (! (m_compile_options & EOptionSuppressInfolog)) {
1380 puts(shader->getInfoLog());
1381 puts(shader->getInfoDebugLog());
1382 }
1383
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001384 return false; // something didn't work
1385 }
1386
1387 program.addShader(shader);
1388
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001389
1390 //
1391 // Program-level processing...
1392 //
1393
Cody Northrop195d6622014-11-03 12:54:37 -07001394 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001395
Cody Northrop195d6622014-11-03 12:54:37 -07001396 if (! (m_compile_options & EOptionSuppressInfolog)) {
1397 puts(shader->getInfoLog());
1398 puts(shader->getInfoDebugLog());
1399 }
1400
1401 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001402 }
1403
1404 if (m_compile_options & EOptionDumpReflection) {
1405 program.buildReflection();
1406 program.dumpReflection();
1407 }
1408
Cody Northrop5a95b472015-06-03 13:01:54 -06001409 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1410
1411 //
1412 // Test the different modes of SPIR-V modification
1413 //
1414 if (this->m_canonicalize_spv) {
1415 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1416 }
1417
1418 if (this->m_strip_spv) {
1419 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1420 }
1421
1422 if (this->m_do_everything_spv) {
1423 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1424 }
1425
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001426
1427 return true;
1428}
1429
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001430
1431
Tony Barbour6918cd52015-04-09 12:58:51 -06001432VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001433 m_width( 0 ),
1434 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001435 m_data( NULL ),
1436 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001437{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001438}
1439
Tony Barbour6918cd52015-04-09 12:58:51 -06001440VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001441{
1442
1443}
1444
Tony Barbour6918cd52015-04-09 12:58:51 -06001445VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001446{
1447 m_title = copyin.m_title;
1448 m_width = copyin.m_width;
1449 m_height = copyin.m_height;
1450 m_data_size = copyin.m_data_size;
1451 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1452}
1453
Tony Barbour6918cd52015-04-09 12:58:51 -06001454ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001455{
Tony Barbour6918cd52015-04-09 12:58:51 -06001456 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1457 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001458 return output;
1459}
1460
Tony Barbour6918cd52015-04-09 12:58:51 -06001461VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001462{
1463 m_title = rhs.m_title;
1464 m_width = rhs.m_width;
1465 m_height = rhs.m_height;
1466 m_data_size = rhs.m_data_size;
1467 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001468 return *this;
1469}
1470
Tony Barbour6918cd52015-04-09 12:58:51 -06001471int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001472{
1473 if( this->m_data != rhs.m_data) return 0;
1474 return 1;
1475}
1476
1477// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001478int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001479{
1480 if( this->m_data_size < rhs.m_data_size ) return 1;
1481 return 0;
1482}
1483