blob: ffb2549c5a2c4fef4c977170084ac74846d4b215 [file] [log] [blame]
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001// VK tests
Courtney Goeltzenleuchterd0d7ccc2014-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 Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060023#include "vktestframework.h"
24#include "vkrenderframework.h"
Cody Northropeb9130e2015-06-03 13:01:54 -060025#include "SPIRV/GlslangToSpv.h"
26#include "SPIRV/SPVRemapper.h"
Tony Barbour772c5ef2014-12-10 17:00:20 -070027#include <limits.h>
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -060028#include <math.h>
Chia-I Wu3d9ebb22014-12-02 11:54:24 +080029#include <wand/MagickWand.h>
Chia-I Wu5b66aa52015-04-16 22:02:10 +080030#include <xcb/xcb.h>
31#include <vk_wsi_lunarg.h>
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -060032
Tony Barbour25e3b832015-05-20 16:53:31 -060033#if defined(PATH_MAX) && !defined(MAX_PATH)
34#define MAX_PATH PATH_MAX
35#endif
36
Courtney Goeltzenleuchter94192032014-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 Northropacfb0492015-03-17 15:55:58 -060051 EOptionSpv = 0x800,
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -060052 EOptionDefaultDesktop = 0x1000,
53};
54
Chia-I Wu5b66aa52015-04-16 22:02:10 +080055class TestFrameworkVkPresent
56{
57public:
58 TestFrameworkVkPresent(vk_testing::Device &device);
59
60 void Run();
Jon Ashburncedc15f2015-05-21 18:13:33 -060061 void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst);
Chia-I Wu5b66aa52015-04-16 22:02:10 +080062 void CreateMyWindow();
63 void CreateSwapChain();
64 void TearDown();
Tony Barbour25e3b832015-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 Wu5b66aa52015-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 Barbour25e3b832015-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 Wu5b66aa52015-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 Barbour25e3b832015-05-20 16:53:31 -060085#endif
Courtney Goeltzenleuchterec69b9c2015-04-22 10:09:35 -060086 std::list<VkTestImageRecord> m_images;
Chia-I Wu5b66aa52015-04-16 22:02:10 +080087
Jon Ashburncedc15f2015-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 Wu5b66aa52015-04-16 22:02:10 +080093 VkSwapChainWSI m_swap_chain;
Tony-LunarGf05ba082015-05-19 14:08:26 -060094 std::vector<VkSwapChainImageInfoWSI> m_persistent_images;
95 int m_current_buffer;
Chia-I Wu5b66aa52015-04-16 22:02:10 +080096
97 bool m_quit;
98 bool m_pause;
99
Tony Barbour8bef8ee2015-05-22 09:44:58 -0600100 int m_width;
101 int m_height;
Chia-I Wu5b66aa52015-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 Goeltzenleuchter94192032014-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600137
Tony Barbour25e3b832015-05-20 16:53:31 -0600138
139
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600140// Set up environment for GLSL compiler
141// Must be done once per process
142void TestEnvironment::SetUp()
143{
Cody Northropacfb0492015-03-17 15:55:58 -0600144 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600145 glslang::InitializeProcess();
Chia-I Wu1c9869e2014-12-28 14:27:28 +0800146
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600147 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600148}
149
150void TestEnvironment::TearDown()
151{
152 glslang::FinalizeProcess();
153}
154
Tony Barbour01999182015-04-09 12:58:51 -0600155VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600156 m_compile_options( 0 ),
157 m_num_shader_strings( 0 )
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600158{
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600159
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600160}
161
Tony Barbour01999182015-04-09 12:58:51 -0600162VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600163{
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600164
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600165}
166
167// Define all the static elements
Cody Northropa392a292015-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 Northropeb9130e2015-06-03 13:01:54 -0600174bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour01999182015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600179int m_display_image_idx = 0;
180
Cody Northrop1cfbd172015-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 Barbour01999182015-04-09 12:58:51 -0600189void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600190{
191 int i, n;
192
Cody Northrop1cfbd172015-06-03 16:49:20 -0600193 for (i=1, n=1; i< *argc; i++) {
194 if (optionMatch("--show-images", argv[i]))
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600195 m_show_images = true;
Cody Northrop1cfbd172015-06-03 16:49:20 -0600196 else if (optionMatch("--save-images", argv[i]))
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600197 m_save_images = true;
Cody Northrop1cfbd172015-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 Barbour32f368c2014-10-30 14:29:04 -0600205 m_compare_images = true;
Tony Barbour32f368c2014-10-30 14:29:04 -0600206
Cody Northrop1cfbd172015-06-03 16:49:20 -0600207 else if (optionMatch("--help", argv[i]) ||
208 optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchterb7f26e02014-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 Barbour0e4235d2014-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 Goeltzenleuchterb7f26e02014-12-02 13:13:10 -0700221 "\t\tSignal test failure if different.\n");
Cody Northropacfb0492015-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 Northrop1cfbd172015-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 Barbour772c5ef2014-12-10 17:00:20 -0700232 exit(0);
Courtney Goeltzenleuchterb7f26e02014-12-02 13:13:10 -0700233 }
234
Cody Northrop1cfbd172015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600240 argv[n] = argv[i];
241 n++;
242 }
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600243}
244
Tony Barbour01999182015-04-09 12:58:51 -0600245void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600246{
247 string filename;
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600248 VkResult err;
Tony Barbour8bef8ee2015-05-22 09:44:58 -0600249 uint32_t x, y;
Tony Barbour01999182015-04-09 12:58:51 -0600250 VkImageObj displayImage(image->device());
Tony Barbour94310562015-04-22 15:10:33 -0600251 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbouredc49d92015-04-02 14:02:33 -0600252
Tony Barbour94310562015-04-22 15:10:33 -0600253 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, VK_IMAGE_TILING_LINEAR, reqs);
Tony Barbouredc49d92015-04-02 14:02:33 -0600254 displayImage.CopyImage(*image);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600255
256 filename.append(basename);
257 filename.append(".ppm");
Tony Barbour25e3b832015-05-20 16:53:31 -0600258
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600259 const VkImageSubresource sr = {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600260 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600261 };
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600262 VkSubresourceLayout sr_layout;
Tony Barbour25e3b832015-05-20 16:53:31 -0600263
Tony Barbour426b9052015-06-24 16:06:58 -0600264 err = vkGetImageSubresourceLayout(image->device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600265 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600266
Tony Barbouredc49d92015-04-02 14:02:33 -0600267 char *ptr;
268 ptr = (char *) displayImage.map();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600269 ptr += sr_layout.offset;
Tony Barbour25e3b832015-05-20 16:53:31 -0600270 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600271 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
272
273 file << "P6\n";
Tony Barbouredc49d92015-04-02 14:02:33 -0600274 file << displayImage.width() << "\n";
275 file << displayImage.height() << "\n";
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600276 file << 255 << "\n";
277
Tony Barbouredc49d92015-04-02 14:02:33 -0600278 for (y = 0; y < displayImage.height(); y++) {
Tony Barboure2668672015-02-25 11:25:11 -0700279 const int *row = (const int *) ptr;
280 int swapped;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600281
Tony Barbour8205d902015-04-16 15:59:00 -0600282 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboure2668672015-02-25 11:25:11 -0700283 {
Tony Barbouredc49d92015-04-02 14:02:33 -0600284 for (x = 0; x < displayImage.width(); x++) {
Tony Barboure2668672015-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 Barbour8205d902015-04-16 15:59:00 -0600290 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboure2668672015-02-25 11:25:11 -0700291 {
Tony Barbouredc49d92015-04-02 14:02:33 -0600292 for (x = 0; x < displayImage.width(); x++) {
Tony Barboure2668672015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600300 }
301
302 ptr += sr_layout.rowPitch;
303 }
304
305 file.close();
Tony Barbouredc49d92015-04-02 14:02:33 -0600306 displayImage.unmap();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600307}
308
Tony Barbour01999182015-04-09 12:58:51 -0600309void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour32f368c2014-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 Barbour25e3b832015-05-20 16:53:31 -0600316 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour32f368c2014-10-30 14:29:04 -0600317 double differenz;
318
Tony Barbour772c5ef2014-12-10 17:00:20 -0700319 if (getenv("RENDERTEST_GOLDEN_DIR"))
320 {
321 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
322 }
323
Tony Barbour32f368c2014-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 Barbour8bef8ee2015-05-22 09:44:58 -0600328 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour32f368c2014-10-30 14:29:04 -0600329
330
331 MagickWandGenesis();
332 magick_wand_2=NewMagickWand();
Tony Barbour772c5ef2014-12-10 17:00:20 -0700333 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour32f368c2014-10-30 14:29:04 -0600334 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour8bef8ee2015-05-22 09:44:58 -0600335 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour32f368c2014-10-30 14:29:04 -0600336
Tony Barbour32f368c2014-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 Goeltzenleuchterdfa97b82014-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 Barbour32f368c2014-10-30 14:29:04 -0600360}
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600361
Tony Barbour01999182015-04-09 12:58:51 -0600362void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600363{
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600364 VkResult err;
Courtney Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600365 VkSubresourceLayout sr_layout;
366 char *ptr;
367 VkTestImageRecord record;
Courtney Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600368 VkImageObj displayImage(image->device());
369 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
370
Courtney Goeltzenleuchtere5871c72015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600373
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600374 const VkImageSubresource sr = {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600375 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600376 };
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600377
Tony Barbour426b9052015-06-24 16:06:58 -0600378 err = vkGetImageSubresourceLayout(displayImage.device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600379 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600380
Courtney Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600381 err = displayImage.MapMemory( (void **) &ptr );
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600382 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600383
384 ptr += sr_layout.offset;
385
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600386 record.m_title.append(comment);
Courtney Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600387 record.m_width = displayImage.width();
388 record.m_height = displayImage.height();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600389 // TODO: Need to make this more robust to handle different image formats
Tony-LunarGf05ba082015-05-19 14:08:26 -0600390 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchterd0d7ccc2014-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 Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600396 err = displayImage.UnmapMemory();
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600397 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600398}
399
Tony Barbour01999182015-04-09 12:58:51 -0600400void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour32f368c2014-10-30 14:29:04 -0600401{
Courtney Goeltzenleuchtercd5ed1e2015-04-02 14:17:44 -0600402 for (int32_t i = 0; i < images.size(); i++) {
403 RecordImage(images[i]);
Tony Barbour32f368c2014-10-30 14:29:04 -0600404 }
405}
406
Tony Barbour01999182015-04-09 12:58:51 -0600407void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600408{
409 const ::testing::TestInfo* const test_info =
410 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour32f368c2014-10-30 14:29:04 -0600411 ostringstream filestream;
412 string filename;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600413
Tony Barbour32f368c2014-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 Barboura48b0812014-11-18 17:02:36 -0700419 m_frameNum = 2;
420 filename = filestream.str();
Tony Barbour32f368c2014-10-30 14:29:04 -0600421 }
422 else {
423 filestream << test_info->name() << "-" << m_frameNum;
424 m_frameNum++;
Tony Barboura48b0812014-11-18 17:02:36 -0700425 filename = filestream.str();
Tony Barbour32f368c2014-10-30 14:29:04 -0600426 }
427
Tony Barbour32f368c2014-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600435 }
436
437 if (m_show_images) {
Courtney Goeltzenleuchtere5409342014-10-08 14:26:40 -0600438 Show(test_info->name(), image);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600439 }
440}
441
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800442TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
443 m_device(device),
Courtney Goeltzenleuchterdd745fd2015-03-05 16:47:18 -0700444 m_queue(*m_device.graphics_queues()[0]),
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600445 m_cmdbuf(m_device, vk_testing::CmdBuffer::create_info(m_device.graphics_queue_node_index_))
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600446{
Tony Barbouref20d322015-02-25 12:28:39 -0700447 m_quit = false;
448 m_pause = false;
449 m_width = 0;
450 m_height = 0;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600451}
452
Tony Barbour01999182015-04-09 12:58:51 -0600453void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600454{
Tony Barbour22a30862015-04-22 09:02:32 -0600455 VkResult U_ASSERT_ONLY err;
Tony-LunarGf05ba082015-05-19 14:08:26 -0600456 vk_testing::Buffer buf;
457 void *dest_ptr;
458
459 if (m_persistent_images.size() != 2) {
460 return;
461 }
462
463 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Cody Northrop257fe6e2015-06-17 08:29:35 -0600464 flags |= VK_BUFFER_USAGE_TRANSFER_SOURCE_BIT;
Tony-LunarGf05ba082015-05-19 14:08:26 -0600465 buf.init(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
466 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 Barbouref20d322015-02-25 12:28:39 -0700488
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800489 VkPresentInfoWSI present = {};
490 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_WSI;
Tony-LunarGf05ba082015-05-19 14:08:26 -0600491 present.image = m_persistent_images[m_current_buffer].image;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800492 present.flipInterval = 1;
Tony Barbouref20d322015-02-25 12:28:39 -0700493
Tony Barbour25e3b832015-05-20 16:53:31 -0600494#ifndef _WIN32
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800495 xcb_change_property (m_connection,
Tony Barbouref20d322015-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 Barbour25e3b832015-05-20 16:53:31 -0600503#endif
Jon Ashburncedc15f2015-05-21 18:13:33 -0600504
505 err = m_fpQueuePresentWSI(m_queue.obj(), &present);
Tony Barbouref20d322015-02-25 12:28:39 -0700506 assert(!err);
507
508 m_queue.wait();
Tony-LunarGf05ba082015-05-19 14:08:26 -0600509 m_current_buffer = (m_current_buffer + 1) % 2;
Tony Barbouref20d322015-02-25 12:28:39 -0700510
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600511}
512
Tony Barbour25e3b832015-05-20 16:53:31 -0600513#ifdef _WIN32
Tony-LunarGf05ba082015-05-19 14:08:26 -0600514# define PREVIOUSLY_DOWN 1<<29
Tony Barbour25e3b832015-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-LunarGf05ba082015-05-19 14:08:26 -0600532 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour25e3b832015-05-20 16:53:31 -0600533 me->Display();
534 }
535 }
Tony-LunarGf05ba082015-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 Barbour25e3b832015-05-20 16:53:31 -0600573 }
574 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
575}
576
577void TestFrameworkVkPresent::Run()
578{
579 MSG msg; // message
Tony Barbour25e3b832015-05-20 16:53:31 -0600580
Tony Barbour25e3b832015-05-20 16:53:31 -0600581 /* main message loop*/
Tony-LunarGf05ba082015-05-19 14:08:26 -0600582 while(! m_quit) {
583 GetMessage(&msg, m_window, 0, 0);
Tony Barbour25e3b832015-05-20 16:53:31 -0600584 if (msg.message == WM_QUIT) {
Tony-LunarGf05ba082015-05-19 14:08:26 -0600585 m_quit = true; //if found, quit app
Tony Barbour25e3b832015-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 Barbour01999182015-04-09 12:58:51 -0600595void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600596{
Tony Barbour3a5cda02015-04-02 15:48:24 -0600597 uint8_t event_code = event->response_type & 0x7f;
Tony Barbouref20d322015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600606 }
607 break;
Tony Barbouref20d322015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600612
Tony Barbouref20d322015-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600638 break;
639 }
Tony Barbouref20d322015-02-25 12:28:39 -0700640}
641
Tony Barbour01999182015-04-09 12:58:51 -0600642void TestFrameworkVkPresent::Run()
Tony Barbouref20d322015-02-25 12:28:39 -0700643{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800644 xcb_flush(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700645
646 while (! m_quit) {
647 xcb_generic_event_t *event;
648
649 if (m_pause) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800650 event = xcb_wait_for_event(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700651 } else {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800652 event = xcb_poll_for_event(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700653 }
654 if (event) {
655 HandleEvent(event);
656 free(event);
657 }
658 }
659}
Tony Barbour25e3b832015-05-20 16:53:31 -0600660#endif // _WIN32
Tony Barbouref20d322015-02-25 12:28:39 -0700661
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800662void TestFrameworkVkPresent::CreateSwapChain()
Tony Barbouref20d322015-02-25 12:28:39 -0700663{
Tony Barbour22a30862015-04-22 09:02:32 -0600664 VkResult U_ASSERT_ONLY err;
Tony Barbouref20d322015-02-25 12:28:39 -0700665
Tony-LunarGf05ba082015-05-19 14:08:26 -0600666 m_display_image = m_images.begin();
667 m_current_buffer = 0;
668
Chia-I Wu5b66aa52015-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-LunarGf05ba082015-05-19 14:08:26 -0600673 swap_chain.imageCount = 2;
Chia-I Wu5b66aa52015-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;
678 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT;
679 swap_chain.swapModeFlags = VK_SWAP_MODE_FLIP_BIT_WSI |
680 VK_SWAP_MODE_BLIT_BIT_WSI;
681
Jon Ashburncedc15f2015-05-21 18:13:33 -0600682 err = m_fpCreateSwapChainWSI(m_device.obj(), &swap_chain, &m_swap_chain);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800683 assert(!err);
684
Tony-LunarGf05ba082015-05-19 14:08:26 -0600685 VkSwapChainImageInfoWSI infos[2];
Courtney Goeltzenleuchter7ce9d262015-06-24 15:02:51 -0600686 size_t size = sizeof(VkSwapChainImageInfoWSI) * m_images.size() * 2;
Jon Ashburncedc15f2015-05-21 18:13:33 -0600687 std::vector<VkSwapChainImageInfoWSI> persistent_images;
688 persistent_images.resize(m_images.size());
689 err = m_fpGetSwapChainInfoWSI(m_swap_chain,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800690 VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI,
Tony-LunarGf05ba082015-05-19 14:08:26 -0600691 &size, &infos);
692 assert(!err && size == sizeof(VkSwapChainImageInfoWSI) * 2);
693 m_persistent_images.push_back(infos[0]);
694 m_persistent_images.push_back(infos[1]);
Tony Barbouref20d322015-02-25 12:28:39 -0700695}
696
Jon Ashburncedc15f2015-05-21 18:13:33 -0600697void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbouref20d322015-02-25 12:28:39 -0700698{
Jon Ashburncedc15f2015-05-21 18:13:33 -0600699 m_fpCreateSwapChainWSI = (PFN_vkCreateSwapChainWSI) vkGetInstanceProcAddr(inst, "vkCreateSwapChainWSI");
700 ASSERT_TRUE(m_fpCreateSwapChainWSI != NULL) << "vkGetInstanceProcAddr failed to find vkCreateSwapChainWSI";
701
702 m_fpDestroySwapChainWSI = (PFN_vkDestroySwapChainWSI) vkGetInstanceProcAddr(inst, "vkDestroySwapChainWSI");
703 ASSERT_TRUE(m_fpDestroySwapChainWSI != NULL) << "vkGetInstanceProcAddr failed to find vkDestroySwapChainWSI";
704
705 m_fpGetSwapChainInfoWSI = (PFN_vkGetSwapChainInfoWSI) vkGetInstanceProcAddr(inst, "vkGetSwapChainInfoWSI");
706 ASSERT_TRUE(m_fpGetSwapChainInfoWSI != NULL) << "vkGetInstanceProcAddr failed to find vkGetSwapChainInfoWSI";
707
708 m_fpQueuePresentWSI = (PFN_vkQueuePresentWSI) vkGetInstanceProcAddr(inst, "vkQueuePresentWSI");
709 ASSERT_TRUE(m_fpQueuePresentWSI != NULL) << "vkGetInstanceProcAddr failed to find vkQueuePresentWSI";
710
Tony Barbouref20d322015-02-25 12:28:39 -0700711 m_images = imagesIn;
712}
713
Tony Barbour25e3b832015-05-20 16:53:31 -0600714#ifdef _WIN32
715void TestFrameworkVkPresent::CreateMyWindow()
716{
717 WNDCLASSEX win_class;
718 // const ::testing::TestInfo* const test_info =
719 // ::testing::UnitTest::GetInstance()->current_test_info();
720 m_connection = GetModuleHandle(NULL);
721
722 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
723 it != m_images.end(); it++) {
724 if (m_width < it->m_width)
725 m_width = it->m_width;
726 if (m_height < it->m_height)
727 m_height = it->m_height;
728 }
729 // Initialize the window class structure:
730 win_class.cbSize = sizeof(WNDCLASSEX);
731 win_class.style = CS_HREDRAW | CS_VREDRAW;
732 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
733 win_class.cbClsExtra = 0;
734 win_class.cbWndExtra = 0;
735 win_class.hInstance = m_connection; // hInstance
736 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
737 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
738 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
739 win_class.lpszMenuName = NULL;
740 win_class.lpszClassName = "Test";
741 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
742 // Register window class:
743 if (!RegisterClassEx(&win_class)) {
744 // It didn't work, so try to give a useful error:
745 printf("Unexpected error trying to start the application!\n");
746 fflush(stdout);
747 exit(1);
748 }
749 // Create window with the registered class:
750 m_window = CreateWindowEx(0,
751 "Test", // class name
752 "Test", // app name
753 WS_OVERLAPPEDWINDOW | // window style
754 WS_VISIBLE |
755 WS_SYSMENU,
756 100,100, // x/y coords
757 m_width, // width
758 m_height, // height
759 NULL, // handle to parent
760 NULL, // handle to menu
761 m_connection, // hInstance
762 NULL); // no extra parameters
763
764 if (!m_window) {
765 // It didn't work, so try to give a useful error:
766 DWORD error = GetLastError();
767 char message[120];
768 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
769 MessageBox(NULL, message, "Error", MB_OK);
770 exit(1);
771 }
Tony-LunarGf05ba082015-05-19 14:08:26 -0600772 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
773 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour25e3b832015-05-20 16:53:31 -0600774}
775#else
Tony Barbour01999182015-04-09 12:58:51 -0600776void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbouref20d322015-02-25 12:28:39 -0700777{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800778 const xcb_setup_t *setup;
779 xcb_screen_iterator_t iter;
780 int scr;
Tony Barbouref20d322015-02-25 12:28:39 -0700781 uint32_t value_mask, value_list[32];
782
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800783 m_connection = xcb_connect(NULL, &scr);
784
785 setup = xcb_get_setup(m_connection);
786 iter = xcb_setup_roots_iterator(setup);
787 while (scr-- > 0)
788 xcb_screen_next(&iter);
789
790 m_screen = iter.data;
791
792 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
793 it != m_images.end(); it++) {
794 if (m_width < it->m_width)
795 m_width = it->m_width;
796 if (m_height < it->m_height)
797 m_height = it->m_height;
798 }
799
800 m_window = xcb_generate_id(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700801
802 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800803 value_list[0] = m_screen->black_pixel;
Tony Barbouref20d322015-02-25 12:28:39 -0700804 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
805 XCB_EVENT_MASK_EXPOSURE |
806 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
807
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800808 xcb_create_window(m_connection,
Tony Barbouref20d322015-02-25 12:28:39 -0700809 XCB_COPY_FROM_PARENT,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800810 m_window, m_screen->root,
Tony Barbouref20d322015-02-25 12:28:39 -0700811 0, 0, m_width, m_height, 0,
812 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800813 m_screen->root_visual,
Tony Barbouref20d322015-02-25 12:28:39 -0700814 value_mask, value_list);
815
816 /* Magic code that will send notification when window is destroyed */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800817 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbouref20d322015-02-25 12:28:39 -0700818 "WM_PROTOCOLS");
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800819 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbouref20d322015-02-25 12:28:39 -0700820
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800821 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
822 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbouref20d322015-02-25 12:28:39 -0700823
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800824 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbouref20d322015-02-25 12:28:39 -0700825 m_window, (*reply).atom, 4, 32, 1,
826 &(*m_atom_wm_delete_window).atom);
827 free(reply);
828
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800829 xcb_map_window(m_connection, m_window);
Tony Barbouref20d322015-02-25 12:28:39 -0700830}
Tony Barbour25e3b832015-05-20 16:53:31 -0600831#endif
Tony Barbouref20d322015-02-25 12:28:39 -0700832
Tony Barbour01999182015-04-09 12:58:51 -0600833void TestFrameworkVkPresent::TearDown()
Tony Barbouref20d322015-02-25 12:28:39 -0700834{
Jon Ashburncedc15f2015-05-21 18:13:33 -0600835 m_fpDestroySwapChainWSI(m_swap_chain);
Tony Barbour25e3b832015-05-20 16:53:31 -0600836#ifndef _WIN32
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800837 xcb_destroy_window(m_connection, m_window);
838 xcb_disconnect(m_connection);
Tony Barbour25e3b832015-05-20 16:53:31 -0600839#endif
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600840}
841
Tony Barbour01999182015-04-09 12:58:51 -0600842void VkTestFramework::Finish()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600843{
844 if (m_images.size() == 0) return;
845
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800846 vk_testing::Environment env;
847 env.SetUp();
Tony Barbouref20d322015-02-25 12:28:39 -0700848 {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800849 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbouref20d322015-02-25 12:28:39 -0700850
Jon Ashburncedc15f2015-05-21 18:13:33 -0600851 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600852 vkPresent.CreateMyWindow();
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800853 vkPresent.CreateSwapChain();
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600854 vkPresent.Run();
855 vkPresent.TearDown();
Tony Barbouref20d322015-02-25 12:28:39 -0700856 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800857 env.TearDown();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600858}
859
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600860//
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600861// These are the default resources for TBuiltInResources, used for both
862// - parsing this string for the case where the user didn't supply one
863// - dumping out a template for user construction of a config file
864//
865static const char* DefaultConfig =
866 "MaxLights 32\n"
867 "MaxClipPlanes 6\n"
868 "MaxTextureUnits 32\n"
869 "MaxTextureCoords 32\n"
870 "MaxVertexAttribs 64\n"
871 "MaxVertexUniformComponents 4096\n"
872 "MaxVaryingFloats 64\n"
873 "MaxVertexTextureImageUnits 32\n"
874 "MaxCombinedTextureImageUnits 80\n"
875 "MaxTextureImageUnits 32\n"
876 "MaxFragmentUniformComponents 4096\n"
877 "MaxDrawBuffers 32\n"
878 "MaxVertexUniformVectors 128\n"
879 "MaxVaryingVectors 8\n"
880 "MaxFragmentUniformVectors 16\n"
881 "MaxVertexOutputVectors 16\n"
882 "MaxFragmentInputVectors 15\n"
883 "MinProgramTexelOffset -8\n"
884 "MaxProgramTexelOffset 7\n"
885 "MaxClipDistances 8\n"
886 "MaxComputeWorkGroupCountX 65535\n"
887 "MaxComputeWorkGroupCountY 65535\n"
888 "MaxComputeWorkGroupCountZ 65535\n"
889 "MaxComputeWorkGroupSizeX 1024\n"
890 "MaxComputeWorkGroupSizeY 1024\n"
891 "MaxComputeWorkGroupSizeZ 64\n"
892 "MaxComputeUniformComponents 1024\n"
893 "MaxComputeTextureImageUnits 16\n"
894 "MaxComputeImageUniforms 8\n"
895 "MaxComputeAtomicCounters 8\n"
896 "MaxComputeAtomicCounterBuffers 1\n"
897 "MaxVaryingComponents 60\n"
898 "MaxVertexOutputComponents 64\n"
899 "MaxGeometryInputComponents 64\n"
900 "MaxGeometryOutputComponents 128\n"
901 "MaxFragmentInputComponents 128\n"
902 "MaxImageUnits 8\n"
903 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
904 "MaxCombinedShaderOutputResources 8\n"
905 "MaxImageSamples 0\n"
906 "MaxVertexImageUniforms 0\n"
907 "MaxTessControlImageUniforms 0\n"
908 "MaxTessEvaluationImageUniforms 0\n"
909 "MaxGeometryImageUniforms 0\n"
910 "MaxFragmentImageUniforms 8\n"
911 "MaxCombinedImageUniforms 8\n"
912 "MaxGeometryTextureImageUnits 16\n"
913 "MaxGeometryOutputVertices 256\n"
914 "MaxGeometryTotalOutputComponents 1024\n"
915 "MaxGeometryUniformComponents 1024\n"
916 "MaxGeometryVaryingComponents 64\n"
917 "MaxTessControlInputComponents 128\n"
918 "MaxTessControlOutputComponents 128\n"
919 "MaxTessControlTextureImageUnits 16\n"
920 "MaxTessControlUniformComponents 1024\n"
921 "MaxTessControlTotalOutputComponents 4096\n"
922 "MaxTessEvaluationInputComponents 128\n"
923 "MaxTessEvaluationOutputComponents 128\n"
924 "MaxTessEvaluationTextureImageUnits 16\n"
925 "MaxTessEvaluationUniformComponents 1024\n"
926 "MaxTessPatchComponents 120\n"
927 "MaxPatchVertices 32\n"
928 "MaxTessGenLevel 64\n"
929 "MaxViewports 16\n"
930 "MaxVertexAtomicCounters 0\n"
931 "MaxTessControlAtomicCounters 0\n"
932 "MaxTessEvaluationAtomicCounters 0\n"
933 "MaxGeometryAtomicCounters 0\n"
934 "MaxFragmentAtomicCounters 8\n"
935 "MaxCombinedAtomicCounters 8\n"
936 "MaxAtomicCounterBindings 1\n"
937 "MaxVertexAtomicCounterBuffers 0\n"
938 "MaxTessControlAtomicCounterBuffers 0\n"
939 "MaxTessEvaluationAtomicCounterBuffers 0\n"
940 "MaxGeometryAtomicCounterBuffers 0\n"
941 "MaxFragmentAtomicCounterBuffers 1\n"
942 "MaxCombinedAtomicCounterBuffers 1\n"
943 "MaxAtomicCounterBufferSize 16384\n"
944 "MaxTransformFeedbackBuffers 4\n"
945 "MaxTransformFeedbackInterleavedComponents 64\n"
946 "MaxCullDistances 8\n"
947 "MaxCombinedClipAndCullDistances 8\n"
948 "MaxSamples 4\n"
949
950 "nonInductiveForLoops 1\n"
951 "whileLoops 1\n"
952 "doWhileLoops 1\n"
953 "generalUniformIndexing 1\n"
954 "generalAttributeMatrixVectorIndexing 1\n"
955 "generalVaryingIndexing 1\n"
956 "generalSamplerIndexing 1\n"
957 "generalVariableIndexing 1\n"
958 "generalConstantMatrixVectorIndexing 1\n"
959 ;
960
961//
962// *.conf => this is a config file that can set limits/resources
963//
Tony Barbour01999182015-04-09 12:58:51 -0600964bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600965{
966 if (name.size() < 5)
967 return false;
968
969 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
970 ConfigFile = name;
971 return true;
972 }
973
974 return false;
975}
976
977//
978// Parse either a .conf file provided by the user or the default string above.
979//
Tony Barbour01999182015-04-09 12:58:51 -0600980void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600981{
982 char** configStrings = 0;
983 char* config = 0;
984 if (ConfigFile.size() > 0) {
985 configStrings = ReadFileData(ConfigFile.c_str());
986 if (configStrings)
987 config = *configStrings;
988 else {
989 printf("Error opening configuration file; will instead use the default configuration\n");
990 }
991 }
992
993 if (config == 0) {
994 config = new char[strlen(DefaultConfig) + 1];
995 strcpy(config, DefaultConfig);
996 }
997
998 const char* delims = " \t\n\r";
999 const char* token = strtok(config, delims);
1000 while (token) {
1001 const char* valueStr = strtok(0, delims);
1002 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1003 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1004 return;
1005 }
1006 int value = atoi(valueStr);
1007
1008 if (strcmp(token, "MaxLights") == 0)
1009 Resources.maxLights = value;
1010 else if (strcmp(token, "MaxClipPlanes") == 0)
1011 Resources.maxClipPlanes = value;
1012 else if (strcmp(token, "MaxTextureUnits") == 0)
1013 Resources.maxTextureUnits = value;
1014 else if (strcmp(token, "MaxTextureCoords") == 0)
1015 Resources.maxTextureCoords = value;
1016 else if (strcmp(token, "MaxVertexAttribs") == 0)
1017 Resources.maxVertexAttribs = value;
1018 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1019 Resources.maxVertexUniformComponents = value;
1020 else if (strcmp(token, "MaxVaryingFloats") == 0)
1021 Resources.maxVaryingFloats = value;
1022 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1023 Resources.maxVertexTextureImageUnits = value;
1024 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1025 Resources.maxCombinedTextureImageUnits = value;
1026 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1027 Resources.maxTextureImageUnits = value;
1028 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1029 Resources.maxFragmentUniformComponents = value;
1030 else if (strcmp(token, "MaxDrawBuffers") == 0)
1031 Resources.maxDrawBuffers = value;
1032 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1033 Resources.maxVertexUniformVectors = value;
1034 else if (strcmp(token, "MaxVaryingVectors") == 0)
1035 Resources.maxVaryingVectors = value;
1036 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1037 Resources.maxFragmentUniformVectors = value;
1038 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1039 Resources.maxVertexOutputVectors = value;
1040 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1041 Resources.maxFragmentInputVectors = value;
1042 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1043 Resources.minProgramTexelOffset = value;
1044 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1045 Resources.maxProgramTexelOffset = value;
1046 else if (strcmp(token, "MaxClipDistances") == 0)
1047 Resources.maxClipDistances = value;
1048 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1049 Resources.maxComputeWorkGroupCountX = value;
1050 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1051 Resources.maxComputeWorkGroupCountY = value;
1052 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1053 Resources.maxComputeWorkGroupCountZ = value;
1054 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1055 Resources.maxComputeWorkGroupSizeX = value;
1056 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1057 Resources.maxComputeWorkGroupSizeY = value;
1058 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1059 Resources.maxComputeWorkGroupSizeZ = value;
1060 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1061 Resources.maxComputeUniformComponents = value;
1062 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1063 Resources.maxComputeTextureImageUnits = value;
1064 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1065 Resources.maxComputeImageUniforms = value;
1066 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1067 Resources.maxComputeAtomicCounters = value;
1068 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1069 Resources.maxComputeAtomicCounterBuffers = value;
1070 else if (strcmp(token, "MaxVaryingComponents") == 0)
1071 Resources.maxVaryingComponents = value;
1072 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1073 Resources.maxVertexOutputComponents = value;
1074 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1075 Resources.maxGeometryInputComponents = value;
1076 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1077 Resources.maxGeometryOutputComponents = value;
1078 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1079 Resources.maxFragmentInputComponents = value;
1080 else if (strcmp(token, "MaxImageUnits") == 0)
1081 Resources.maxImageUnits = value;
1082 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1083 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1084 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1085 Resources.maxCombinedShaderOutputResources = value;
1086 else if (strcmp(token, "MaxImageSamples") == 0)
1087 Resources.maxImageSamples = value;
1088 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1089 Resources.maxVertexImageUniforms = value;
1090 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1091 Resources.maxTessControlImageUniforms = value;
1092 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1093 Resources.maxTessEvaluationImageUniforms = value;
1094 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1095 Resources.maxGeometryImageUniforms = value;
1096 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1097 Resources.maxFragmentImageUniforms = value;
1098 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1099 Resources.maxCombinedImageUniforms = value;
1100 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1101 Resources.maxGeometryTextureImageUnits = value;
1102 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1103 Resources.maxGeometryOutputVertices = value;
1104 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1105 Resources.maxGeometryTotalOutputComponents = value;
1106 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1107 Resources.maxGeometryUniformComponents = value;
1108 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1109 Resources.maxGeometryVaryingComponents = value;
1110 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1111 Resources.maxTessControlInputComponents = value;
1112 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1113 Resources.maxTessControlOutputComponents = value;
1114 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1115 Resources.maxTessControlTextureImageUnits = value;
1116 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1117 Resources.maxTessControlUniformComponents = value;
1118 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1119 Resources.maxTessControlTotalOutputComponents = value;
1120 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1121 Resources.maxTessEvaluationInputComponents = value;
1122 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1123 Resources.maxTessEvaluationOutputComponents = value;
1124 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1125 Resources.maxTessEvaluationTextureImageUnits = value;
1126 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1127 Resources.maxTessEvaluationUniformComponents = value;
1128 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1129 Resources.maxTessPatchComponents = value;
1130 else if (strcmp(token, "MaxPatchVertices") == 0)
1131 Resources.maxPatchVertices = value;
1132 else if (strcmp(token, "MaxTessGenLevel") == 0)
1133 Resources.maxTessGenLevel = value;
1134 else if (strcmp(token, "MaxViewports") == 0)
1135 Resources.maxViewports = value;
1136 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1137 Resources.maxVertexAtomicCounters = value;
1138 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1139 Resources.maxTessControlAtomicCounters = value;
1140 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1141 Resources.maxTessEvaluationAtomicCounters = value;
1142 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1143 Resources.maxGeometryAtomicCounters = value;
1144 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1145 Resources.maxFragmentAtomicCounters = value;
1146 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1147 Resources.maxCombinedAtomicCounters = value;
1148 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1149 Resources.maxAtomicCounterBindings = value;
1150 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1151 Resources.maxVertexAtomicCounterBuffers = value;
1152 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1153 Resources.maxTessControlAtomicCounterBuffers = value;
1154 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1155 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1156 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1157 Resources.maxGeometryAtomicCounterBuffers = value;
1158 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1159 Resources.maxFragmentAtomicCounterBuffers = value;
1160 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1161 Resources.maxCombinedAtomicCounterBuffers = value;
1162 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1163 Resources.maxAtomicCounterBufferSize = value;
1164 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1165 Resources.maxTransformFeedbackBuffers = value;
1166 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1167 Resources.maxTransformFeedbackInterleavedComponents = value;
1168 else if (strcmp(token, "MaxCullDistances") == 0)
1169 Resources.maxCullDistances = value;
1170 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1171 Resources.maxCombinedClipAndCullDistances = value;
1172 else if (strcmp(token, "MaxSamples") == 0)
1173 Resources.maxSamples = value;
1174
1175 else if (strcmp(token, "nonInductiveForLoops") == 0)
1176 Resources.limits.nonInductiveForLoops = (value != 0);
1177 else if (strcmp(token, "whileLoops") == 0)
1178 Resources.limits.whileLoops = (value != 0);
1179 else if (strcmp(token, "doWhileLoops") == 0)
1180 Resources.limits.doWhileLoops = (value != 0);
1181 else if (strcmp(token, "generalUniformIndexing") == 0)
1182 Resources.limits.generalUniformIndexing = (value != 0);
1183 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1184 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1185 else if (strcmp(token, "generalVaryingIndexing") == 0)
1186 Resources.limits.generalVaryingIndexing = (value != 0);
1187 else if (strcmp(token, "generalSamplerIndexing") == 0)
1188 Resources.limits.generalSamplerIndexing = (value != 0);
1189 else if (strcmp(token, "generalVariableIndexing") == 0)
1190 Resources.limits.generalVariableIndexing = (value != 0);
1191 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1192 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1193 else
1194 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1195
1196 token = strtok(0, delims);
1197 }
1198 if (configStrings)
1199 FreeFileData(configStrings);
1200}
1201
Tony Barbour01999182015-04-09 12:58:51 -06001202void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001203{
1204 if (m_compile_options & EOptionRelaxedErrors)
1205 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1206 if (m_compile_options & EOptionIntermediate)
1207 messages = (EShMessages)(messages | EShMsgAST);
1208 if (m_compile_options & EOptionSuppressWarnings)
1209 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1210}
1211
1212//
1213// Malloc a string of sufficient size and read a string into it.
1214//
Tony Barbour01999182015-04-09 12:58:51 -06001215char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001216{
1217 FILE *in;
1218 #if defined(_WIN32) && defined(__GNUC__)
1219 in = fopen(fileName, "r");
1220 int errorCode = in ? 0 : 1;
1221 #else
1222 int errorCode = fopen_s(&in, fileName, "r");
1223 #endif
1224
1225 char *fdata;
1226 int count = 0;
1227 const int maxSourceStrings = 5;
1228 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1229
1230 if (errorCode) {
1231 printf("Error: unable to open input file: %s\n", fileName);
1232 return 0;
1233 }
1234
1235 while (fgetc(in) != EOF)
1236 count++;
1237
1238 fseek(in, 0, SEEK_SET);
1239
1240 if (!(fdata = (char*)malloc(count+2))) {
1241 printf("Error allocating memory\n");
1242 return 0;
1243 }
1244 if (fread(fdata,1,count, in)!=count) {
1245 printf("Error reading input file: %s\n", fileName);
1246 return 0;
1247 }
1248 fdata[count] = '\0';
1249 fclose(in);
1250 if (count == 0) {
1251 return_data[0]=(char*)malloc(count+2);
1252 return_data[0][0]='\0';
1253 m_num_shader_strings = 0;
1254 return return_data;
1255 } else
1256 m_num_shader_strings = 1;
1257
1258 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1259 int ptr_len=0,i=0;
1260 while(count>0){
1261 return_data[i]=(char*)malloc(len+2);
1262 memcpy(return_data[i],fdata+ptr_len,len);
1263 return_data[i][len]='\0';
1264 count-=(len);
1265 ptr_len+=(len);
1266 if(count<len){
1267 if(count==0){
1268 m_num_shader_strings=(i+1);
1269 break;
1270 }
1271 len = count;
1272 }
1273 ++i;
1274 }
1275 return return_data;
1276}
1277
Tony Barbour01999182015-04-09 12:58:51 -06001278void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001279{
1280 for(int i=0;i<m_num_shader_strings;i++)
1281 free(data[i]);
1282}
1283
1284//
1285// Deduce the language from the filename. Files must end in one of the
1286// following extensions:
1287//
1288// .vert = vertex
1289// .tesc = tessellation control
1290// .tese = tessellation evaluation
1291// .geom = geometry
1292// .frag = fragment
1293// .comp = compute
1294//
Tony Barbour01999182015-04-09 12:58:51 -06001295EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001296{
1297 size_t ext = name.rfind('.');
1298 if (ext == std::string::npos) {
1299 return EShLangVertex;
1300 }
1301
1302 std::string suffix = name.substr(ext + 1, std::string::npos);
1303 if (suffix == "vert")
1304 return EShLangVertex;
1305 else if (suffix == "tesc")
1306 return EShLangTessControl;
1307 else if (suffix == "tese")
1308 return EShLangTessEvaluation;
1309 else if (suffix == "geom")
1310 return EShLangGeometry;
1311 else if (suffix == "frag")
1312 return EShLangFragment;
1313 else if (suffix == "comp")
1314 return EShLangCompute;
1315
1316 return EShLangVertex;
1317}
1318
1319//
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001320// Convert VK shader type to compiler's
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001321//
Tony Barbour8205d902015-04-16 15:59:00 -06001322EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001323{
1324 switch (shader_type) {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001325 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001326 return EShLangVertex;
1327
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001328 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001329 return EShLangTessControl;
1330
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001331 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001332 return EShLangTessEvaluation;
1333
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001334 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001335 return EShLangGeometry;
1336
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001337 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001338 return EShLangFragment;
1339
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001340 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001341 return EShLangCompute;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001342
Chia-I Wubbdeacc2014-12-15 23:50:11 +08001343 default:
1344 return EShLangVertex;
1345 }
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001346}
1347
1348
1349//
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001350// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001351// Return value of false means an error was encountered.
1352//
Tony Barbour8205d902015-04-16 15:59:00 -06001353bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001354 const char *pshader,
Cody Northropeb9130e2015-06-03 13:01:54 -06001355 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001356{
1357 glslang::TProgram& program = *new glslang::TProgram;
1358 const char *shaderStrings[1];
1359
1360 // TODO: Do we want to load a special config file depending on the
1361 // shader source? Optional name maybe?
1362 // SetConfigFile(fileName);
1363
1364 ProcessConfigFile();
1365
1366 EShMessages messages = EShMsgDefault;
1367 SetMessageOptions(messages);
1368
1369 EShLanguage stage = FindLanguage(shader_type);
1370 glslang::TShader* shader = new glslang::TShader(stage);
1371
1372 shaderStrings[0] = pshader;
1373 shader->setStrings(shaderStrings, 1);
1374
1375 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1376
Cody Northropad306f02014-11-03 12:54:37 -07001377 if (! (m_compile_options & EOptionSuppressInfolog)) {
1378 puts(shader->getInfoLog());
1379 puts(shader->getInfoDebugLog());
1380 }
1381
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001382 return false; // something didn't work
1383 }
1384
1385 program.addShader(shader);
1386
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001387
1388 //
1389 // Program-level processing...
1390 //
1391
Cody Northropad306f02014-11-03 12:54:37 -07001392 if (! program.link(messages)) {
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001393
Cody Northropad306f02014-11-03 12:54:37 -07001394 if (! (m_compile_options & EOptionSuppressInfolog)) {
1395 puts(shader->getInfoLog());
1396 puts(shader->getInfoDebugLog());
1397 }
1398
1399 return false;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001400 }
1401
1402 if (m_compile_options & EOptionDumpReflection) {
1403 program.buildReflection();
1404 program.dumpReflection();
1405 }
1406
Cody Northropeb9130e2015-06-03 13:01:54 -06001407 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1408
1409 //
1410 // Test the different modes of SPIR-V modification
1411 //
1412 if (this->m_canonicalize_spv) {
1413 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1414 }
1415
1416 if (this->m_strip_spv) {
1417 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1418 }
1419
1420 if (this->m_do_everything_spv) {
1421 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1422 }
1423
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001424
1425 return true;
1426}
1427
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001428
1429
Tony Barbour01999182015-04-09 12:58:51 -06001430VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001431 m_width( 0 ),
1432 m_height( 0 ),
Chia-I Wub2c2dea2014-12-15 23:29:34 +08001433 m_data( NULL ),
1434 m_data_size( 0 )
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001435{
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001436}
1437
Tony Barbour01999182015-04-09 12:58:51 -06001438VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001439{
1440
1441}
1442
Tony Barbour01999182015-04-09 12:58:51 -06001443VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001444{
1445 m_title = copyin.m_title;
1446 m_width = copyin.m_width;
1447 m_height = copyin.m_height;
1448 m_data_size = copyin.m_data_size;
1449 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1450}
1451
Tony Barbour01999182015-04-09 12:58:51 -06001452ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001453{
Tony Barbour01999182015-04-09 12:58:51 -06001454 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1455 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001456 return output;
1457}
1458
Tony Barbour01999182015-04-09 12:58:51 -06001459VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001460{
1461 m_title = rhs.m_title;
1462 m_width = rhs.m_width;
1463 m_height = rhs.m_height;
1464 m_data_size = rhs.m_data_size;
1465 m_data = rhs.m_data;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001466 return *this;
1467}
1468
Tony Barbour01999182015-04-09 12:58:51 -06001469int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001470{
1471 if( this->m_data != rhs.m_data) return 0;
1472 return 1;
1473}
1474
1475// This function is required for built-in STL list functions like sort
Tony Barbour01999182015-04-09 12:58:51 -06001476int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001477{
1478 if( this->m_data_size < rhs.m_data_size ) return 1;
1479 return 0;
1480}
1481