blob: a6daf42e4f8c32f924a05ca418dd1675e734b30f [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>
Ian Elliott331f4e82015-07-06 14:33:04 -060031#include "vk_wsi_swapchain.h"
32#include "vk_wsi_device_swapchain.h"
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -060033
Tony Barbour25e3b832015-05-20 16:53:31 -060034#if defined(PATH_MAX) && !defined(MAX_PATH)
35#define MAX_PATH PATH_MAX
36#endif
37
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -060038// Command-line options
39enum TOptions {
40 EOptionNone = 0x000,
41 EOptionIntermediate = 0x001,
42 EOptionSuppressInfolog = 0x002,
43 EOptionMemoryLeakMode = 0x004,
44 EOptionRelaxedErrors = 0x008,
45 EOptionGiveWarnings = 0x010,
46 EOptionLinkProgram = 0x020,
47 EOptionMultiThreaded = 0x040,
48 EOptionDumpConfig = 0x080,
49 EOptionDumpReflection = 0x100,
50 EOptionSuppressWarnings = 0x200,
51 EOptionDumpVersions = 0x400,
Cody Northropacfb0492015-03-17 15:55:58 -060052 EOptionSpv = 0x800,
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -060053 EOptionDefaultDesktop = 0x1000,
54};
55
Chia-I Wu5b66aa52015-04-16 22:02:10 +080056class TestFrameworkVkPresent
57{
58public:
59 TestFrameworkVkPresent(vk_testing::Device &device);
60
61 void Run();
Jon Ashburncedc15f2015-05-21 18:13:33 -060062 void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst);
Chia-I Wu5b66aa52015-04-16 22:02:10 +080063 void CreateMyWindow();
64 void CreateSwapChain();
65 void TearDown();
Tony Barbour25e3b832015-05-20 16:53:31 -060066#ifdef _WIN32
67 static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
68#endif
69
Chia-I Wu5b66aa52015-04-16 22:02:10 +080070
71protected:
72 vk_testing::Device &m_device;
73 vk_testing::Queue &m_queue;
74 vk_testing::CmdBuffer m_cmdbuf;
75
76private:
Tony Barbour25e3b832015-05-20 16:53:31 -060077#ifdef _WIN32
78 HINSTANCE m_connection; // hInstance - Windows Instance
79 HWND m_window; // hWnd - window handle
80
81#else
Chia-I Wu5b66aa52015-04-16 22:02:10 +080082 xcb_connection_t *m_connection;
83 xcb_screen_t *m_screen;
84 xcb_window_t m_window;
85 xcb_intern_atom_reply_t *m_atom_wm_delete_window;
Tony Barbour25e3b832015-05-20 16:53:31 -060086#endif
Courtney Goeltzenleuchterec69b9c2015-04-22 10:09:35 -060087 std::list<VkTestImageRecord> m_images;
Chia-I Wu5b66aa52015-04-16 22:02:10 +080088
Jon Ashburncedc15f2015-05-21 18:13:33 -060089 PFN_vkCreateSwapChainWSI m_fpCreateSwapChainWSI;
90 PFN_vkDestroySwapChainWSI m_fpDestroySwapChainWSI;
91 PFN_vkGetSwapChainInfoWSI m_fpGetSwapChainInfoWSI;
92 PFN_vkQueuePresentWSI m_fpQueuePresentWSI;
93
Chia-I Wu5b66aa52015-04-16 22:02:10 +080094 VkSwapChainWSI m_swap_chain;
Ian Elliott331f4e82015-07-06 14:33:04 -060095 std::vector<VkSwapChainImagePropertiesWSI> m_persistent_images;
Tony-LunarGf05ba082015-05-19 14:08:26 -060096 int m_current_buffer;
Chia-I Wu5b66aa52015-04-16 22:02:10 +080097
98 bool m_quit;
99 bool m_pause;
100
Tony Barbour8bef8ee2015-05-22 09:44:58 -0600101 int m_width;
102 int m_height;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800103
104 std::list<VkTestImageRecord>::iterator m_display_image;
105
106 void Display();
107 void HandleEvent(xcb_generic_event_t *event);
108};
109
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600110#ifndef _WIN32
111
112#include <errno.h>
113
114int fopen_s(
115 FILE** pFile,
116 const char* filename,
117 const char* mode
118)
119{
120 if (!pFile || !filename || !mode) {
121 return EINVAL;
122 }
123
124 FILE* f = fopen(filename, mode);
125 if (! f) {
126 if (errno != 0) {
127 return errno;
128 } else {
129 return ENOENT;
130 }
131 }
132 *pFile = f;
133
134 return 0;
135}
136
137#endif
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600138
Tony Barbour25e3b832015-05-20 16:53:31 -0600139
140
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600141// Set up environment for GLSL compiler
142// Must be done once per process
143void TestEnvironment::SetUp()
144{
Cody Northropacfb0492015-03-17 15:55:58 -0600145 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600146 glslang::InitializeProcess();
Chia-I Wu1c9869e2014-12-28 14:27:28 +0800147
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600148 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600149}
150
151void TestEnvironment::TearDown()
152{
153 glslang::FinalizeProcess();
154}
155
Tony Barbour01999182015-04-09 12:58:51 -0600156VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600157 m_compile_options( 0 ),
158 m_num_shader_strings( 0 )
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600159{
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600160
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600161}
162
Tony Barbour01999182015-04-09 12:58:51 -0600163VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600164{
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600165
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600166}
167
168// Define all the static elements
Cody Northropa392a292015-06-09 13:00:45 -0600169bool VkTestFramework::m_show_images = false;
170bool VkTestFramework::m_save_images = false;
171bool VkTestFramework::m_compare_images = false;
172bool VkTestFramework::m_use_glsl = false;
173bool VkTestFramework::m_canonicalize_spv = false;
174bool VkTestFramework::m_strip_spv = false;
Cody Northropeb9130e2015-06-03 13:01:54 -0600175bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour01999182015-04-09 12:58:51 -0600176int VkTestFramework::m_width = 0;
177int VkTestFramework::m_height = 0;
178std::list<VkTestImageRecord> VkTestFramework::m_images;
179std::list<VkTestImageRecord>::iterator VkTestFramework::m_display_image;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600180int m_display_image_idx = 0;
181
Cody Northrop1cfbd172015-06-03 16:49:20 -0600182bool VkTestFramework::optionMatch(const char* option, char* optionLine)
183{
184 if (strncmp(option, optionLine, strlen(option)) == 0)
185 return true;
186 else
187 return false;
188}
189
Tony Barbour01999182015-04-09 12:58:51 -0600190void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600191{
192 int i, n;
193
Cody Northrop1cfbd172015-06-03 16:49:20 -0600194 for (i=1, n=1; i< *argc; i++) {
195 if (optionMatch("--show-images", argv[i]))
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600196 m_show_images = true;
Cody Northrop1cfbd172015-06-03 16:49:20 -0600197 else if (optionMatch("--save-images", argv[i]))
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600198 m_save_images = true;
Cody Northrop1cfbd172015-06-03 16:49:20 -0600199 else if (optionMatch("--no-SPV", argv[i]))
200 m_use_glsl = true;
201 else if (optionMatch("--strip-SPV", argv[i]))
202 m_strip_spv = true;
203 else if (optionMatch("--canonicalize-SPV", argv[i]))
204 m_canonicalize_spv = true;
205 else if (optionMatch("--compare-images", argv[i]))
Tony Barbour32f368c2014-10-30 14:29:04 -0600206 m_compare_images = true;
Tony Barbour32f368c2014-10-30 14:29:04 -0600207
Cody Northrop1cfbd172015-06-03 16:49:20 -0600208 else if (optionMatch("--help", argv[i]) ||
209 optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchterb7f26e02014-12-02 13:13:10 -0700210 printf("\nOther options:\n");
211 printf("\t--show-images\n"
212 "\t\tDisplay test images in viewer after tests complete.\n");
213 printf("\t--save-images\n"
214 "\t\tSave tests images as ppm files in current working directory.\n"
215 "\t\tUsed to generate golden images for compare-images.\n");
216 printf("\t--compare-images\n"
217 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barbour0e4235d2014-12-11 09:52:49 -0700218 "\t\tAlso saves the generated test image in current working\n"
219 "\t\t\tdirectory but only if the image is different from the golden\n"
220 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
221 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchterb7f26e02014-12-02 13:13:10 -0700222 "\t\tSignal test failure if different.\n");
Cody Northropacfb0492015-03-17 15:55:58 -0600223 printf("\t--no-SPV\n"
224 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop1cfbd172015-06-03 16:49:20 -0600225 printf("\t--strip-SPV\n"
Cody Northrop1e056dd2015-07-13 12:48:41 -0600226 "\t\tStrip SPIR-V debug information (line numbers, names, etc).\n");
Cody Northrop1cfbd172015-06-03 16:49:20 -0600227 printf("\t--canonicalize-SPV\n"
Cody Northrop1e056dd2015-07-13 12:48:41 -0600228 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
Cody Northrop1cfbd172015-06-03 16:49:20 -0600229 exit(0);
230 } else {
231 printf("\nUnrecognized option: %s\n", argv[i]);
232 printf("\nUse --help or -h for option list.\n");
Tony Barbour772c5ef2014-12-10 17:00:20 -0700233 exit(0);
Courtney Goeltzenleuchterb7f26e02014-12-02 13:13:10 -0700234 }
235
Cody Northrop1cfbd172015-06-03 16:49:20 -0600236 /*
237 * Since the above "consume" inputs, update argv
238 * so that it contains the trimmed list of args for glutInit
239 */
240
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600241 argv[n] = argv[i];
242 n++;
243 }
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600244}
245
Tony Barbour01999182015-04-09 12:58:51 -0600246void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600247{
248 string filename;
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600249 VkResult err;
Tony Barbour8bef8ee2015-05-22 09:44:58 -0600250 uint32_t x, y;
Tony Barbour01999182015-04-09 12:58:51 -0600251 VkImageObj displayImage(image->device());
Tony Barbour94310562015-04-22 15:10:33 -0600252 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbouredc49d92015-04-02 14:02:33 -0600253
Tony Barboura7ec3ba2015-07-21 17:01:42 -0600254 displayImage.init(image->extent().width, image->extent().height, image->format(), VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT, VK_IMAGE_TILING_LINEAR, reqs);
Tony Barbouredc49d92015-04-02 14:02:33 -0600255 displayImage.CopyImage(*image);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600256
257 filename.append(basename);
258 filename.append(".ppm");
Tony Barbour25e3b832015-05-20 16:53:31 -0600259
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600260 const VkImageSubresource sr = {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600261 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600262 };
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600263 VkSubresourceLayout sr_layout;
Tony Barbour25e3b832015-05-20 16:53:31 -0600264
Tony Barbour426b9052015-06-24 16:06:58 -0600265 err = vkGetImageSubresourceLayout(image->device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600266 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600267
Tony Barbouredc49d92015-04-02 14:02:33 -0600268 char *ptr;
Chia-I Wuf4aed6c2015-07-03 13:44:34 +0800269 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600270 ptr += sr_layout.offset;
Tony Barbour25e3b832015-05-20 16:53:31 -0600271 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600272 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
273
274 file << "P6\n";
Tony Barbouredc49d92015-04-02 14:02:33 -0600275 file << displayImage.width() << "\n";
276 file << displayImage.height() << "\n";
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600277 file << 255 << "\n";
278
Tony Barbouredc49d92015-04-02 14:02:33 -0600279 for (y = 0; y < displayImage.height(); y++) {
Tony Barboure2668672015-02-25 11:25:11 -0700280 const int *row = (const int *) ptr;
281 int swapped;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600282
Tony Barbour8205d902015-04-16 15:59:00 -0600283 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboure2668672015-02-25 11:25:11 -0700284 {
Tony Barbouredc49d92015-04-02 14:02:33 -0600285 for (x = 0; x < displayImage.width(); x++) {
Tony Barboure2668672015-02-25 11:25:11 -0700286 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
287 file.write((char *) &swapped, 3);
288 row++;
289 }
290 }
Tony Barbour8205d902015-04-16 15:59:00 -0600291 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboure2668672015-02-25 11:25:11 -0700292 {
Tony Barbouredc49d92015-04-02 14:02:33 -0600293 for (x = 0; x < displayImage.width(); x++) {
Tony Barboure2668672015-02-25 11:25:11 -0700294 file.write((char *) row, 3);
295 row++;
296 }
297 }
298 else {
299 printf("Unrecognized image format - will not write image files");
300 break;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600301 }
302
303 ptr += sr_layout.rowPitch;
304 }
305
306 file.close();
Chia-I Wuf4aed6c2015-07-03 13:44:34 +0800307 displayImage.UnmapMemory();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600308}
309
Tony Barbour01999182015-04-09 12:58:51 -0600310void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour32f368c2014-10-30 14:29:04 -0600311{
312
313 MagickWand *magick_wand_1;
314 MagickWand *magick_wand_2;
315 MagickWand *compare_wand;
316 MagickBooleanType status;
Tony Barbour25e3b832015-05-20 16:53:31 -0600317 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour32f368c2014-10-30 14:29:04 -0600318 double differenz;
319
Tony Barbour772c5ef2014-12-10 17:00:20 -0700320 if (getenv("RENDERTEST_GOLDEN_DIR"))
321 {
322 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
323 }
324
Tony Barbour32f368c2014-10-30 14:29:04 -0600325 MagickWandGenesis();
326 magick_wand_1=NewMagickWand();
327 sprintf(testimage,"%s.ppm",basename);
328 status=MagickReadImage(magick_wand_1,testimage);
Tony Barbour8bef8ee2015-05-22 09:44:58 -0600329 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour32f368c2014-10-30 14:29:04 -0600330
331
332 MagickWandGenesis();
333 magick_wand_2=NewMagickWand();
Tony Barbour772c5ef2014-12-10 17:00:20 -0700334 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour32f368c2014-10-30 14:29:04 -0600335 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour8bef8ee2015-05-22 09:44:58 -0600336 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour32f368c2014-10-30 14:29:04 -0600337
Tony Barbour32f368c2014-10-30 14:29:04 -0600338 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
339 if (differenz != 0.0)
340 {
341 char difference[256];
342
343 sprintf(difference,"%s-diff.ppm",basename);
344 status = MagickWriteImage(compare_wand, difference);
345 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
346 }
347 DestroyMagickWand(compare_wand);
348
349 DestroyMagickWand(magick_wand_1);
350 DestroyMagickWand(magick_wand_2);
351 MagickWandTerminus();
Courtney Goeltzenleuchterdfa97b82014-12-05 15:41:02 -0700352
353 if (differenz == 0.0)
354 {
355 /*
356 * If test image and golden image match, we do not need to
357 * keep around the test image.
358 */
359 remove(testimage);
360 }
Tony Barbour32f368c2014-10-30 14:29:04 -0600361}
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600362
Tony Barbour01999182015-04-09 12:58:51 -0600363void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600364{
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600365 VkResult err;
Courtney Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600366 VkSubresourceLayout sr_layout;
367 char *ptr;
368 VkTestImageRecord record;
Courtney Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600369 VkImageObj displayImage(image->device());
370 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
371
Cody Northrop025cbb12015-06-18 17:05:15 -0600372 displayImage.init(image->extent().width, image->extent().height, image->format(), VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT, VK_IMAGE_TILING_LINEAR, reqs);
373
Courtney Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600374 displayImage.CopyImage(*image);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600375
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600376 const VkImageSubresource sr = {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600377 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600378 };
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600379
Tony Barbour426b9052015-06-24 16:06:58 -0600380 err = vkGetImageSubresourceLayout(displayImage.device()->device(), displayImage.image(), &sr, &sr_layout);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600381 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600382
Chia-I Wuf4aed6c2015-07-03 13:44:34 +0800383 ptr = (char *) displayImage.MapMemory();
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600384 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600385
386 ptr += sr_layout.offset;
387
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600388 record.m_title.append(comment);
Courtney Goeltzenleuchtere5871c72015-04-29 10:53:31 -0600389 record.m_width = displayImage.width();
390 record.m_height = displayImage.height();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600391 // TODO: Need to make this more robust to handle different image formats
Tony-LunarGf05ba082015-05-19 14:08:26 -0600392 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600393 record.m_data = malloc(record.m_data_size);
394 memcpy(record.m_data, ptr, record.m_data_size);
395 m_images.push_back(record);
396 m_display_image = --m_images.end();
397
Chia-I Wuf4aed6c2015-07-03 13:44:34 +0800398 displayImage.UnmapMemory();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600399}
400
Tony Barbour01999182015-04-09 12:58:51 -0600401void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour32f368c2014-10-30 14:29:04 -0600402{
Courtney Goeltzenleuchtercd5ed1e2015-04-02 14:17:44 -0600403 for (int32_t i = 0; i < images.size(); i++) {
404 RecordImage(images[i]);
Tony Barbour32f368c2014-10-30 14:29:04 -0600405 }
406}
407
Tony Barbour01999182015-04-09 12:58:51 -0600408void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600409{
410 const ::testing::TestInfo* const test_info =
411 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour32f368c2014-10-30 14:29:04 -0600412 ostringstream filestream;
413 string filename;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600414
Tony Barbour32f368c2014-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 Barboura48b0812014-11-18 17:02:36 -0700420 m_frameNum = 2;
421 filename = filestream.str();
Tony Barbour32f368c2014-10-30 14:29:04 -0600422 }
423 else {
424 filestream << test_info->name() << "-" << m_frameNum;
425 m_frameNum++;
Tony Barboura48b0812014-11-18 17:02:36 -0700426 filename = filestream.str();
Tony Barbour32f368c2014-10-30 14:29:04 -0600427 }
428
Tony Barbour32f368c2014-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 Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600436 }
437
438 if (m_show_images) {
Courtney Goeltzenleuchtere5409342014-10-08 14:26:40 -0600439 Show(test_info->name(), image);
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600440 }
441}
442
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800443TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
444 m_device(device),
Courtney Goeltzenleuchterdd745fd2015-03-05 16:47:18 -0700445 m_queue(*m_device.graphics_queues()[0]),
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600446 m_cmdbuf(m_device, vk_testing::CmdBuffer::create_info(m_device.graphics_queue_node_index_))
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600447{
Tony Barbouref20d322015-02-25 12:28:39 -0700448 m_quit = false;
449 m_pause = false;
450 m_width = 0;
451 m_height = 0;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600452}
453
Tony Barbour01999182015-04-09 12:58:51 -0600454void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600455{
Tony Barbour22a30862015-04-22 09:02:32 -0600456 VkResult U_ASSERT_ONLY err;
Tony-LunarGf05ba082015-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 Northropd0e7d222015-06-22 14:56:14 -0600465 buf.init_as_src(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
Chia-I Wuf4aed6c2015-07-03 13:44:34 +0800466 dest_ptr = buf.memory().map();
Tony-LunarGf05ba082015-05-19 14:08:26 -0600467 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
Chia-I Wuf4aed6c2015-07-03 13:44:34 +0800468 buf.memory().unmap();
Tony-LunarGf05ba082015-05-19 14:08:26 -0600469
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
Chia-I Wu78c2a352015-07-03 11:49:42 +0800477 vkCmdCopyBufferToImage(m_cmdbuf.handle(),
Chia-I Wuf4aed6c2015-07-03 13:44:34 +0800478 buf.handle(),
Tony-LunarGf05ba082015-05-19 14:08:26 -0600479 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];
Chia-I Wu78c2a352015-07-03 11:49:42 +0800484 cmdBufs[0] = m_cmdbuf.handle();
Tony-LunarGf05ba082015-05-19 14:08:26 -0600485
Tony Barboure84a8d62015-07-10 14:10:27 -0600486 VkFence nullFence = { VK_NULL_HANDLE };
487 vkQueueSubmit(m_queue.handle(), 1, cmdBufs, nullFence);
Tony-LunarGf05ba082015-05-19 14:08:26 -0600488 m_queue.wait();
Tony Barbouref20d322015-02-25 12:28:39 -0700489
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800490 VkPresentInfoWSI present = {};
Ian Elliott331f4e82015-07-06 14:33:04 -0600491 // FIXME: WRITE THE REAL CODE!!!
492 // FIXME: WRITE THE REAL CODE!!!
493 // FIXME: WRITE THE REAL CODE!!!
494 // FIXME: WRITE THE REAL CODE!!!
495 present.sType = VK_STRUCTURE_TYPE_QUEUE_PRESENT_INFO_WSI;
Tony Barbouref20d322015-02-25 12:28:39 -0700496
Tony Barbour25e3b832015-05-20 16:53:31 -0600497#ifndef _WIN32
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800498 xcb_change_property (m_connection,
Tony Barbouref20d322015-02-25 12:28:39 -0700499 XCB_PROP_MODE_REPLACE,
500 m_window,
501 XCB_ATOM_WM_NAME,
502 XCB_ATOM_STRING,
503 8,
504 m_display_image->m_title.size(),
505 m_display_image->m_title.c_str());
Tony Barbour25e3b832015-05-20 16:53:31 -0600506#endif
Jon Ashburncedc15f2015-05-21 18:13:33 -0600507
Chia-I Wuf2862c72015-07-03 10:53:18 +0800508 err = m_fpQueuePresentWSI(m_queue.handle(), &present);
Tony Barbouref20d322015-02-25 12:28:39 -0700509 assert(!err);
510
511 m_queue.wait();
Tony-LunarGf05ba082015-05-19 14:08:26 -0600512 m_current_buffer = (m_current_buffer + 1) % 2;
Tony Barbouref20d322015-02-25 12:28:39 -0700513
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600514}
515
Tony Barbour25e3b832015-05-20 16:53:31 -0600516#ifdef _WIN32
Tony-LunarGf05ba082015-05-19 14:08:26 -0600517# define PREVIOUSLY_DOWN 1<<29
Tony Barbour25e3b832015-05-20 16:53:31 -0600518// MS-Windows event handling function:
519LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
520 UINT uMsg,
521 WPARAM wParam,
522 LPARAM lParam)
523{
524
525 switch(uMsg)
526 {
527 case WM_CLOSE:
528 PostQuitMessage(0);
529 break;
530
531 case WM_PAINT:
532 {
533 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
534 if (me) {
Tony-LunarGf05ba082015-05-19 14:08:26 -0600535 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour25e3b832015-05-20 16:53:31 -0600536 me->Display();
537 }
538 }
Tony-LunarGf05ba082015-05-19 14:08:26 -0600539 break;
540
541 case WM_KEYDOWN:
542 {
543 if (lParam & (PREVIOUSLY_DOWN)){
544 break;
545 }
546 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
547 // the window, we put the this pointer into the window's user data so we could get it back now
548 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
549 switch (wParam)
550 {
551 case VK_ESCAPE: me->m_quit = true;
552 break;
553
554 case VK_LEFT: // left arrow key
555 if (me->m_display_image == me->m_images.begin()) {
556 me->m_display_image = --me->m_images.end();
557 }
558 else {
559 --me->m_display_image;
560 }
561 break;
562
563 case VK_RIGHT: // right arrow key
564 ++me->m_display_image;
565 if (me->m_display_image == me->m_images.end()) {
566 me->m_display_image = me->m_images.begin();
567 }
568 break;
569
570 default:
571 break;
572 }
573 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
574 me->Display();
575 }
Tony Barbour25e3b832015-05-20 16:53:31 -0600576 }
577 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
578}
579
580void TestFrameworkVkPresent::Run()
581{
582 MSG msg; // message
Tony Barbour25e3b832015-05-20 16:53:31 -0600583
Tony Barbour25e3b832015-05-20 16:53:31 -0600584 /* main message loop*/
Tony-LunarGf05ba082015-05-19 14:08:26 -0600585 while(! m_quit) {
586 GetMessage(&msg, m_window, 0, 0);
Tony Barbour25e3b832015-05-20 16:53:31 -0600587 if (msg.message == WM_QUIT) {
Tony-LunarGf05ba082015-05-19 14:08:26 -0600588 m_quit = true; //if found, quit app
Tony Barbour25e3b832015-05-20 16:53:31 -0600589 } else {
590 /* Translate and dispatch to event queue*/
591 TranslateMessage(&msg);
592 DispatchMessage(&msg);
593 }
594 }
595}
596
597#else
Tony Barbour01999182015-04-09 12:58:51 -0600598void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600599{
Tony Barbour3a5cda02015-04-02 15:48:24 -0600600 uint8_t event_code = event->response_type & 0x7f;
Tony Barbouref20d322015-02-25 12:28:39 -0700601 switch (event_code) {
602 case XCB_EXPOSE:
603 Display(); // TODO: handle resize
604 break;
605 case XCB_CLIENT_MESSAGE:
606 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
607 (m_atom_wm_delete_window)->atom) {
608 m_quit = true;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600609 }
610 break;
Tony Barbouref20d322015-02-25 12:28:39 -0700611 case XCB_KEY_RELEASE:
612 {
613 const xcb_key_release_event_t *key =
614 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600615
Tony Barbouref20d322015-02-25 12:28:39 -0700616 switch (key->detail) {
617 case 0x9: // Escape
618 m_quit = true;
619 break;
620 case 0x71: // left arrow key
621 if (m_display_image == m_images.begin()) {
622 m_display_image = --m_images.end();
623 } else {
624 --m_display_image;
625 }
626 break;
627 case 0x72: // right arrow key
628 ++m_display_image;
629 if (m_display_image == m_images.end()) {
630 m_display_image = m_images.begin();
631 }
632 break;
633 case 0x41:
634 m_pause = !m_pause;
635 break;
636 }
637 Display();
638 }
639 break;
640 default:
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600641 break;
642 }
Tony Barbouref20d322015-02-25 12:28:39 -0700643}
644
Tony Barbour01999182015-04-09 12:58:51 -0600645void TestFrameworkVkPresent::Run()
Tony Barbouref20d322015-02-25 12:28:39 -0700646{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800647 xcb_flush(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700648
649 while (! m_quit) {
650 xcb_generic_event_t *event;
651
652 if (m_pause) {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800653 event = xcb_wait_for_event(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700654 } else {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800655 event = xcb_poll_for_event(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700656 }
657 if (event) {
658 HandleEvent(event);
659 free(event);
660 }
661 }
662}
Tony Barbour25e3b832015-05-20 16:53:31 -0600663#endif // _WIN32
Tony Barbouref20d322015-02-25 12:28:39 -0700664
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800665void TestFrameworkVkPresent::CreateSwapChain()
Tony Barbouref20d322015-02-25 12:28:39 -0700666{
Tony Barbour22a30862015-04-22 09:02:32 -0600667 VkResult U_ASSERT_ONLY err;
Tony Barbouref20d322015-02-25 12:28:39 -0700668
Tony-LunarGf05ba082015-05-19 14:08:26 -0600669 m_display_image = m_images.begin();
670 m_current_buffer = 0;
671
Ian Elliott331f4e82015-07-06 14:33:04 -0600672 // FIXME: WRITE THE REAL CODE!!!
673 // FIXME: WRITE THE REAL CODE!!!
674 // FIXME: WRITE THE REAL CODE!!!
675 // FIXME: WRITE THE REAL CODE!!!
676 VkSurfaceDescriptionWindowWSI surface_description;
Tony Barbour9a3558d2015-07-28 10:23:02 -0600677
Ian Elliott331f4e82015-07-06 14:33:04 -0600678 surface_description.sType = VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_WSI;
679 surface_description.pNext = NULL;
680#ifdef _WIN32
681 surface_description.platform = VK_PLATFORM_WIN32_WSI;
682 surface_description.pPlatformHandle = m_connection;
683#else // _WIN32
Tony Barbour9a3558d2015-07-28 10:23:02 -0600684 VkPlatformHandleXcbWSI platform_handle_xcb;
Ian Elliott331f4e82015-07-06 14:33:04 -0600685 platform_handle_xcb.connection = m_connection;
686 platform_handle_xcb.root = m_screen->root;
687 surface_description.platform = VK_PLATFORM_XCB_WSI;
688 surface_description.pPlatformHandle = &platform_handle_xcb;
689#endif // _WIN32
690 surface_description.pPlatformWindow = (void *) (intptr_t) m_window;
691
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800692 VkSwapChainCreateInfoWSI swap_chain = {};
693 swap_chain.sType = VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI;
Ian Elliott331f4e82015-07-06 14:33:04 -0600694 swap_chain.pNext = NULL;
695 // FIXME: WRITE THE REAL CODE!!!
696 // FIXME: WRITE THE REAL CODE!!!
697 // FIXME: WRITE THE REAL CODE!!!
698 // FIXME: WRITE THE REAL CODE!!!
699 swap_chain.pSurfaceDescription =
700 (VkSurfaceDescriptionWSI*) &surface_description;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800701 swap_chain.imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
702 swap_chain.imageExtent.width = m_width;
703 swap_chain.imageExtent.height = m_height;
704 swap_chain.imageArraySize = 1;
Cody Northropdda0c172015-06-09 15:56:56 -0600705 // Note: Addition of color attachment is a workaround needed for some implementations
706 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT |
707 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800708
Chia-I Wua2636292015-07-03 10:41:20 +0800709 err = m_fpCreateSwapChainWSI(m_device.handle(), &swap_chain, &m_swap_chain);
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800710 assert(!err);
711
Ian Elliott331f4e82015-07-06 14:33:04 -0600712 VkSwapChainImagePropertiesWSI infos[2];
713 size_t size = sizeof(VkSwapChainImagePropertiesWSI) * m_images.size() * 2;
714 std::vector<VkSwapChainImagePropertiesWSI> persistent_images;
Jon Ashburncedc15f2015-05-21 18:13:33 -0600715 persistent_images.resize(m_images.size());
Ian Elliott331f4e82015-07-06 14:33:04 -0600716 err = m_fpGetSwapChainInfoWSI(m_device.handle(), m_swap_chain,
717 VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI,
Tony-LunarGf05ba082015-05-19 14:08:26 -0600718 &size, &infos);
Ian Elliott331f4e82015-07-06 14:33:04 -0600719 assert(!err && size == sizeof(VkSwapChainImagePropertiesWSI) * 2);
Tony-LunarGf05ba082015-05-19 14:08:26 -0600720 m_persistent_images.push_back(infos[0]);
721 m_persistent_images.push_back(infos[1]);
Tony Barbouref20d322015-02-25 12:28:39 -0700722}
723
Jon Ashburncedc15f2015-05-21 18:13:33 -0600724void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn, VkInstance inst)
Tony Barbouref20d322015-02-25 12:28:39 -0700725{
Jon Ashburncedc15f2015-05-21 18:13:33 -0600726 m_fpCreateSwapChainWSI = (PFN_vkCreateSwapChainWSI) vkGetInstanceProcAddr(inst, "vkCreateSwapChainWSI");
727 ASSERT_TRUE(m_fpCreateSwapChainWSI != NULL) << "vkGetInstanceProcAddr failed to find vkCreateSwapChainWSI";
728
729 m_fpDestroySwapChainWSI = (PFN_vkDestroySwapChainWSI) vkGetInstanceProcAddr(inst, "vkDestroySwapChainWSI");
730 ASSERT_TRUE(m_fpDestroySwapChainWSI != NULL) << "vkGetInstanceProcAddr failed to find vkDestroySwapChainWSI";
731
732 m_fpGetSwapChainInfoWSI = (PFN_vkGetSwapChainInfoWSI) vkGetInstanceProcAddr(inst, "vkGetSwapChainInfoWSI");
733 ASSERT_TRUE(m_fpGetSwapChainInfoWSI != NULL) << "vkGetInstanceProcAddr failed to find vkGetSwapChainInfoWSI";
734
735 m_fpQueuePresentWSI = (PFN_vkQueuePresentWSI) vkGetInstanceProcAddr(inst, "vkQueuePresentWSI");
736 ASSERT_TRUE(m_fpQueuePresentWSI != NULL) << "vkGetInstanceProcAddr failed to find vkQueuePresentWSI";
737
Tony Barbouref20d322015-02-25 12:28:39 -0700738 m_images = imagesIn;
739}
740
Tony Barbour25e3b832015-05-20 16:53:31 -0600741#ifdef _WIN32
742void TestFrameworkVkPresent::CreateMyWindow()
743{
744 WNDCLASSEX win_class;
745 // const ::testing::TestInfo* const test_info =
746 // ::testing::UnitTest::GetInstance()->current_test_info();
747 m_connection = GetModuleHandle(NULL);
748
749 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
750 it != m_images.end(); it++) {
751 if (m_width < it->m_width)
752 m_width = it->m_width;
753 if (m_height < it->m_height)
754 m_height = it->m_height;
755 }
756 // Initialize the window class structure:
757 win_class.cbSize = sizeof(WNDCLASSEX);
758 win_class.style = CS_HREDRAW | CS_VREDRAW;
759 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
760 win_class.cbClsExtra = 0;
761 win_class.cbWndExtra = 0;
762 win_class.hInstance = m_connection; // hInstance
763 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
764 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
765 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
766 win_class.lpszMenuName = NULL;
767 win_class.lpszClassName = "Test";
768 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
769 // Register window class:
770 if (!RegisterClassEx(&win_class)) {
771 // It didn't work, so try to give a useful error:
772 printf("Unexpected error trying to start the application!\n");
773 fflush(stdout);
774 exit(1);
775 }
776 // Create window with the registered class:
777 m_window = CreateWindowEx(0,
778 "Test", // class name
779 "Test", // app name
780 WS_OVERLAPPEDWINDOW | // window style
781 WS_VISIBLE |
782 WS_SYSMENU,
783 100,100, // x/y coords
784 m_width, // width
785 m_height, // height
786 NULL, // handle to parent
787 NULL, // handle to menu
788 m_connection, // hInstance
789 NULL); // no extra parameters
790
791 if (!m_window) {
792 // It didn't work, so try to give a useful error:
793 DWORD error = GetLastError();
794 char message[120];
795 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
796 MessageBox(NULL, message, "Error", MB_OK);
797 exit(1);
798 }
Tony-LunarGf05ba082015-05-19 14:08:26 -0600799 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
800 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour25e3b832015-05-20 16:53:31 -0600801}
802#else
Tony Barbour01999182015-04-09 12:58:51 -0600803void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbouref20d322015-02-25 12:28:39 -0700804{
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800805 const xcb_setup_t *setup;
806 xcb_screen_iterator_t iter;
807 int scr;
Tony Barbouref20d322015-02-25 12:28:39 -0700808 uint32_t value_mask, value_list[32];
809
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800810 m_connection = xcb_connect(NULL, &scr);
811
812 setup = xcb_get_setup(m_connection);
813 iter = xcb_setup_roots_iterator(setup);
814 while (scr-- > 0)
815 xcb_screen_next(&iter);
816
817 m_screen = iter.data;
818
819 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
820 it != m_images.end(); it++) {
821 if (m_width < it->m_width)
822 m_width = it->m_width;
823 if (m_height < it->m_height)
824 m_height = it->m_height;
825 }
826
827 m_window = xcb_generate_id(m_connection);
Tony Barbouref20d322015-02-25 12:28:39 -0700828
829 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800830 value_list[0] = m_screen->black_pixel;
Tony Barbouref20d322015-02-25 12:28:39 -0700831 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
832 XCB_EVENT_MASK_EXPOSURE |
833 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
834
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800835 xcb_create_window(m_connection,
Tony Barbouref20d322015-02-25 12:28:39 -0700836 XCB_COPY_FROM_PARENT,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800837 m_window, m_screen->root,
Tony Barbouref20d322015-02-25 12:28:39 -0700838 0, 0, m_width, m_height, 0,
839 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800840 m_screen->root_visual,
Tony Barbouref20d322015-02-25 12:28:39 -0700841 value_mask, value_list);
842
843 /* Magic code that will send notification when window is destroyed */
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800844 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbouref20d322015-02-25 12:28:39 -0700845 "WM_PROTOCOLS");
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800846 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbouref20d322015-02-25 12:28:39 -0700847
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800848 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
849 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbouref20d322015-02-25 12:28:39 -0700850
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800851 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbouref20d322015-02-25 12:28:39 -0700852 m_window, (*reply).atom, 4, 32, 1,
853 &(*m_atom_wm_delete_window).atom);
854 free(reply);
855
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800856 xcb_map_window(m_connection, m_window);
Tony Barbouref20d322015-02-25 12:28:39 -0700857}
Tony Barbour25e3b832015-05-20 16:53:31 -0600858#endif
Tony Barbouref20d322015-02-25 12:28:39 -0700859
Tony Barbour01999182015-04-09 12:58:51 -0600860void TestFrameworkVkPresent::TearDown()
Tony Barbouref20d322015-02-25 12:28:39 -0700861{
Ian Elliott331f4e82015-07-06 14:33:04 -0600862 m_fpDestroySwapChainWSI(m_device.handle(), m_swap_chain);
Tony Barbour25e3b832015-05-20 16:53:31 -0600863#ifndef _WIN32
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800864 xcb_destroy_window(m_connection, m_window);
865 xcb_disconnect(m_connection);
Tony Barbour25e3b832015-05-20 16:53:31 -0600866#endif
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600867}
868
Tony Barbour01999182015-04-09 12:58:51 -0600869void VkTestFramework::Finish()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600870{
871 if (m_images.size() == 0) return;
872
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800873 vk_testing::Environment env;
874 env.SetUp();
Tony Barbouref20d322015-02-25 12:28:39 -0700875 {
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800876 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbouref20d322015-02-25 12:28:39 -0700877
Jon Ashburncedc15f2015-05-21 18:13:33 -0600878 vkPresent.InitPresentFramework(m_images, env.get_instance());
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600879 vkPresent.CreateMyWindow();
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800880 vkPresent.CreateSwapChain();
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600881 vkPresent.Run();
882 vkPresent.TearDown();
Tony Barbouref20d322015-02-25 12:28:39 -0700883 }
Chia-I Wu5b66aa52015-04-16 22:02:10 +0800884 env.TearDown();
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600885}
886
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600887//
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600888// These are the default resources for TBuiltInResources, used for both
889// - parsing this string for the case where the user didn't supply one
890// - dumping out a template for user construction of a config file
891//
892static const char* DefaultConfig =
893 "MaxLights 32\n"
894 "MaxClipPlanes 6\n"
895 "MaxTextureUnits 32\n"
896 "MaxTextureCoords 32\n"
897 "MaxVertexAttribs 64\n"
898 "MaxVertexUniformComponents 4096\n"
899 "MaxVaryingFloats 64\n"
900 "MaxVertexTextureImageUnits 32\n"
901 "MaxCombinedTextureImageUnits 80\n"
902 "MaxTextureImageUnits 32\n"
903 "MaxFragmentUniformComponents 4096\n"
904 "MaxDrawBuffers 32\n"
905 "MaxVertexUniformVectors 128\n"
906 "MaxVaryingVectors 8\n"
907 "MaxFragmentUniformVectors 16\n"
908 "MaxVertexOutputVectors 16\n"
909 "MaxFragmentInputVectors 15\n"
910 "MinProgramTexelOffset -8\n"
911 "MaxProgramTexelOffset 7\n"
912 "MaxClipDistances 8\n"
913 "MaxComputeWorkGroupCountX 65535\n"
914 "MaxComputeWorkGroupCountY 65535\n"
915 "MaxComputeWorkGroupCountZ 65535\n"
916 "MaxComputeWorkGroupSizeX 1024\n"
917 "MaxComputeWorkGroupSizeY 1024\n"
918 "MaxComputeWorkGroupSizeZ 64\n"
919 "MaxComputeUniformComponents 1024\n"
920 "MaxComputeTextureImageUnits 16\n"
921 "MaxComputeImageUniforms 8\n"
922 "MaxComputeAtomicCounters 8\n"
923 "MaxComputeAtomicCounterBuffers 1\n"
924 "MaxVaryingComponents 60\n"
925 "MaxVertexOutputComponents 64\n"
926 "MaxGeometryInputComponents 64\n"
927 "MaxGeometryOutputComponents 128\n"
928 "MaxFragmentInputComponents 128\n"
929 "MaxImageUnits 8\n"
930 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
931 "MaxCombinedShaderOutputResources 8\n"
932 "MaxImageSamples 0\n"
933 "MaxVertexImageUniforms 0\n"
934 "MaxTessControlImageUniforms 0\n"
935 "MaxTessEvaluationImageUniforms 0\n"
936 "MaxGeometryImageUniforms 0\n"
937 "MaxFragmentImageUniforms 8\n"
938 "MaxCombinedImageUniforms 8\n"
939 "MaxGeometryTextureImageUnits 16\n"
940 "MaxGeometryOutputVertices 256\n"
941 "MaxGeometryTotalOutputComponents 1024\n"
942 "MaxGeometryUniformComponents 1024\n"
943 "MaxGeometryVaryingComponents 64\n"
944 "MaxTessControlInputComponents 128\n"
945 "MaxTessControlOutputComponents 128\n"
946 "MaxTessControlTextureImageUnits 16\n"
947 "MaxTessControlUniformComponents 1024\n"
948 "MaxTessControlTotalOutputComponents 4096\n"
949 "MaxTessEvaluationInputComponents 128\n"
950 "MaxTessEvaluationOutputComponents 128\n"
951 "MaxTessEvaluationTextureImageUnits 16\n"
952 "MaxTessEvaluationUniformComponents 1024\n"
953 "MaxTessPatchComponents 120\n"
954 "MaxPatchVertices 32\n"
955 "MaxTessGenLevel 64\n"
956 "MaxViewports 16\n"
957 "MaxVertexAtomicCounters 0\n"
958 "MaxTessControlAtomicCounters 0\n"
959 "MaxTessEvaluationAtomicCounters 0\n"
960 "MaxGeometryAtomicCounters 0\n"
961 "MaxFragmentAtomicCounters 8\n"
962 "MaxCombinedAtomicCounters 8\n"
963 "MaxAtomicCounterBindings 1\n"
964 "MaxVertexAtomicCounterBuffers 0\n"
965 "MaxTessControlAtomicCounterBuffers 0\n"
966 "MaxTessEvaluationAtomicCounterBuffers 0\n"
967 "MaxGeometryAtomicCounterBuffers 0\n"
968 "MaxFragmentAtomicCounterBuffers 1\n"
969 "MaxCombinedAtomicCounterBuffers 1\n"
970 "MaxAtomicCounterBufferSize 16384\n"
971 "MaxTransformFeedbackBuffers 4\n"
972 "MaxTransformFeedbackInterleavedComponents 64\n"
973 "MaxCullDistances 8\n"
974 "MaxCombinedClipAndCullDistances 8\n"
975 "MaxSamples 4\n"
976
977 "nonInductiveForLoops 1\n"
978 "whileLoops 1\n"
979 "doWhileLoops 1\n"
980 "generalUniformIndexing 1\n"
981 "generalAttributeMatrixVectorIndexing 1\n"
982 "generalVaryingIndexing 1\n"
983 "generalSamplerIndexing 1\n"
984 "generalVariableIndexing 1\n"
985 "generalConstantMatrixVectorIndexing 1\n"
986 ;
987
988//
989// *.conf => this is a config file that can set limits/resources
990//
Tony Barbour01999182015-04-09 12:58:51 -0600991bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600992{
993 if (name.size() < 5)
994 return false;
995
996 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
997 ConfigFile = name;
998 return true;
999 }
1000
1001 return false;
1002}
1003
1004//
1005// Parse either a .conf file provided by the user or the default string above.
1006//
Tony Barbour01999182015-04-09 12:58:51 -06001007void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001008{
1009 char** configStrings = 0;
1010 char* config = 0;
1011 if (ConfigFile.size() > 0) {
1012 configStrings = ReadFileData(ConfigFile.c_str());
1013 if (configStrings)
1014 config = *configStrings;
1015 else {
1016 printf("Error opening configuration file; will instead use the default configuration\n");
1017 }
1018 }
1019
1020 if (config == 0) {
1021 config = new char[strlen(DefaultConfig) + 1];
1022 strcpy(config, DefaultConfig);
1023 }
1024
1025 const char* delims = " \t\n\r";
1026 const char* token = strtok(config, delims);
1027 while (token) {
1028 const char* valueStr = strtok(0, delims);
1029 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
1030 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
1031 return;
1032 }
1033 int value = atoi(valueStr);
1034
1035 if (strcmp(token, "MaxLights") == 0)
1036 Resources.maxLights = value;
1037 else if (strcmp(token, "MaxClipPlanes") == 0)
1038 Resources.maxClipPlanes = value;
1039 else if (strcmp(token, "MaxTextureUnits") == 0)
1040 Resources.maxTextureUnits = value;
1041 else if (strcmp(token, "MaxTextureCoords") == 0)
1042 Resources.maxTextureCoords = value;
1043 else if (strcmp(token, "MaxVertexAttribs") == 0)
1044 Resources.maxVertexAttribs = value;
1045 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1046 Resources.maxVertexUniformComponents = value;
1047 else if (strcmp(token, "MaxVaryingFloats") == 0)
1048 Resources.maxVaryingFloats = value;
1049 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1050 Resources.maxVertexTextureImageUnits = value;
1051 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1052 Resources.maxCombinedTextureImageUnits = value;
1053 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1054 Resources.maxTextureImageUnits = value;
1055 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1056 Resources.maxFragmentUniformComponents = value;
1057 else if (strcmp(token, "MaxDrawBuffers") == 0)
1058 Resources.maxDrawBuffers = value;
1059 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1060 Resources.maxVertexUniformVectors = value;
1061 else if (strcmp(token, "MaxVaryingVectors") == 0)
1062 Resources.maxVaryingVectors = value;
1063 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1064 Resources.maxFragmentUniformVectors = value;
1065 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1066 Resources.maxVertexOutputVectors = value;
1067 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1068 Resources.maxFragmentInputVectors = value;
1069 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1070 Resources.minProgramTexelOffset = value;
1071 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1072 Resources.maxProgramTexelOffset = value;
1073 else if (strcmp(token, "MaxClipDistances") == 0)
1074 Resources.maxClipDistances = value;
1075 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1076 Resources.maxComputeWorkGroupCountX = value;
1077 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1078 Resources.maxComputeWorkGroupCountY = value;
1079 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1080 Resources.maxComputeWorkGroupCountZ = value;
1081 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1082 Resources.maxComputeWorkGroupSizeX = value;
1083 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1084 Resources.maxComputeWorkGroupSizeY = value;
1085 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1086 Resources.maxComputeWorkGroupSizeZ = value;
1087 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1088 Resources.maxComputeUniformComponents = value;
1089 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1090 Resources.maxComputeTextureImageUnits = value;
1091 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1092 Resources.maxComputeImageUniforms = value;
1093 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1094 Resources.maxComputeAtomicCounters = value;
1095 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1096 Resources.maxComputeAtomicCounterBuffers = value;
1097 else if (strcmp(token, "MaxVaryingComponents") == 0)
1098 Resources.maxVaryingComponents = value;
1099 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1100 Resources.maxVertexOutputComponents = value;
1101 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1102 Resources.maxGeometryInputComponents = value;
1103 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1104 Resources.maxGeometryOutputComponents = value;
1105 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1106 Resources.maxFragmentInputComponents = value;
1107 else if (strcmp(token, "MaxImageUnits") == 0)
1108 Resources.maxImageUnits = value;
1109 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1110 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1111 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1112 Resources.maxCombinedShaderOutputResources = value;
1113 else if (strcmp(token, "MaxImageSamples") == 0)
1114 Resources.maxImageSamples = value;
1115 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1116 Resources.maxVertexImageUniforms = value;
1117 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1118 Resources.maxTessControlImageUniforms = value;
1119 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1120 Resources.maxTessEvaluationImageUniforms = value;
1121 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1122 Resources.maxGeometryImageUniforms = value;
1123 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1124 Resources.maxFragmentImageUniforms = value;
1125 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1126 Resources.maxCombinedImageUniforms = value;
1127 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1128 Resources.maxGeometryTextureImageUnits = value;
1129 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1130 Resources.maxGeometryOutputVertices = value;
1131 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1132 Resources.maxGeometryTotalOutputComponents = value;
1133 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1134 Resources.maxGeometryUniformComponents = value;
1135 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1136 Resources.maxGeometryVaryingComponents = value;
1137 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1138 Resources.maxTessControlInputComponents = value;
1139 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1140 Resources.maxTessControlOutputComponents = value;
1141 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1142 Resources.maxTessControlTextureImageUnits = value;
1143 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1144 Resources.maxTessControlUniformComponents = value;
1145 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1146 Resources.maxTessControlTotalOutputComponents = value;
1147 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1148 Resources.maxTessEvaluationInputComponents = value;
1149 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1150 Resources.maxTessEvaluationOutputComponents = value;
1151 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1152 Resources.maxTessEvaluationTextureImageUnits = value;
1153 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1154 Resources.maxTessEvaluationUniformComponents = value;
1155 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1156 Resources.maxTessPatchComponents = value;
1157 else if (strcmp(token, "MaxPatchVertices") == 0)
1158 Resources.maxPatchVertices = value;
1159 else if (strcmp(token, "MaxTessGenLevel") == 0)
1160 Resources.maxTessGenLevel = value;
1161 else if (strcmp(token, "MaxViewports") == 0)
1162 Resources.maxViewports = value;
1163 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1164 Resources.maxVertexAtomicCounters = value;
1165 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1166 Resources.maxTessControlAtomicCounters = value;
1167 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1168 Resources.maxTessEvaluationAtomicCounters = value;
1169 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1170 Resources.maxGeometryAtomicCounters = value;
1171 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1172 Resources.maxFragmentAtomicCounters = value;
1173 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1174 Resources.maxCombinedAtomicCounters = value;
1175 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1176 Resources.maxAtomicCounterBindings = value;
1177 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1178 Resources.maxVertexAtomicCounterBuffers = value;
1179 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1180 Resources.maxTessControlAtomicCounterBuffers = value;
1181 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1182 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1183 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1184 Resources.maxGeometryAtomicCounterBuffers = value;
1185 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1186 Resources.maxFragmentAtomicCounterBuffers = value;
1187 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1188 Resources.maxCombinedAtomicCounterBuffers = value;
1189 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1190 Resources.maxAtomicCounterBufferSize = value;
1191 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1192 Resources.maxTransformFeedbackBuffers = value;
1193 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1194 Resources.maxTransformFeedbackInterleavedComponents = value;
1195 else if (strcmp(token, "MaxCullDistances") == 0)
1196 Resources.maxCullDistances = value;
1197 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1198 Resources.maxCombinedClipAndCullDistances = value;
1199 else if (strcmp(token, "MaxSamples") == 0)
1200 Resources.maxSamples = value;
1201
1202 else if (strcmp(token, "nonInductiveForLoops") == 0)
1203 Resources.limits.nonInductiveForLoops = (value != 0);
1204 else if (strcmp(token, "whileLoops") == 0)
1205 Resources.limits.whileLoops = (value != 0);
1206 else if (strcmp(token, "doWhileLoops") == 0)
1207 Resources.limits.doWhileLoops = (value != 0);
1208 else if (strcmp(token, "generalUniformIndexing") == 0)
1209 Resources.limits.generalUniformIndexing = (value != 0);
1210 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1211 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1212 else if (strcmp(token, "generalVaryingIndexing") == 0)
1213 Resources.limits.generalVaryingIndexing = (value != 0);
1214 else if (strcmp(token, "generalSamplerIndexing") == 0)
1215 Resources.limits.generalSamplerIndexing = (value != 0);
1216 else if (strcmp(token, "generalVariableIndexing") == 0)
1217 Resources.limits.generalVariableIndexing = (value != 0);
1218 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1219 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1220 else
1221 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1222
1223 token = strtok(0, delims);
1224 }
1225 if (configStrings)
1226 FreeFileData(configStrings);
1227}
1228
Tony Barbour01999182015-04-09 12:58:51 -06001229void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001230{
1231 if (m_compile_options & EOptionRelaxedErrors)
1232 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1233 if (m_compile_options & EOptionIntermediate)
1234 messages = (EShMessages)(messages | EShMsgAST);
1235 if (m_compile_options & EOptionSuppressWarnings)
1236 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1237}
1238
1239//
1240// Malloc a string of sufficient size and read a string into it.
1241//
Tony Barbour01999182015-04-09 12:58:51 -06001242char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001243{
1244 FILE *in;
1245 #if defined(_WIN32) && defined(__GNUC__)
1246 in = fopen(fileName, "r");
1247 int errorCode = in ? 0 : 1;
1248 #else
1249 int errorCode = fopen_s(&in, fileName, "r");
1250 #endif
1251
1252 char *fdata;
1253 int count = 0;
1254 const int maxSourceStrings = 5;
1255 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1256
1257 if (errorCode) {
1258 printf("Error: unable to open input file: %s\n", fileName);
1259 return 0;
1260 }
1261
1262 while (fgetc(in) != EOF)
1263 count++;
1264
1265 fseek(in, 0, SEEK_SET);
1266
1267 if (!(fdata = (char*)malloc(count+2))) {
1268 printf("Error allocating memory\n");
1269 return 0;
1270 }
1271 if (fread(fdata,1,count, in)!=count) {
1272 printf("Error reading input file: %s\n", fileName);
1273 return 0;
1274 }
1275 fdata[count] = '\0';
1276 fclose(in);
1277 if (count == 0) {
1278 return_data[0]=(char*)malloc(count+2);
1279 return_data[0][0]='\0';
1280 m_num_shader_strings = 0;
1281 return return_data;
1282 } else
1283 m_num_shader_strings = 1;
1284
1285 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1286 int ptr_len=0,i=0;
1287 while(count>0){
1288 return_data[i]=(char*)malloc(len+2);
1289 memcpy(return_data[i],fdata+ptr_len,len);
1290 return_data[i][len]='\0';
1291 count-=(len);
1292 ptr_len+=(len);
1293 if(count<len){
1294 if(count==0){
1295 m_num_shader_strings=(i+1);
1296 break;
1297 }
1298 len = count;
1299 }
1300 ++i;
1301 }
1302 return return_data;
1303}
1304
Tony Barbour01999182015-04-09 12:58:51 -06001305void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001306{
1307 for(int i=0;i<m_num_shader_strings;i++)
1308 free(data[i]);
1309}
1310
1311//
1312// Deduce the language from the filename. Files must end in one of the
1313// following extensions:
1314//
1315// .vert = vertex
1316// .tesc = tessellation control
1317// .tese = tessellation evaluation
1318// .geom = geometry
1319// .frag = fragment
1320// .comp = compute
1321//
Tony Barbour01999182015-04-09 12:58:51 -06001322EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001323{
1324 size_t ext = name.rfind('.');
1325 if (ext == std::string::npos) {
1326 return EShLangVertex;
1327 }
1328
1329 std::string suffix = name.substr(ext + 1, std::string::npos);
1330 if (suffix == "vert")
1331 return EShLangVertex;
1332 else if (suffix == "tesc")
1333 return EShLangTessControl;
1334 else if (suffix == "tese")
1335 return EShLangTessEvaluation;
1336 else if (suffix == "geom")
1337 return EShLangGeometry;
1338 else if (suffix == "frag")
1339 return EShLangFragment;
1340 else if (suffix == "comp")
1341 return EShLangCompute;
1342
1343 return EShLangVertex;
1344}
1345
1346//
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001347// Convert VK shader type to compiler's
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001348//
Tony Barbour8205d902015-04-16 15:59:00 -06001349EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001350{
1351 switch (shader_type) {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001352 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001353 return EShLangVertex;
1354
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001355 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001356 return EShLangTessControl;
1357
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001358 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001359 return EShLangTessEvaluation;
1360
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001361 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001362 return EShLangGeometry;
1363
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001364 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001365 return EShLangFragment;
1366
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001367 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001368 return EShLangCompute;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001369
Chia-I Wubbdeacc2014-12-15 23:50:11 +08001370 default:
1371 return EShLangVertex;
1372 }
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001373}
1374
1375
1376//
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001377// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001378// Return value of false means an error was encountered.
1379//
Tony Barbour8205d902015-04-16 15:59:00 -06001380bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001381 const char *pshader,
Cody Northropeb9130e2015-06-03 13:01:54 -06001382 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001383{
1384 glslang::TProgram& program = *new glslang::TProgram;
1385 const char *shaderStrings[1];
1386
1387 // TODO: Do we want to load a special config file depending on the
1388 // shader source? Optional name maybe?
1389 // SetConfigFile(fileName);
1390
1391 ProcessConfigFile();
1392
1393 EShMessages messages = EShMsgDefault;
1394 SetMessageOptions(messages);
1395
1396 EShLanguage stage = FindLanguage(shader_type);
1397 glslang::TShader* shader = new glslang::TShader(stage);
1398
1399 shaderStrings[0] = pshader;
1400 shader->setStrings(shaderStrings, 1);
1401
1402 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1403
Cody Northropad306f02014-11-03 12:54:37 -07001404 if (! (m_compile_options & EOptionSuppressInfolog)) {
1405 puts(shader->getInfoLog());
1406 puts(shader->getInfoDebugLog());
1407 }
1408
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001409 return false; // something didn't work
1410 }
1411
1412 program.addShader(shader);
1413
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001414
1415 //
1416 // Program-level processing...
1417 //
1418
Cody Northropad306f02014-11-03 12:54:37 -07001419 if (! program.link(messages)) {
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001420
Cody Northropad306f02014-11-03 12:54:37 -07001421 if (! (m_compile_options & EOptionSuppressInfolog)) {
1422 puts(shader->getInfoLog());
1423 puts(shader->getInfoDebugLog());
1424 }
1425
1426 return false;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001427 }
1428
1429 if (m_compile_options & EOptionDumpReflection) {
1430 program.buildReflection();
1431 program.dumpReflection();
1432 }
1433
Cody Northropeb9130e2015-06-03 13:01:54 -06001434 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1435
1436 //
1437 // Test the different modes of SPIR-V modification
1438 //
1439 if (this->m_canonicalize_spv) {
1440 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1441 }
1442
1443 if (this->m_strip_spv) {
1444 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1445 }
1446
1447 if (this->m_do_everything_spv) {
1448 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1449 }
1450
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -06001451
1452 return true;
1453}
1454
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001455
1456
Tony Barbour01999182015-04-09 12:58:51 -06001457VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001458 m_width( 0 ),
1459 m_height( 0 ),
Chia-I Wub2c2dea2014-12-15 23:29:34 +08001460 m_data( NULL ),
1461 m_data_size( 0 )
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001462{
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001463}
1464
Tony Barbour01999182015-04-09 12:58:51 -06001465VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001466{
1467
1468}
1469
Tony Barbour01999182015-04-09 12:58:51 -06001470VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001471{
1472 m_title = copyin.m_title;
1473 m_width = copyin.m_width;
1474 m_height = copyin.m_height;
1475 m_data_size = copyin.m_data_size;
1476 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1477}
1478
Tony Barbour01999182015-04-09 12:58:51 -06001479ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001480{
Tony Barbour01999182015-04-09 12:58:51 -06001481 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1482 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001483 return output;
1484}
1485
Tony Barbour01999182015-04-09 12:58:51 -06001486VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001487{
1488 m_title = rhs.m_title;
1489 m_width = rhs.m_width;
1490 m_height = rhs.m_height;
1491 m_data_size = rhs.m_data_size;
1492 m_data = rhs.m_data;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001493 return *this;
1494}
1495
Tony Barbour01999182015-04-09 12:58:51 -06001496int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001497{
1498 if( this->m_data != rhs.m_data) return 0;
1499 return 1;
1500}
1501
1502// This function is required for built-in STL list functions like sort
Tony Barbour01999182015-04-09 12:58:51 -06001503int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -06001504{
1505 if( this->m_data_size < rhs.m_data_size ) return 1;
1506 return 0;
1507}
1508