blob: 58cae8fee742d368130400c9ee7f4eb66ed4b93f [file] [log] [blame]
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001// VK tests
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06002//
3// Copyright (C) 2014 LunarG, Inc.
4//
5// Permission is hereby granted, free of charge, to any person obtaining a
6// copy of this software and associated documentation files (the "Software"),
7// to deal in the Software without restriction, including without limitation
8// the rights to use, copy, modify, merge, publish, distribute, sublicense,
9// and/or sell copies of the Software, and to permit persons to whom the
10// Software is furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included
13// in all copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21// DEALINGS IN THE SOFTWARE.
22
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060023#include "vktestframework.h"
24#include "vkrenderframework.h"
Cody Northrop5a95b472015-06-03 13:01:54 -060025#include "SPIRV/GlslangToSpv.h"
26#include "SPIRV/SPVRemapper.h"
Tony Barbour4ab45422014-12-10 17:00:20 -070027#include <limits.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060028#include <math.h>
Chia-I Wuec664fa2014-12-02 11:54:24 +080029#include <wand/MagickWand.h>
Chia-I Wuf8693382015-04-16 22:02:10 +080030#include <xcb/xcb.h>
31#include <vk_wsi_lunarg.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060032
Tony Barbour3d69c9e2015-05-20 16:53:31 -060033#if defined(PATH_MAX) && !defined(MAX_PATH)
34#define MAX_PATH PATH_MAX
35#endif
36
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060037// Command-line options
38enum TOptions {
39 EOptionNone = 0x000,
40 EOptionIntermediate = 0x001,
41 EOptionSuppressInfolog = 0x002,
42 EOptionMemoryLeakMode = 0x004,
43 EOptionRelaxedErrors = 0x008,
44 EOptionGiveWarnings = 0x010,
45 EOptionLinkProgram = 0x020,
46 EOptionMultiThreaded = 0x040,
47 EOptionDumpConfig = 0x080,
48 EOptionDumpReflection = 0x100,
49 EOptionSuppressWarnings = 0x200,
50 EOptionDumpVersions = 0x400,
Cody Northrop3bfd27c2015-03-17 15:55:58 -060051 EOptionSpv = 0x800,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060052 EOptionDefaultDesktop = 0x1000,
53};
54
Chia-I Wuf8693382015-04-16 22:02:10 +080055class TestFrameworkVkPresent
56{
57public:
58 TestFrameworkVkPresent(vk_testing::Device &device);
59
60 void Run();
61 void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn);
62 void CreateMyWindow();
63 void CreateSwapChain();
64 void TearDown();
Tony Barbour3d69c9e2015-05-20 16:53:31 -060065#ifdef _WIN32
66 static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
67#endif
68
Chia-I Wuf8693382015-04-16 22:02:10 +080069
70protected:
71 vk_testing::Device &m_device;
72 vk_testing::Queue &m_queue;
73 vk_testing::CmdBuffer m_cmdbuf;
74
75private:
Tony Barbour3d69c9e2015-05-20 16:53:31 -060076#ifdef _WIN32
77 HINSTANCE m_connection; // hInstance - Windows Instance
78 HWND m_window; // hWnd - window handle
79
80#else
Chia-I Wuf8693382015-04-16 22:02:10 +080081 xcb_connection_t *m_connection;
82 xcb_screen_t *m_screen;
83 xcb_window_t m_window;
84 xcb_intern_atom_reply_t *m_atom_wm_delete_window;
Tony Barbour3d69c9e2015-05-20 16:53:31 -060085#endif
Courtney Goeltzenleuchterd6079ec2015-04-22 10:09:35 -060086 std::list<VkTestImageRecord> m_images;
Chia-I Wuf8693382015-04-16 22:02:10 +080087
88 VkSwapChainWSI m_swap_chain;
Tony-LunarG399dfca2015-05-19 14:08:26 -060089 std::vector<VkSwapChainImageInfoWSI> m_persistent_images;
90 int m_current_buffer;
Chia-I Wuf8693382015-04-16 22:02:10 +080091
92 bool m_quit;
93 bool m_pause;
94
Tony Barbour7ea6aa22015-05-22 09:44:58 -060095 int m_width;
96 int m_height;
Chia-I Wuf8693382015-04-16 22:02:10 +080097
98 std::list<VkTestImageRecord>::iterator m_display_image;
99
100 void Display();
101 void HandleEvent(xcb_generic_event_t *event);
102};
103
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600104#ifndef _WIN32
105
106#include <errno.h>
107
108int fopen_s(
109 FILE** pFile,
110 const char* filename,
111 const char* mode
112)
113{
114 if (!pFile || !filename || !mode) {
115 return EINVAL;
116 }
117
118 FILE* f = fopen(filename, mode);
119 if (! f) {
120 if (errno != 0) {
121 return errno;
122 } else {
123 return ENOENT;
124 }
125 }
126 *pFile = f;
127
128 return 0;
129}
130
131#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600132
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600133
134
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600135// Set up environment for GLSL compiler
136// Must be done once per process
137void TestEnvironment::SetUp()
138{
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600139 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600140 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800141
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600142 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600143}
144
145void TestEnvironment::TearDown()
146{
147 glslang::FinalizeProcess();
148}
149
Tony Barbour6918cd52015-04-09 12:58:51 -0600150VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600151 m_compile_options( 0 ),
152 m_num_shader_strings( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600153{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600154
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600155}
156
Tony Barbour6918cd52015-04-09 12:58:51 -0600157VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600158{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600159
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600160}
161
162// Define all the static elements
Tony Barbour6918cd52015-04-09 12:58:51 -0600163bool VkTestFramework::m_show_images = false;
164bool VkTestFramework::m_save_images = false;
165bool VkTestFramework::m_compare_images = false;
Tony Barbour0dd968a2015-04-02 15:48:24 -0600166#ifdef _WIN32
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600167bool VkTestFramework::m_use_glsl = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600168bool VkTestFramework::m_canonicalize_spv = false;
169bool VkTestFramework::m_strip_spv = false;
170bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour0dd968a2015-04-02 15:48:24 -0600171#else
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600172bool VkTestFramework::m_use_glsl = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600173bool VkTestFramework::m_canonicalize_spv = false;
174bool VkTestFramework::m_strip_spv = false;
175bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour0dd968a2015-04-02 15:48:24 -0600176#endif
Tony Barbour6918cd52015-04-09 12:58:51 -0600177int VkTestFramework::m_width = 0;
178int VkTestFramework::m_height = 0;
179std::list<VkTestImageRecord> VkTestFramework::m_images;
180std::list<VkTestImageRecord>::iterator VkTestFramework::m_display_image;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600181int m_display_image_idx = 0;
182
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600183bool VkTestFramework::optionMatch(const char* option, char* optionLine)
184{
185 if (strncmp(option, optionLine, strlen(option)) == 0)
186 return true;
187 else
188 return false;
189}
190
Tony Barbour6918cd52015-04-09 12:58:51 -0600191void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600192{
193 int i, n;
194
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600195 for (i=1, n=1; i< *argc; i++) {
196 if (optionMatch("--show-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600197 m_show_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600198 else if (optionMatch("--save-images", argv[i]))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600199 m_save_images = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600200 else if (optionMatch("--no-SPV", argv[i]))
201 m_use_glsl = true;
202 else if (optionMatch("--strip-SPV", argv[i]))
203 m_strip_spv = true;
204 else if (optionMatch("--canonicalize-SPV", argv[i]))
205 m_canonicalize_spv = true;
206 else if (optionMatch("--compare-images", argv[i]))
Tony Barbour247bf372014-10-30 14:29:04 -0600207 m_compare_images = true;
Tony Barbour247bf372014-10-30 14:29:04 -0600208
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600209 else if (optionMatch("--help", argv[i]) ||
210 optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700211 printf("\nOther options:\n");
212 printf("\t--show-images\n"
213 "\t\tDisplay test images in viewer after tests complete.\n");
214 printf("\t--save-images\n"
215 "\t\tSave tests images as ppm files in current working directory.\n"
216 "\t\tUsed to generate golden images for compare-images.\n");
217 printf("\t--compare-images\n"
218 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barboura98d3932014-12-11 09:52:49 -0700219 "\t\tAlso saves the generated test image in current working\n"
220 "\t\t\tdirectory but only if the image is different from the golden\n"
221 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
222 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700223 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600224 printf("\t--no-SPV\n"
225 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600226 printf("\t--strip-SPV\n"
227 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
228 printf("\t--canonicalize-SPV\n"
229 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
230 exit(0);
231 } else {
232 printf("\nUnrecognized option: %s\n", argv[i]);
233 printf("\nUse --help or -h for option list.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700234 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700235 }
236
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600237 /*
238 * Since the above "consume" inputs, update argv
239 * so that it contains the trimmed list of args for glutInit
240 */
241
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600242 argv[n] = argv[i];
243 n++;
244 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600245}
246
Tony Barbour6918cd52015-04-09 12:58:51 -0600247void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600248{
249 string filename;
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600250 VkResult err;
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600251 uint32_t x, y;
Tony Barbour6918cd52015-04-09 12:58:51 -0600252 VkImageObj displayImage(image->device());
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600253 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbour84d448c2015-04-02 14:02:33 -0600254
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600255 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, VK_IMAGE_TILING_LINEAR, reqs);
Tony Barbour84d448c2015-04-02 14:02:33 -0600256 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600257
258 filename.append(basename);
259 filename.append(".ppm");
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600260
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600261 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600262 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600263 };
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600264 VkSubresourceLayout sr_layout;
Chia-I Wu99ff89d2014-12-27 14:14:50 +0800265 size_t data_size = sizeof(sr_layout);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600266
267 err = vkGetImageSubresourceInfo(image->device()->device(), displayImage.image(), &sr,
Tony Barbourd1c35722015-04-16 15:59:00 -0600268 VK_SUBRESOURCE_INFO_TYPE_LAYOUT,
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600269 &data_size, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600270 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600271 ASSERT_EQ(data_size, sizeof(sr_layout));
272
Tony Barbour84d448c2015-04-02 14:02:33 -0600273 char *ptr;
274 ptr = (char *) displayImage.map();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600275 ptr += sr_layout.offset;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600276 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600277 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
278
279 file << "P6\n";
Tony Barbour84d448c2015-04-02 14:02:33 -0600280 file << displayImage.width() << "\n";
281 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600282 file << 255 << "\n";
283
Tony Barbour84d448c2015-04-02 14:02:33 -0600284 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700285 const int *row = (const int *) ptr;
286 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600287
Tony Barbourd1c35722015-04-16 15:59:00 -0600288 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700289 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600290 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700291 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
292 file.write((char *) &swapped, 3);
293 row++;
294 }
295 }
Tony Barbourd1c35722015-04-16 15:59:00 -0600296 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700297 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600298 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700299 file.write((char *) row, 3);
300 row++;
301 }
302 }
303 else {
304 printf("Unrecognized image format - will not write image files");
305 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600306 }
307
308 ptr += sr_layout.rowPitch;
309 }
310
311 file.close();
Tony Barbour84d448c2015-04-02 14:02:33 -0600312 displayImage.unmap();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600313}
314
Tony Barbour6918cd52015-04-09 12:58:51 -0600315void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour247bf372014-10-30 14:29:04 -0600316{
317
318 MagickWand *magick_wand_1;
319 MagickWand *magick_wand_2;
320 MagickWand *compare_wand;
321 MagickBooleanType status;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600322 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600323 double differenz;
324
Tony Barbour4ab45422014-12-10 17:00:20 -0700325 if (getenv("RENDERTEST_GOLDEN_DIR"))
326 {
327 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
328 }
329
Tony Barbour247bf372014-10-30 14:29:04 -0600330 MagickWandGenesis();
331 magick_wand_1=NewMagickWand();
332 sprintf(testimage,"%s.ppm",basename);
333 status=MagickReadImage(magick_wand_1,testimage);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600334 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour247bf372014-10-30 14:29:04 -0600335
336
337 MagickWandGenesis();
338 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700339 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600340 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600341 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour247bf372014-10-30 14:29:04 -0600342
Tony Barbour247bf372014-10-30 14:29:04 -0600343 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
344 if (differenz != 0.0)
345 {
346 char difference[256];
347
348 sprintf(difference,"%s-diff.ppm",basename);
349 status = MagickWriteImage(compare_wand, difference);
350 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
351 }
352 DestroyMagickWand(compare_wand);
353
354 DestroyMagickWand(magick_wand_1);
355 DestroyMagickWand(magick_wand_2);
356 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700357
358 if (differenz == 0.0)
359 {
360 /*
361 * If test image and golden image match, we do not need to
362 * keep around the test image.
363 */
364 remove(testimage);
365 }
Tony Barbour247bf372014-10-30 14:29:04 -0600366}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600367
Tony Barbour6918cd52015-04-09 12:58:51 -0600368void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600369{
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600370 VkResult err;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600371 VkSubresourceLayout sr_layout;
372 char *ptr;
373 VkTestImageRecord record;
374 size_t data_size = sizeof(sr_layout);
375 VkImageObj displayImage(image->device());
376 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
377
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600378 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, VK_IMAGE_TILING_LINEAR, reqs);
379 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600380
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600381 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600382 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600383 };
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600384
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600385 err = vkGetImageSubresourceInfo(displayImage.device()->device(), displayImage.image(), &sr,
386 VK_SUBRESOURCE_INFO_TYPE_LAYOUT,
387 &data_size, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600388 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600389 ASSERT_EQ(data_size, sizeof(sr_layout));
390
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600391 err = displayImage.MapMemory( (void **) &ptr );
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600392 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600393
394 ptr += sr_layout.offset;
395
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600396 record.m_title.append(comment);
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600397 record.m_width = displayImage.width();
398 record.m_height = displayImage.height();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600399 // TODO: Need to make this more robust to handle different image formats
Tony-LunarG399dfca2015-05-19 14:08:26 -0600400 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600401 record.m_data = malloc(record.m_data_size);
402 memcpy(record.m_data, ptr, record.m_data_size);
403 m_images.push_back(record);
404 m_display_image = --m_images.end();
405
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600406 err = displayImage.UnmapMemory();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600407 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600408}
409
Tony Barbour6918cd52015-04-09 12:58:51 -0600410void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600411{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600412 for (int32_t i = 0; i < images.size(); i++) {
413 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600414 }
415}
416
Tony Barbour6918cd52015-04-09 12:58:51 -0600417void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600418{
419 const ::testing::TestInfo* const test_info =
420 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600421 ostringstream filestream;
422 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600423
Tony Barbour247bf372014-10-30 14:29:04 -0600424 m_width = 40;
425
426 if (strcmp(test_info->name(), m_testName.c_str())) {
427 filestream << test_info->name();
428 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700429 m_frameNum = 2;
430 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600431 }
432 else {
433 filestream << test_info->name() << "-" << m_frameNum;
434 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700435 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600436 }
437
Tony Barbour247bf372014-10-30 14:29:04 -0600438 // ToDo - scrub string for bad characters
439
440 if (m_save_images || m_compare_images) {
441 WritePPM(filename.c_str(), image);
442 if (m_compare_images) {
443 Compare(filename.c_str(), image);
444 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600445 }
446
447 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600448 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600449 }
450}
451
Chia-I Wuf8693382015-04-16 22:02:10 +0800452TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
453 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700454 m_queue(*m_device.graphics_queues()[0]),
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600455 m_cmdbuf(m_device, vk_testing::CmdBuffer::create_info(m_device.graphics_queue_node_index_))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600456{
Tony Barbour96db8822015-02-25 12:28:39 -0700457 m_quit = false;
458 m_pause = false;
459 m_width = 0;
460 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600461}
462
Tony Barbour6918cd52015-04-09 12:58:51 -0600463void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600464{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600465 VkResult U_ASSERT_ONLY err;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600466 vk_testing::Buffer buf;
467 void *dest_ptr;
468
469 if (m_persistent_images.size() != 2) {
470 return;
471 }
472
473 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
474 buf.init(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
475 dest_ptr = buf.map();
476 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
477 buf.unmap();
478
479 m_cmdbuf.begin();
480
481 VkBufferImageCopy region = {};
482 region.imageExtent.height = m_display_image->m_height;
483 region.imageExtent.width = m_display_image->m_width;
484 region.imageExtent.depth = 1;
485
486 vkCmdCopyBufferToImage(m_cmdbuf.obj(),
487 buf.obj(),
488 m_persistent_images[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
489 1, &region);
490 m_cmdbuf.end();
491
492 VkCmdBuffer cmdBufs[1];
493 cmdBufs[0] = m_cmdbuf.obj();
494
495 vkQueueSubmit(m_queue.obj(), 1, cmdBufs, NULL);
496 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700497
Chia-I Wuf8693382015-04-16 22:02:10 +0800498 VkPresentInfoWSI present = {};
499 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_WSI;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600500 present.image = m_persistent_images[m_current_buffer].image;
Chia-I Wuf8693382015-04-16 22:02:10 +0800501 present.flipInterval = 1;
Tony Barbour96db8822015-02-25 12:28:39 -0700502
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600503#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800504 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700505 XCB_PROP_MODE_REPLACE,
506 m_window,
507 XCB_ATOM_WM_NAME,
508 XCB_ATOM_STRING,
509 8,
510 m_display_image->m_title.size(),
511 m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600512#endif
Chia-I Wuf8693382015-04-16 22:02:10 +0800513 err = vkQueuePresentWSI(m_queue.obj(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700514 assert(!err);
515
516 m_queue.wait();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600517 m_current_buffer = (m_current_buffer + 1) % 2;
Tony Barbour96db8822015-02-25 12:28:39 -0700518
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600519}
520
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600521#ifdef _WIN32
Tony-LunarG399dfca2015-05-19 14:08:26 -0600522# define PREVIOUSLY_DOWN 1<<29
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600523// MS-Windows event handling function:
524LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
525 UINT uMsg,
526 WPARAM wParam,
527 LPARAM lParam)
528{
529
530 switch(uMsg)
531 {
532 case WM_CLOSE:
533 PostQuitMessage(0);
534 break;
535
536 case WM_PAINT:
537 {
538 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
539 if (me) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600540 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600541 me->Display();
542 }
543 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600544 break;
545
546 case WM_KEYDOWN:
547 {
548 if (lParam & (PREVIOUSLY_DOWN)){
549 break;
550 }
551 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
552 // the window, we put the this pointer into the window's user data so we could get it back now
553 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
554 switch (wParam)
555 {
556 case VK_ESCAPE: me->m_quit = true;
557 break;
558
559 case VK_LEFT: // left arrow key
560 if (me->m_display_image == me->m_images.begin()) {
561 me->m_display_image = --me->m_images.end();
562 }
563 else {
564 --me->m_display_image;
565 }
566 break;
567
568 case VK_RIGHT: // right arrow key
569 ++me->m_display_image;
570 if (me->m_display_image == me->m_images.end()) {
571 me->m_display_image = me->m_images.begin();
572 }
573 break;
574
575 default:
576 break;
577 }
578 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
579 me->Display();
580 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600581 }
582 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
583}
584
585void TestFrameworkVkPresent::Run()
586{
587 MSG msg; // message
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600588
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600589 /* main message loop*/
Tony-LunarG399dfca2015-05-19 14:08:26 -0600590 while(! m_quit) {
591 GetMessage(&msg, m_window, 0, 0);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600592 if (msg.message == WM_QUIT) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600593 m_quit = true; //if found, quit app
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600594 } else {
595 /* Translate and dispatch to event queue*/
596 TranslateMessage(&msg);
597 DispatchMessage(&msg);
598 }
599 }
600}
601
602#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600603void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600604{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600605 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700606 switch (event_code) {
607 case XCB_EXPOSE:
608 Display(); // TODO: handle resize
609 break;
610 case XCB_CLIENT_MESSAGE:
611 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
612 (m_atom_wm_delete_window)->atom) {
613 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600614 }
615 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700616 case XCB_KEY_RELEASE:
617 {
618 const xcb_key_release_event_t *key =
619 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600620
Tony Barbour96db8822015-02-25 12:28:39 -0700621 switch (key->detail) {
622 case 0x9: // Escape
623 m_quit = true;
624 break;
625 case 0x71: // left arrow key
626 if (m_display_image == m_images.begin()) {
627 m_display_image = --m_images.end();
628 } else {
629 --m_display_image;
630 }
631 break;
632 case 0x72: // right arrow key
633 ++m_display_image;
634 if (m_display_image == m_images.end()) {
635 m_display_image = m_images.begin();
636 }
637 break;
638 case 0x41:
639 m_pause = !m_pause;
640 break;
641 }
642 Display();
643 }
644 break;
645 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600646 break;
647 }
Tony Barbour96db8822015-02-25 12:28:39 -0700648}
649
Tony Barbour6918cd52015-04-09 12:58:51 -0600650void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700651{
Chia-I Wuf8693382015-04-16 22:02:10 +0800652 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700653
654 while (! m_quit) {
655 xcb_generic_event_t *event;
656
657 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800658 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700659 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800660 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700661 }
662 if (event) {
663 HandleEvent(event);
664 free(event);
665 }
666 }
667}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600668#endif // _WIN32
Tony Barbour96db8822015-02-25 12:28:39 -0700669
Chia-I Wuf8693382015-04-16 22:02:10 +0800670void TestFrameworkVkPresent::CreateSwapChain()
Tony Barbour96db8822015-02-25 12:28:39 -0700671{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600672 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700673
Tony-LunarG399dfca2015-05-19 14:08:26 -0600674 m_display_image = m_images.begin();
675 m_current_buffer = 0;
676
Chia-I Wuf8693382015-04-16 22:02:10 +0800677 VkSwapChainCreateInfoWSI swap_chain = {};
678 swap_chain.sType = VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI;
679 swap_chain.pNativeWindowSystemHandle = (void *) m_connection;
680 swap_chain.pNativeWindowHandle = (void *) (intptr_t) m_window;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600681 swap_chain.imageCount = 2;
Chia-I Wuf8693382015-04-16 22:02:10 +0800682 swap_chain.imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
683 swap_chain.imageExtent.width = m_width;
684 swap_chain.imageExtent.height = m_height;
685 swap_chain.imageArraySize = 1;
686 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT;
687 swap_chain.swapModeFlags = VK_SWAP_MODE_FLIP_BIT_WSI |
688 VK_SWAP_MODE_BLIT_BIT_WSI;
689
690 err = vkCreateSwapChainWSI(m_device.obj(), &swap_chain, &m_swap_chain);
691 assert(!err);
692
Tony-LunarG399dfca2015-05-19 14:08:26 -0600693 size_t size = sizeof(VkSwapChainImageInfoWSI) * 2;
694 VkSwapChainImageInfoWSI infos[2];
695
Chia-I Wuf8693382015-04-16 22:02:10 +0800696 err = vkGetSwapChainInfoWSI(m_swap_chain,
697 VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600698 &size, &infos);
699 assert(!err && size == sizeof(VkSwapChainImageInfoWSI) * 2);
700 m_persistent_images.push_back(infos[0]);
701 m_persistent_images.push_back(infos[1]);
Tony Barbour96db8822015-02-25 12:28:39 -0700702}
703
Tony Barbour6918cd52015-04-09 12:58:51 -0600704void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn)
Tony Barbour96db8822015-02-25 12:28:39 -0700705{
706 m_images = imagesIn;
707}
708
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600709#ifdef _WIN32
710void TestFrameworkVkPresent::CreateMyWindow()
711{
712 WNDCLASSEX win_class;
713 // const ::testing::TestInfo* const test_info =
714 // ::testing::UnitTest::GetInstance()->current_test_info();
715 m_connection = GetModuleHandle(NULL);
716
717 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
718 it != m_images.end(); it++) {
719 if (m_width < it->m_width)
720 m_width = it->m_width;
721 if (m_height < it->m_height)
722 m_height = it->m_height;
723 }
724 // Initialize the window class structure:
725 win_class.cbSize = sizeof(WNDCLASSEX);
726 win_class.style = CS_HREDRAW | CS_VREDRAW;
727 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
728 win_class.cbClsExtra = 0;
729 win_class.cbWndExtra = 0;
730 win_class.hInstance = m_connection; // hInstance
731 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
732 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
733 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
734 win_class.lpszMenuName = NULL;
735 win_class.lpszClassName = "Test";
736 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
737 // Register window class:
738 if (!RegisterClassEx(&win_class)) {
739 // It didn't work, so try to give a useful error:
740 printf("Unexpected error trying to start the application!\n");
741 fflush(stdout);
742 exit(1);
743 }
744 // Create window with the registered class:
745 m_window = CreateWindowEx(0,
746 "Test", // class name
747 "Test", // app name
748 WS_OVERLAPPEDWINDOW | // window style
749 WS_VISIBLE |
750 WS_SYSMENU,
751 100,100, // x/y coords
752 m_width, // width
753 m_height, // height
754 NULL, // handle to parent
755 NULL, // handle to menu
756 m_connection, // hInstance
757 NULL); // no extra parameters
758
759 if (!m_window) {
760 // It didn't work, so try to give a useful error:
761 DWORD error = GetLastError();
762 char message[120];
763 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
764 MessageBox(NULL, message, "Error", MB_OK);
765 exit(1);
766 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600767 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
768 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600769}
770#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600771void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -0700772{
Chia-I Wuf8693382015-04-16 22:02:10 +0800773 const xcb_setup_t *setup;
774 xcb_screen_iterator_t iter;
775 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -0700776 uint32_t value_mask, value_list[32];
777
Chia-I Wuf8693382015-04-16 22:02:10 +0800778 m_connection = xcb_connect(NULL, &scr);
779
780 setup = xcb_get_setup(m_connection);
781 iter = xcb_setup_roots_iterator(setup);
782 while (scr-- > 0)
783 xcb_screen_next(&iter);
784
785 m_screen = iter.data;
786
787 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
788 it != m_images.end(); it++) {
789 if (m_width < it->m_width)
790 m_width = it->m_width;
791 if (m_height < it->m_height)
792 m_height = it->m_height;
793 }
794
795 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700796
797 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +0800798 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -0700799 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
800 XCB_EVENT_MASK_EXPOSURE |
801 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
802
Chia-I Wuf8693382015-04-16 22:02:10 +0800803 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700804 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800805 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -0700806 0, 0, m_width, m_height, 0,
807 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800808 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -0700809 value_mask, value_list);
810
811 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +0800812 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -0700813 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +0800814 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -0700815
Chia-I Wuf8693382015-04-16 22:02:10 +0800816 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
817 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -0700818
Chia-I Wuf8693382015-04-16 22:02:10 +0800819 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -0700820 m_window, (*reply).atom, 4, 32, 1,
821 &(*m_atom_wm_delete_window).atom);
822 free(reply);
823
Chia-I Wuf8693382015-04-16 22:02:10 +0800824 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -0700825}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600826#endif
Tony Barbour96db8822015-02-25 12:28:39 -0700827
Tony Barbour6918cd52015-04-09 12:58:51 -0600828void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -0700829{
Chia-I Wuf8693382015-04-16 22:02:10 +0800830 vkDestroySwapChainWSI(m_swap_chain);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600831#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800832 xcb_destroy_window(m_connection, m_window);
833 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600834#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600835}
836
Tony Barbour6918cd52015-04-09 12:58:51 -0600837void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600838{
839 if (m_images.size() == 0) return;
840
Chia-I Wuf8693382015-04-16 22:02:10 +0800841 vk_testing::Environment env;
842 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -0700843 {
Chia-I Wuf8693382015-04-16 22:02:10 +0800844 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -0700845
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600846 vkPresent.InitPresentFramework(m_images);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600847 vkPresent.CreateMyWindow();
Chia-I Wuf8693382015-04-16 22:02:10 +0800848 vkPresent.CreateSwapChain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600849 vkPresent.Run();
850 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -0700851 }
Chia-I Wuf8693382015-04-16 22:02:10 +0800852 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600853}
854
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600855//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600856// These are the default resources for TBuiltInResources, used for both
857// - parsing this string for the case where the user didn't supply one
858// - dumping out a template for user construction of a config file
859//
860static const char* DefaultConfig =
861 "MaxLights 32\n"
862 "MaxClipPlanes 6\n"
863 "MaxTextureUnits 32\n"
864 "MaxTextureCoords 32\n"
865 "MaxVertexAttribs 64\n"
866 "MaxVertexUniformComponents 4096\n"
867 "MaxVaryingFloats 64\n"
868 "MaxVertexTextureImageUnits 32\n"
869 "MaxCombinedTextureImageUnits 80\n"
870 "MaxTextureImageUnits 32\n"
871 "MaxFragmentUniformComponents 4096\n"
872 "MaxDrawBuffers 32\n"
873 "MaxVertexUniformVectors 128\n"
874 "MaxVaryingVectors 8\n"
875 "MaxFragmentUniformVectors 16\n"
876 "MaxVertexOutputVectors 16\n"
877 "MaxFragmentInputVectors 15\n"
878 "MinProgramTexelOffset -8\n"
879 "MaxProgramTexelOffset 7\n"
880 "MaxClipDistances 8\n"
881 "MaxComputeWorkGroupCountX 65535\n"
882 "MaxComputeWorkGroupCountY 65535\n"
883 "MaxComputeWorkGroupCountZ 65535\n"
884 "MaxComputeWorkGroupSizeX 1024\n"
885 "MaxComputeWorkGroupSizeY 1024\n"
886 "MaxComputeWorkGroupSizeZ 64\n"
887 "MaxComputeUniformComponents 1024\n"
888 "MaxComputeTextureImageUnits 16\n"
889 "MaxComputeImageUniforms 8\n"
890 "MaxComputeAtomicCounters 8\n"
891 "MaxComputeAtomicCounterBuffers 1\n"
892 "MaxVaryingComponents 60\n"
893 "MaxVertexOutputComponents 64\n"
894 "MaxGeometryInputComponents 64\n"
895 "MaxGeometryOutputComponents 128\n"
896 "MaxFragmentInputComponents 128\n"
897 "MaxImageUnits 8\n"
898 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
899 "MaxCombinedShaderOutputResources 8\n"
900 "MaxImageSamples 0\n"
901 "MaxVertexImageUniforms 0\n"
902 "MaxTessControlImageUniforms 0\n"
903 "MaxTessEvaluationImageUniforms 0\n"
904 "MaxGeometryImageUniforms 0\n"
905 "MaxFragmentImageUniforms 8\n"
906 "MaxCombinedImageUniforms 8\n"
907 "MaxGeometryTextureImageUnits 16\n"
908 "MaxGeometryOutputVertices 256\n"
909 "MaxGeometryTotalOutputComponents 1024\n"
910 "MaxGeometryUniformComponents 1024\n"
911 "MaxGeometryVaryingComponents 64\n"
912 "MaxTessControlInputComponents 128\n"
913 "MaxTessControlOutputComponents 128\n"
914 "MaxTessControlTextureImageUnits 16\n"
915 "MaxTessControlUniformComponents 1024\n"
916 "MaxTessControlTotalOutputComponents 4096\n"
917 "MaxTessEvaluationInputComponents 128\n"
918 "MaxTessEvaluationOutputComponents 128\n"
919 "MaxTessEvaluationTextureImageUnits 16\n"
920 "MaxTessEvaluationUniformComponents 1024\n"
921 "MaxTessPatchComponents 120\n"
922 "MaxPatchVertices 32\n"
923 "MaxTessGenLevel 64\n"
924 "MaxViewports 16\n"
925 "MaxVertexAtomicCounters 0\n"
926 "MaxTessControlAtomicCounters 0\n"
927 "MaxTessEvaluationAtomicCounters 0\n"
928 "MaxGeometryAtomicCounters 0\n"
929 "MaxFragmentAtomicCounters 8\n"
930 "MaxCombinedAtomicCounters 8\n"
931 "MaxAtomicCounterBindings 1\n"
932 "MaxVertexAtomicCounterBuffers 0\n"
933 "MaxTessControlAtomicCounterBuffers 0\n"
934 "MaxTessEvaluationAtomicCounterBuffers 0\n"
935 "MaxGeometryAtomicCounterBuffers 0\n"
936 "MaxFragmentAtomicCounterBuffers 1\n"
937 "MaxCombinedAtomicCounterBuffers 1\n"
938 "MaxAtomicCounterBufferSize 16384\n"
939 "MaxTransformFeedbackBuffers 4\n"
940 "MaxTransformFeedbackInterleavedComponents 64\n"
941 "MaxCullDistances 8\n"
942 "MaxCombinedClipAndCullDistances 8\n"
943 "MaxSamples 4\n"
944
945 "nonInductiveForLoops 1\n"
946 "whileLoops 1\n"
947 "doWhileLoops 1\n"
948 "generalUniformIndexing 1\n"
949 "generalAttributeMatrixVectorIndexing 1\n"
950 "generalVaryingIndexing 1\n"
951 "generalSamplerIndexing 1\n"
952 "generalVariableIndexing 1\n"
953 "generalConstantMatrixVectorIndexing 1\n"
954 ;
955
956//
957// *.conf => this is a config file that can set limits/resources
958//
Tony Barbour6918cd52015-04-09 12:58:51 -0600959bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600960{
961 if (name.size() < 5)
962 return false;
963
964 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
965 ConfigFile = name;
966 return true;
967 }
968
969 return false;
970}
971
972//
973// Parse either a .conf file provided by the user or the default string above.
974//
Tony Barbour6918cd52015-04-09 12:58:51 -0600975void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600976{
977 char** configStrings = 0;
978 char* config = 0;
979 if (ConfigFile.size() > 0) {
980 configStrings = ReadFileData(ConfigFile.c_str());
981 if (configStrings)
982 config = *configStrings;
983 else {
984 printf("Error opening configuration file; will instead use the default configuration\n");
985 }
986 }
987
988 if (config == 0) {
989 config = new char[strlen(DefaultConfig) + 1];
990 strcpy(config, DefaultConfig);
991 }
992
993 const char* delims = " \t\n\r";
994 const char* token = strtok(config, delims);
995 while (token) {
996 const char* valueStr = strtok(0, delims);
997 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
998 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
999 return;
1000 }
1001 int value = atoi(valueStr);
1002
1003 if (strcmp(token, "MaxLights") == 0)
1004 Resources.maxLights = value;
1005 else if (strcmp(token, "MaxClipPlanes") == 0)
1006 Resources.maxClipPlanes = value;
1007 else if (strcmp(token, "MaxTextureUnits") == 0)
1008 Resources.maxTextureUnits = value;
1009 else if (strcmp(token, "MaxTextureCoords") == 0)
1010 Resources.maxTextureCoords = value;
1011 else if (strcmp(token, "MaxVertexAttribs") == 0)
1012 Resources.maxVertexAttribs = value;
1013 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1014 Resources.maxVertexUniformComponents = value;
1015 else if (strcmp(token, "MaxVaryingFloats") == 0)
1016 Resources.maxVaryingFloats = value;
1017 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1018 Resources.maxVertexTextureImageUnits = value;
1019 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1020 Resources.maxCombinedTextureImageUnits = value;
1021 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1022 Resources.maxTextureImageUnits = value;
1023 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1024 Resources.maxFragmentUniformComponents = value;
1025 else if (strcmp(token, "MaxDrawBuffers") == 0)
1026 Resources.maxDrawBuffers = value;
1027 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1028 Resources.maxVertexUniformVectors = value;
1029 else if (strcmp(token, "MaxVaryingVectors") == 0)
1030 Resources.maxVaryingVectors = value;
1031 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1032 Resources.maxFragmentUniformVectors = value;
1033 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1034 Resources.maxVertexOutputVectors = value;
1035 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1036 Resources.maxFragmentInputVectors = value;
1037 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1038 Resources.minProgramTexelOffset = value;
1039 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1040 Resources.maxProgramTexelOffset = value;
1041 else if (strcmp(token, "MaxClipDistances") == 0)
1042 Resources.maxClipDistances = value;
1043 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1044 Resources.maxComputeWorkGroupCountX = value;
1045 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1046 Resources.maxComputeWorkGroupCountY = value;
1047 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1048 Resources.maxComputeWorkGroupCountZ = value;
1049 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1050 Resources.maxComputeWorkGroupSizeX = value;
1051 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1052 Resources.maxComputeWorkGroupSizeY = value;
1053 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1054 Resources.maxComputeWorkGroupSizeZ = value;
1055 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1056 Resources.maxComputeUniformComponents = value;
1057 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1058 Resources.maxComputeTextureImageUnits = value;
1059 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1060 Resources.maxComputeImageUniforms = value;
1061 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1062 Resources.maxComputeAtomicCounters = value;
1063 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1064 Resources.maxComputeAtomicCounterBuffers = value;
1065 else if (strcmp(token, "MaxVaryingComponents") == 0)
1066 Resources.maxVaryingComponents = value;
1067 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1068 Resources.maxVertexOutputComponents = value;
1069 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1070 Resources.maxGeometryInputComponents = value;
1071 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1072 Resources.maxGeometryOutputComponents = value;
1073 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1074 Resources.maxFragmentInputComponents = value;
1075 else if (strcmp(token, "MaxImageUnits") == 0)
1076 Resources.maxImageUnits = value;
1077 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1078 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1079 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1080 Resources.maxCombinedShaderOutputResources = value;
1081 else if (strcmp(token, "MaxImageSamples") == 0)
1082 Resources.maxImageSamples = value;
1083 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1084 Resources.maxVertexImageUniforms = value;
1085 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1086 Resources.maxTessControlImageUniforms = value;
1087 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1088 Resources.maxTessEvaluationImageUniforms = value;
1089 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1090 Resources.maxGeometryImageUniforms = value;
1091 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1092 Resources.maxFragmentImageUniforms = value;
1093 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1094 Resources.maxCombinedImageUniforms = value;
1095 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1096 Resources.maxGeometryTextureImageUnits = value;
1097 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1098 Resources.maxGeometryOutputVertices = value;
1099 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1100 Resources.maxGeometryTotalOutputComponents = value;
1101 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1102 Resources.maxGeometryUniformComponents = value;
1103 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1104 Resources.maxGeometryVaryingComponents = value;
1105 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1106 Resources.maxTessControlInputComponents = value;
1107 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1108 Resources.maxTessControlOutputComponents = value;
1109 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1110 Resources.maxTessControlTextureImageUnits = value;
1111 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1112 Resources.maxTessControlUniformComponents = value;
1113 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1114 Resources.maxTessControlTotalOutputComponents = value;
1115 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1116 Resources.maxTessEvaluationInputComponents = value;
1117 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1118 Resources.maxTessEvaluationOutputComponents = value;
1119 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1120 Resources.maxTessEvaluationTextureImageUnits = value;
1121 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1122 Resources.maxTessEvaluationUniformComponents = value;
1123 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1124 Resources.maxTessPatchComponents = value;
1125 else if (strcmp(token, "MaxPatchVertices") == 0)
1126 Resources.maxPatchVertices = value;
1127 else if (strcmp(token, "MaxTessGenLevel") == 0)
1128 Resources.maxTessGenLevel = value;
1129 else if (strcmp(token, "MaxViewports") == 0)
1130 Resources.maxViewports = value;
1131 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1132 Resources.maxVertexAtomicCounters = value;
1133 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1134 Resources.maxTessControlAtomicCounters = value;
1135 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1136 Resources.maxTessEvaluationAtomicCounters = value;
1137 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1138 Resources.maxGeometryAtomicCounters = value;
1139 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1140 Resources.maxFragmentAtomicCounters = value;
1141 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1142 Resources.maxCombinedAtomicCounters = value;
1143 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1144 Resources.maxAtomicCounterBindings = value;
1145 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1146 Resources.maxVertexAtomicCounterBuffers = value;
1147 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1148 Resources.maxTessControlAtomicCounterBuffers = value;
1149 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1150 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1151 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1152 Resources.maxGeometryAtomicCounterBuffers = value;
1153 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1154 Resources.maxFragmentAtomicCounterBuffers = value;
1155 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1156 Resources.maxCombinedAtomicCounterBuffers = value;
1157 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1158 Resources.maxAtomicCounterBufferSize = value;
1159 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1160 Resources.maxTransformFeedbackBuffers = value;
1161 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1162 Resources.maxTransformFeedbackInterleavedComponents = value;
1163 else if (strcmp(token, "MaxCullDistances") == 0)
1164 Resources.maxCullDistances = value;
1165 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1166 Resources.maxCombinedClipAndCullDistances = value;
1167 else if (strcmp(token, "MaxSamples") == 0)
1168 Resources.maxSamples = value;
1169
1170 else if (strcmp(token, "nonInductiveForLoops") == 0)
1171 Resources.limits.nonInductiveForLoops = (value != 0);
1172 else if (strcmp(token, "whileLoops") == 0)
1173 Resources.limits.whileLoops = (value != 0);
1174 else if (strcmp(token, "doWhileLoops") == 0)
1175 Resources.limits.doWhileLoops = (value != 0);
1176 else if (strcmp(token, "generalUniformIndexing") == 0)
1177 Resources.limits.generalUniformIndexing = (value != 0);
1178 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1179 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1180 else if (strcmp(token, "generalVaryingIndexing") == 0)
1181 Resources.limits.generalVaryingIndexing = (value != 0);
1182 else if (strcmp(token, "generalSamplerIndexing") == 0)
1183 Resources.limits.generalSamplerIndexing = (value != 0);
1184 else if (strcmp(token, "generalVariableIndexing") == 0)
1185 Resources.limits.generalVariableIndexing = (value != 0);
1186 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1187 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1188 else
1189 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1190
1191 token = strtok(0, delims);
1192 }
1193 if (configStrings)
1194 FreeFileData(configStrings);
1195}
1196
Tony Barbour6918cd52015-04-09 12:58:51 -06001197void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001198{
1199 if (m_compile_options & EOptionRelaxedErrors)
1200 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1201 if (m_compile_options & EOptionIntermediate)
1202 messages = (EShMessages)(messages | EShMsgAST);
1203 if (m_compile_options & EOptionSuppressWarnings)
1204 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1205}
1206
1207//
1208// Malloc a string of sufficient size and read a string into it.
1209//
Tony Barbour6918cd52015-04-09 12:58:51 -06001210char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001211{
1212 FILE *in;
1213 #if defined(_WIN32) && defined(__GNUC__)
1214 in = fopen(fileName, "r");
1215 int errorCode = in ? 0 : 1;
1216 #else
1217 int errorCode = fopen_s(&in, fileName, "r");
1218 #endif
1219
1220 char *fdata;
1221 int count = 0;
1222 const int maxSourceStrings = 5;
1223 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1224
1225 if (errorCode) {
1226 printf("Error: unable to open input file: %s\n", fileName);
1227 return 0;
1228 }
1229
1230 while (fgetc(in) != EOF)
1231 count++;
1232
1233 fseek(in, 0, SEEK_SET);
1234
1235 if (!(fdata = (char*)malloc(count+2))) {
1236 printf("Error allocating memory\n");
1237 return 0;
1238 }
1239 if (fread(fdata,1,count, in)!=count) {
1240 printf("Error reading input file: %s\n", fileName);
1241 return 0;
1242 }
1243 fdata[count] = '\0';
1244 fclose(in);
1245 if (count == 0) {
1246 return_data[0]=(char*)malloc(count+2);
1247 return_data[0][0]='\0';
1248 m_num_shader_strings = 0;
1249 return return_data;
1250 } else
1251 m_num_shader_strings = 1;
1252
1253 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1254 int ptr_len=0,i=0;
1255 while(count>0){
1256 return_data[i]=(char*)malloc(len+2);
1257 memcpy(return_data[i],fdata+ptr_len,len);
1258 return_data[i][len]='\0';
1259 count-=(len);
1260 ptr_len+=(len);
1261 if(count<len){
1262 if(count==0){
1263 m_num_shader_strings=(i+1);
1264 break;
1265 }
1266 len = count;
1267 }
1268 ++i;
1269 }
1270 return return_data;
1271}
1272
Tony Barbour6918cd52015-04-09 12:58:51 -06001273void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001274{
1275 for(int i=0;i<m_num_shader_strings;i++)
1276 free(data[i]);
1277}
1278
1279//
1280// Deduce the language from the filename. Files must end in one of the
1281// following extensions:
1282//
1283// .vert = vertex
1284// .tesc = tessellation control
1285// .tese = tessellation evaluation
1286// .geom = geometry
1287// .frag = fragment
1288// .comp = compute
1289//
Tony Barbour6918cd52015-04-09 12:58:51 -06001290EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001291{
1292 size_t ext = name.rfind('.');
1293 if (ext == std::string::npos) {
1294 return EShLangVertex;
1295 }
1296
1297 std::string suffix = name.substr(ext + 1, std::string::npos);
1298 if (suffix == "vert")
1299 return EShLangVertex;
1300 else if (suffix == "tesc")
1301 return EShLangTessControl;
1302 else if (suffix == "tese")
1303 return EShLangTessEvaluation;
1304 else if (suffix == "geom")
1305 return EShLangGeometry;
1306 else if (suffix == "frag")
1307 return EShLangFragment;
1308 else if (suffix == "comp")
1309 return EShLangCompute;
1310
1311 return EShLangVertex;
1312}
1313
1314//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001315// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001316//
Tony Barbourd1c35722015-04-16 15:59:00 -06001317EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001318{
1319 switch (shader_type) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001320 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001321 return EShLangVertex;
1322
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001323 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001324 return EShLangTessControl;
1325
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001326 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001327 return EShLangTessEvaluation;
1328
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001329 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001330 return EShLangGeometry;
1331
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001332 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001333 return EShLangFragment;
1334
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001335 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001336 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001337
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001338 default:
1339 return EShLangVertex;
1340 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001341}
1342
1343
1344//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001345// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001346// Return value of false means an error was encountered.
1347//
Tony Barbourd1c35722015-04-16 15:59:00 -06001348bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001349 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001350 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001351{
1352 glslang::TProgram& program = *new glslang::TProgram;
1353 const char *shaderStrings[1];
1354
1355 // TODO: Do we want to load a special config file depending on the
1356 // shader source? Optional name maybe?
1357 // SetConfigFile(fileName);
1358
1359 ProcessConfigFile();
1360
1361 EShMessages messages = EShMsgDefault;
1362 SetMessageOptions(messages);
1363
1364 EShLanguage stage = FindLanguage(shader_type);
1365 glslang::TShader* shader = new glslang::TShader(stage);
1366
1367 shaderStrings[0] = pshader;
1368 shader->setStrings(shaderStrings, 1);
1369
1370 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1371
Cody Northrop195d6622014-11-03 12:54:37 -07001372 if (! (m_compile_options & EOptionSuppressInfolog)) {
1373 puts(shader->getInfoLog());
1374 puts(shader->getInfoDebugLog());
1375 }
1376
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001377 return false; // something didn't work
1378 }
1379
1380 program.addShader(shader);
1381
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001382
1383 //
1384 // Program-level processing...
1385 //
1386
Cody Northrop195d6622014-11-03 12:54:37 -07001387 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001388
Cody Northrop195d6622014-11-03 12:54:37 -07001389 if (! (m_compile_options & EOptionSuppressInfolog)) {
1390 puts(shader->getInfoLog());
1391 puts(shader->getInfoDebugLog());
1392 }
1393
1394 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001395 }
1396
1397 if (m_compile_options & EOptionDumpReflection) {
1398 program.buildReflection();
1399 program.dumpReflection();
1400 }
1401
Cody Northrop5a95b472015-06-03 13:01:54 -06001402 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1403
1404 //
1405 // Test the different modes of SPIR-V modification
1406 //
1407 if (this->m_canonicalize_spv) {
1408 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1409 }
1410
1411 if (this->m_strip_spv) {
1412 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1413 }
1414
1415 if (this->m_do_everything_spv) {
1416 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1417 }
1418
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001419
1420 return true;
1421}
1422
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001423
1424
Tony Barbour6918cd52015-04-09 12:58:51 -06001425VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001426 m_width( 0 ),
1427 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001428 m_data( NULL ),
1429 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001430{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001431}
1432
Tony Barbour6918cd52015-04-09 12:58:51 -06001433VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001434{
1435
1436}
1437
Tony Barbour6918cd52015-04-09 12:58:51 -06001438VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001439{
1440 m_title = copyin.m_title;
1441 m_width = copyin.m_width;
1442 m_height = copyin.m_height;
1443 m_data_size = copyin.m_data_size;
1444 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1445}
1446
Tony Barbour6918cd52015-04-09 12:58:51 -06001447ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001448{
Tony Barbour6918cd52015-04-09 12:58:51 -06001449 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1450 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001451 return output;
1452}
1453
Tony Barbour6918cd52015-04-09 12:58:51 -06001454VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001455{
1456 m_title = rhs.m_title;
1457 m_width = rhs.m_width;
1458 m_height = rhs.m_height;
1459 m_data_size = rhs.m_data_size;
1460 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001461 return *this;
1462}
1463
Tony Barbour6918cd52015-04-09 12:58:51 -06001464int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001465{
1466 if( this->m_data != rhs.m_data) return 0;
1467 return 1;
1468}
1469
1470// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001471int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001472{
1473 if( this->m_data_size < rhs.m_data_size ) return 1;
1474 return 0;
1475}
1476