blob: 85e56fb85f9ca589c433116b251fe345b164ebab [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"
Steve Kc1638cc2015-03-17 09:40:23 -060025#include "GlslangToSpv.h"
Tony Barbour4ab45422014-12-10 17:00:20 -070026#include <limits.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060027#include <math.h>
Chia-I Wuec664fa2014-12-02 11:54:24 +080028#include <wand/MagickWand.h>
Chia-I Wuf8693382015-04-16 22:02:10 +080029#include <xcb/xcb.h>
30#include <vk_wsi_lunarg.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060031
Tony Barbour3d69c9e2015-05-20 16:53:31 -060032#if defined(PATH_MAX) && !defined(MAX_PATH)
33#define MAX_PATH PATH_MAX
34#endif
35
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060036// Command-line options
37enum TOptions {
38 EOptionNone = 0x000,
39 EOptionIntermediate = 0x001,
40 EOptionSuppressInfolog = 0x002,
41 EOptionMemoryLeakMode = 0x004,
42 EOptionRelaxedErrors = 0x008,
43 EOptionGiveWarnings = 0x010,
44 EOptionLinkProgram = 0x020,
45 EOptionMultiThreaded = 0x040,
46 EOptionDumpConfig = 0x080,
47 EOptionDumpReflection = 0x100,
48 EOptionSuppressWarnings = 0x200,
49 EOptionDumpVersions = 0x400,
Cody Northrop3bfd27c2015-03-17 15:55:58 -060050 EOptionSpv = 0x800,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060051 EOptionDefaultDesktop = 0x1000,
52};
53
Chia-I Wuf8693382015-04-16 22:02:10 +080054class TestFrameworkVkPresent
55{
56public:
57 TestFrameworkVkPresent(vk_testing::Device &device);
58
59 void Run();
60 void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn);
61 void CreateMyWindow();
62 void CreateSwapChain();
63 void TearDown();
Tony Barbour3d69c9e2015-05-20 16:53:31 -060064#ifdef _WIN32
65 static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
66#endif
67
Chia-I Wuf8693382015-04-16 22:02:10 +080068
69protected:
70 vk_testing::Device &m_device;
71 vk_testing::Queue &m_queue;
72 vk_testing::CmdBuffer m_cmdbuf;
73
74private:
Tony Barbour3d69c9e2015-05-20 16:53:31 -060075#ifdef _WIN32
76 HINSTANCE m_connection; // hInstance - Windows Instance
77 HWND m_window; // hWnd - window handle
78
79#else
Chia-I Wuf8693382015-04-16 22:02:10 +080080 xcb_connection_t *m_connection;
81 xcb_screen_t *m_screen;
82 xcb_window_t m_window;
83 xcb_intern_atom_reply_t *m_atom_wm_delete_window;
Tony Barbour3d69c9e2015-05-20 16:53:31 -060084#endif
Courtney Goeltzenleuchterd6079ec2015-04-22 10:09:35 -060085 std::list<VkTestImageRecord> m_images;
Chia-I Wuf8693382015-04-16 22:02:10 +080086
87 VkSwapChainWSI m_swap_chain;
Tony-LunarG399dfca2015-05-19 14:08:26 -060088 std::vector<VkSwapChainImageInfoWSI> m_persistent_images;
89 int m_current_buffer;
Chia-I Wuf8693382015-04-16 22:02:10 +080090
91 bool m_quit;
92 bool m_pause;
93
Tony Barbour7ea6aa22015-05-22 09:44:58 -060094 int m_width;
95 int m_height;
Chia-I Wuf8693382015-04-16 22:02:10 +080096
97 std::list<VkTestImageRecord>::iterator m_display_image;
98
99 void Display();
100 void HandleEvent(xcb_generic_event_t *event);
101};
102
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600103#ifndef _WIN32
104
105#include <errno.h>
106
107int fopen_s(
108 FILE** pFile,
109 const char* filename,
110 const char* mode
111)
112{
113 if (!pFile || !filename || !mode) {
114 return EINVAL;
115 }
116
117 FILE* f = fopen(filename, mode);
118 if (! f) {
119 if (errno != 0) {
120 return errno;
121 } else {
122 return ENOENT;
123 }
124 }
125 *pFile = f;
126
127 return 0;
128}
129
130#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600131
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600132
133
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600134// Set up environment for GLSL compiler
135// Must be done once per process
136void TestEnvironment::SetUp()
137{
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600138 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600139 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800140
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600141 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600142}
143
144void TestEnvironment::TearDown()
145{
146 glslang::FinalizeProcess();
147}
148
Tony Barbour6918cd52015-04-09 12:58:51 -0600149VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600150 m_compile_options( 0 ),
151 m_num_shader_strings( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600152{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600153
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600154}
155
Tony Barbour6918cd52015-04-09 12:58:51 -0600156VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600157{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600158
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600159}
160
161// Define all the static elements
Tony Barbour6918cd52015-04-09 12:58:51 -0600162bool VkTestFramework::m_show_images = false;
163bool VkTestFramework::m_save_images = false;
164bool VkTestFramework::m_compare_images = false;
Tony Barbour0dd968a2015-04-02 15:48:24 -0600165#ifdef _WIN32
Tony Barbour6918cd52015-04-09 12:58:51 -0600166bool VkTestFramework::m_use_spv = false;
Tony Barbour0dd968a2015-04-02 15:48:24 -0600167#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600168bool VkTestFramework::m_use_spv = true;
Tony Barbour0dd968a2015-04-02 15:48:24 -0600169#endif
Tony Barbour6918cd52015-04-09 12:58:51 -0600170int VkTestFramework::m_width = 0;
171int VkTestFramework::m_height = 0;
172std::list<VkTestImageRecord> VkTestFramework::m_images;
173std::list<VkTestImageRecord>::iterator VkTestFramework::m_display_image;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600174int m_display_image_idx = 0;
175
Tony Barbour6918cd52015-04-09 12:58:51 -0600176void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600177{
178 int i, n;
179
180 for (i=0, n=0; i< *argc; i++) {
181 if (strncmp("--show-images", argv[i], 13) == 0) {
182 m_show_images = true;
183 continue;
184 }
185 if (strncmp("--save-images", argv[i], 13) == 0) {
186 m_save_images = true;
187 continue;
188 }
189
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600190 if (strncmp("--use-SPV", argv[i], 13) == 0) {
191 m_use_spv = true;
Courtney Goeltzenleuchterb666dc62014-10-09 09:13:56 -0600192 continue;
193 }
194
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600195 if (strncmp("--no-SPV", argv[i], 13) == 0) {
196 m_use_spv = false;
Courtney Goeltzenleuchterc44e3ee2014-10-31 14:13:33 -0600197 continue;
198 }
199
Tony Barbour247bf372014-10-30 14:29:04 -0600200 if (strncmp("--compare-images", argv[i], 16) == 0) {
201 m_compare_images = true;
202 continue;
203 }
204
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600205 /*
206 * Since the above "consume" inputs, update argv
207 * so that it contains the trimmed list of args for glutInit
208 */
Tony Barboura98d3932014-12-11 09:52:49 -0700209 if (strncmp("--help", argv[i], 6) == 0 || strncmp("-h", argv[i], 2) == 0) {
Courtney Goeltzenleuchter31144b72014-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 Barboura98d3932014-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 Goeltzenleuchter31144b72014-12-02 13:13:10 -0700222 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600223 printf("\t--use-SPV\n"
224 "\t\tUse SPV code path (default).\n");
225 printf("\t--no-SPV\n"
226 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700227 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700228 }
229
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600230 argv[n] = argv[i];
231 n++;
232 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600233}
234
Tony Barbour6918cd52015-04-09 12:58:51 -0600235void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600236{
237 string filename;
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600238 VkResult err;
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600239 uint32_t x, y;
Tony Barbour6918cd52015-04-09 12:58:51 -0600240 VkImageObj displayImage(image->device());
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600241 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbour84d448c2015-04-02 14:02:33 -0600242
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600243 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, VK_IMAGE_TILING_LINEAR, reqs);
Tony Barbour84d448c2015-04-02 14:02:33 -0600244 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600245
246 filename.append(basename);
247 filename.append(".ppm");
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600248
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600249 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600250 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600251 };
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600252 VkSubresourceLayout sr_layout;
Chia-I Wu99ff89d2014-12-27 14:14:50 +0800253 size_t data_size = sizeof(sr_layout);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600254
255 err = vkGetImageSubresourceInfo(image->device()->device(), displayImage.image(), &sr,
Tony Barbourd1c35722015-04-16 15:59:00 -0600256 VK_SUBRESOURCE_INFO_TYPE_LAYOUT,
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600257 &data_size, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600258 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600259 ASSERT_EQ(data_size, sizeof(sr_layout));
260
Tony Barbour84d448c2015-04-02 14:02:33 -0600261 char *ptr;
262 ptr = (char *) displayImage.map();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600263 ptr += sr_layout.offset;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600264 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600265 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
266
267 file << "P6\n";
Tony Barbour84d448c2015-04-02 14:02:33 -0600268 file << displayImage.width() << "\n";
269 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600270 file << 255 << "\n";
271
Tony Barbour84d448c2015-04-02 14:02:33 -0600272 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700273 const int *row = (const int *) ptr;
274 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600275
Tony Barbourd1c35722015-04-16 15:59:00 -0600276 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700277 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600278 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700279 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
280 file.write((char *) &swapped, 3);
281 row++;
282 }
283 }
Tony Barbourd1c35722015-04-16 15:59:00 -0600284 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700285 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600286 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700287 file.write((char *) row, 3);
288 row++;
289 }
290 }
291 else {
292 printf("Unrecognized image format - will not write image files");
293 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600294 }
295
296 ptr += sr_layout.rowPitch;
297 }
298
299 file.close();
Tony Barbour84d448c2015-04-02 14:02:33 -0600300 displayImage.unmap();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600301}
302
Tony Barbour6918cd52015-04-09 12:58:51 -0600303void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour247bf372014-10-30 14:29:04 -0600304{
305
306 MagickWand *magick_wand_1;
307 MagickWand *magick_wand_2;
308 MagickWand *compare_wand;
309 MagickBooleanType status;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600310 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600311 double differenz;
312
Tony Barbour4ab45422014-12-10 17:00:20 -0700313 if (getenv("RENDERTEST_GOLDEN_DIR"))
314 {
315 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
316 }
317
Tony Barbour247bf372014-10-30 14:29:04 -0600318 MagickWandGenesis();
319 magick_wand_1=NewMagickWand();
320 sprintf(testimage,"%s.ppm",basename);
321 status=MagickReadImage(magick_wand_1,testimage);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600322 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour247bf372014-10-30 14:29:04 -0600323
324
325 MagickWandGenesis();
326 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700327 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600328 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600329 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour247bf372014-10-30 14:29:04 -0600330
Tony Barbour247bf372014-10-30 14:29:04 -0600331 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
332 if (differenz != 0.0)
333 {
334 char difference[256];
335
336 sprintf(difference,"%s-diff.ppm",basename);
337 status = MagickWriteImage(compare_wand, difference);
338 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
339 }
340 DestroyMagickWand(compare_wand);
341
342 DestroyMagickWand(magick_wand_1);
343 DestroyMagickWand(magick_wand_2);
344 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700345
346 if (differenz == 0.0)
347 {
348 /*
349 * If test image and golden image match, we do not need to
350 * keep around the test image.
351 */
352 remove(testimage);
353 }
Tony Barbour247bf372014-10-30 14:29:04 -0600354}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600355
Tony Barbour6918cd52015-04-09 12:58:51 -0600356void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600357{
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600358 VkResult err;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600359 VkSubresourceLayout sr_layout;
360 char *ptr;
361 VkTestImageRecord record;
362 size_t data_size = sizeof(sr_layout);
363 VkImageObj displayImage(image->device());
364 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
365
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600366 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, VK_IMAGE_TILING_LINEAR, reqs);
367 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600368
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600369 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600370 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600371 };
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600372
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600373 err = vkGetImageSubresourceInfo(displayImage.device()->device(), displayImage.image(), &sr,
374 VK_SUBRESOURCE_INFO_TYPE_LAYOUT,
375 &data_size, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600376 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600377 ASSERT_EQ(data_size, sizeof(sr_layout));
378
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600379 err = displayImage.MapMemory( (void **) &ptr );
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600380 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600381
382 ptr += sr_layout.offset;
383
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600384 record.m_title.append(comment);
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600385 record.m_width = displayImage.width();
386 record.m_height = displayImage.height();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600387 // TODO: Need to make this more robust to handle different image formats
Tony-LunarG399dfca2015-05-19 14:08:26 -0600388 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600389 record.m_data = malloc(record.m_data_size);
390 memcpy(record.m_data, ptr, record.m_data_size);
391 m_images.push_back(record);
392 m_display_image = --m_images.end();
393
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600394 err = displayImage.UnmapMemory();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600395 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600396}
397
Tony Barbour6918cd52015-04-09 12:58:51 -0600398void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600399{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600400 for (int32_t i = 0; i < images.size(); i++) {
401 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600402 }
403}
404
Tony Barbour6918cd52015-04-09 12:58:51 -0600405void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600406{
407 const ::testing::TestInfo* const test_info =
408 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600409 ostringstream filestream;
410 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600411
Tony Barbour247bf372014-10-30 14:29:04 -0600412 m_width = 40;
413
414 if (strcmp(test_info->name(), m_testName.c_str())) {
415 filestream << test_info->name();
416 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700417 m_frameNum = 2;
418 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600419 }
420 else {
421 filestream << test_info->name() << "-" << m_frameNum;
422 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700423 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600424 }
425
Tony Barbour247bf372014-10-30 14:29:04 -0600426 // ToDo - scrub string for bad characters
427
428 if (m_save_images || m_compare_images) {
429 WritePPM(filename.c_str(), image);
430 if (m_compare_images) {
431 Compare(filename.c_str(), image);
432 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600433 }
434
435 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600436 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600437 }
438}
439
Chia-I Wuf8693382015-04-16 22:02:10 +0800440TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
441 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700442 m_queue(*m_device.graphics_queues()[0]),
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600443 m_cmdbuf(m_device, vk_testing::CmdBuffer::create_info(m_device.graphics_queue_node_index_))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600444{
Tony Barbour96db8822015-02-25 12:28:39 -0700445 m_quit = false;
446 m_pause = false;
447 m_width = 0;
448 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600449}
450
Tony Barbour6918cd52015-04-09 12:58:51 -0600451void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600452{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600453 VkResult U_ASSERT_ONLY err;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600454 vk_testing::Buffer buf;
455 void *dest_ptr;
456
457 if (m_persistent_images.size() != 2) {
458 return;
459 }
460
461 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
462 buf.init(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
463 dest_ptr = buf.map();
464 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
465 buf.unmap();
466
467 m_cmdbuf.begin();
468
469 VkBufferImageCopy region = {};
470 region.imageExtent.height = m_display_image->m_height;
471 region.imageExtent.width = m_display_image->m_width;
472 region.imageExtent.depth = 1;
473
474 vkCmdCopyBufferToImage(m_cmdbuf.obj(),
475 buf.obj(),
476 m_persistent_images[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
477 1, &region);
478 m_cmdbuf.end();
479
480 VkCmdBuffer cmdBufs[1];
481 cmdBufs[0] = m_cmdbuf.obj();
482
483 vkQueueSubmit(m_queue.obj(), 1, cmdBufs, NULL);
484 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700485
Chia-I Wuf8693382015-04-16 22:02:10 +0800486 VkPresentInfoWSI present = {};
487 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_WSI;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600488 present.image = m_persistent_images[m_current_buffer].image;
Chia-I Wuf8693382015-04-16 22:02:10 +0800489 present.flipInterval = 1;
Tony Barbour96db8822015-02-25 12:28:39 -0700490
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600491#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800492 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700493 XCB_PROP_MODE_REPLACE,
494 m_window,
495 XCB_ATOM_WM_NAME,
496 XCB_ATOM_STRING,
497 8,
498 m_display_image->m_title.size(),
499 m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600500#endif
Chia-I Wuf8693382015-04-16 22:02:10 +0800501 err = vkQueuePresentWSI(m_queue.obj(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700502 assert(!err);
503
504 m_queue.wait();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600505 m_current_buffer = (m_current_buffer + 1) % 2;
Tony Barbour96db8822015-02-25 12:28:39 -0700506
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600507}
508
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600509#ifdef _WIN32
Tony-LunarG399dfca2015-05-19 14:08:26 -0600510# define PREVIOUSLY_DOWN 1<<29
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600511// MS-Windows event handling function:
512LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
513 UINT uMsg,
514 WPARAM wParam,
515 LPARAM lParam)
516{
517
518 switch(uMsg)
519 {
520 case WM_CLOSE:
521 PostQuitMessage(0);
522 break;
523
524 case WM_PAINT:
525 {
526 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
527 if (me) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600528 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600529 me->Display();
530 }
531 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600532 break;
533
534 case WM_KEYDOWN:
535 {
536 if (lParam & (PREVIOUSLY_DOWN)){
537 break;
538 }
539 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
540 // the window, we put the this pointer into the window's user data so we could get it back now
541 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
542 switch (wParam)
543 {
544 case VK_ESCAPE: me->m_quit = true;
545 break;
546
547 case VK_LEFT: // left arrow key
548 if (me->m_display_image == me->m_images.begin()) {
549 me->m_display_image = --me->m_images.end();
550 }
551 else {
552 --me->m_display_image;
553 }
554 break;
555
556 case VK_RIGHT: // right arrow key
557 ++me->m_display_image;
558 if (me->m_display_image == me->m_images.end()) {
559 me->m_display_image = me->m_images.begin();
560 }
561 break;
562
563 default:
564 break;
565 }
566 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
567 me->Display();
568 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600569 }
570 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
571}
572
573void TestFrameworkVkPresent::Run()
574{
575 MSG msg; // message
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600576
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600577 /* main message loop*/
Tony-LunarG399dfca2015-05-19 14:08:26 -0600578 while(! m_quit) {
579 GetMessage(&msg, m_window, 0, 0);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600580 if (msg.message == WM_QUIT) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600581 m_quit = true; //if found, quit app
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600582 } else {
583 /* Translate and dispatch to event queue*/
584 TranslateMessage(&msg);
585 DispatchMessage(&msg);
586 }
587 }
588}
589
590#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600591void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600592{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600593 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700594 switch (event_code) {
595 case XCB_EXPOSE:
596 Display(); // TODO: handle resize
597 break;
598 case XCB_CLIENT_MESSAGE:
599 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
600 (m_atom_wm_delete_window)->atom) {
601 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600602 }
603 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700604 case XCB_KEY_RELEASE:
605 {
606 const xcb_key_release_event_t *key =
607 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600608
Tony Barbour96db8822015-02-25 12:28:39 -0700609 switch (key->detail) {
610 case 0x9: // Escape
611 m_quit = true;
612 break;
613 case 0x71: // left arrow key
614 if (m_display_image == m_images.begin()) {
615 m_display_image = --m_images.end();
616 } else {
617 --m_display_image;
618 }
619 break;
620 case 0x72: // right arrow key
621 ++m_display_image;
622 if (m_display_image == m_images.end()) {
623 m_display_image = m_images.begin();
624 }
625 break;
626 case 0x41:
627 m_pause = !m_pause;
628 break;
629 }
630 Display();
631 }
632 break;
633 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600634 break;
635 }
Tony Barbour96db8822015-02-25 12:28:39 -0700636}
637
Tony Barbour6918cd52015-04-09 12:58:51 -0600638void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700639{
Chia-I Wuf8693382015-04-16 22:02:10 +0800640 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700641
642 while (! m_quit) {
643 xcb_generic_event_t *event;
644
645 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800646 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700647 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800648 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700649 }
650 if (event) {
651 HandleEvent(event);
652 free(event);
653 }
654 }
655}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600656#endif // _WIN32
Tony Barbour96db8822015-02-25 12:28:39 -0700657
Chia-I Wuf8693382015-04-16 22:02:10 +0800658void TestFrameworkVkPresent::CreateSwapChain()
Tony Barbour96db8822015-02-25 12:28:39 -0700659{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600660 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700661
Tony-LunarG399dfca2015-05-19 14:08:26 -0600662 m_display_image = m_images.begin();
663 m_current_buffer = 0;
664
Chia-I Wuf8693382015-04-16 22:02:10 +0800665 VkSwapChainCreateInfoWSI swap_chain = {};
666 swap_chain.sType = VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI;
667 swap_chain.pNativeWindowSystemHandle = (void *) m_connection;
668 swap_chain.pNativeWindowHandle = (void *) (intptr_t) m_window;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600669 swap_chain.imageCount = 2;
Chia-I Wuf8693382015-04-16 22:02:10 +0800670 swap_chain.imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
671 swap_chain.imageExtent.width = m_width;
672 swap_chain.imageExtent.height = m_height;
673 swap_chain.imageArraySize = 1;
674 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT;
675 swap_chain.swapModeFlags = VK_SWAP_MODE_FLIP_BIT_WSI |
676 VK_SWAP_MODE_BLIT_BIT_WSI;
677
678 err = vkCreateSwapChainWSI(m_device.obj(), &swap_chain, &m_swap_chain);
679 assert(!err);
680
Tony-LunarG399dfca2015-05-19 14:08:26 -0600681 size_t size = sizeof(VkSwapChainImageInfoWSI) * 2;
682 VkSwapChainImageInfoWSI infos[2];
683
Chia-I Wuf8693382015-04-16 22:02:10 +0800684 err = vkGetSwapChainInfoWSI(m_swap_chain,
685 VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600686 &size, &infos);
687 assert(!err && size == sizeof(VkSwapChainImageInfoWSI) * 2);
688 m_persistent_images.push_back(infos[0]);
689 m_persistent_images.push_back(infos[1]);
Tony Barbour96db8822015-02-25 12:28:39 -0700690}
691
Tony Barbour6918cd52015-04-09 12:58:51 -0600692void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn)
Tony Barbour96db8822015-02-25 12:28:39 -0700693{
694 m_images = imagesIn;
695}
696
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600697#ifdef _WIN32
698void TestFrameworkVkPresent::CreateMyWindow()
699{
700 WNDCLASSEX win_class;
701 // const ::testing::TestInfo* const test_info =
702 // ::testing::UnitTest::GetInstance()->current_test_info();
703 m_connection = GetModuleHandle(NULL);
704
705 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
706 it != m_images.end(); it++) {
707 if (m_width < it->m_width)
708 m_width = it->m_width;
709 if (m_height < it->m_height)
710 m_height = it->m_height;
711 }
712 // Initialize the window class structure:
713 win_class.cbSize = sizeof(WNDCLASSEX);
714 win_class.style = CS_HREDRAW | CS_VREDRAW;
715 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
716 win_class.cbClsExtra = 0;
717 win_class.cbWndExtra = 0;
718 win_class.hInstance = m_connection; // hInstance
719 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
720 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
721 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
722 win_class.lpszMenuName = NULL;
723 win_class.lpszClassName = "Test";
724 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
725 // Register window class:
726 if (!RegisterClassEx(&win_class)) {
727 // It didn't work, so try to give a useful error:
728 printf("Unexpected error trying to start the application!\n");
729 fflush(stdout);
730 exit(1);
731 }
732 // Create window with the registered class:
733 m_window = CreateWindowEx(0,
734 "Test", // class name
735 "Test", // app name
736 WS_OVERLAPPEDWINDOW | // window style
737 WS_VISIBLE |
738 WS_SYSMENU,
739 100,100, // x/y coords
740 m_width, // width
741 m_height, // height
742 NULL, // handle to parent
743 NULL, // handle to menu
744 m_connection, // hInstance
745 NULL); // no extra parameters
746
747 if (!m_window) {
748 // It didn't work, so try to give a useful error:
749 DWORD error = GetLastError();
750 char message[120];
751 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
752 MessageBox(NULL, message, "Error", MB_OK);
753 exit(1);
754 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600755 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
756 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600757}
758#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600759void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -0700760{
Chia-I Wuf8693382015-04-16 22:02:10 +0800761 const xcb_setup_t *setup;
762 xcb_screen_iterator_t iter;
763 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -0700764 uint32_t value_mask, value_list[32];
765
Chia-I Wuf8693382015-04-16 22:02:10 +0800766 m_connection = xcb_connect(NULL, &scr);
767
768 setup = xcb_get_setup(m_connection);
769 iter = xcb_setup_roots_iterator(setup);
770 while (scr-- > 0)
771 xcb_screen_next(&iter);
772
773 m_screen = iter.data;
774
775 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
776 it != m_images.end(); it++) {
777 if (m_width < it->m_width)
778 m_width = it->m_width;
779 if (m_height < it->m_height)
780 m_height = it->m_height;
781 }
782
783 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700784
785 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +0800786 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -0700787 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
788 XCB_EVENT_MASK_EXPOSURE |
789 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
790
Chia-I Wuf8693382015-04-16 22:02:10 +0800791 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700792 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800793 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -0700794 0, 0, m_width, m_height, 0,
795 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800796 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -0700797 value_mask, value_list);
798
799 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +0800800 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -0700801 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +0800802 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -0700803
Chia-I Wuf8693382015-04-16 22:02:10 +0800804 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
805 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -0700806
Chia-I Wuf8693382015-04-16 22:02:10 +0800807 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -0700808 m_window, (*reply).atom, 4, 32, 1,
809 &(*m_atom_wm_delete_window).atom);
810 free(reply);
811
Chia-I Wuf8693382015-04-16 22:02:10 +0800812 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -0700813}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600814#endif
Tony Barbour96db8822015-02-25 12:28:39 -0700815
Tony Barbour6918cd52015-04-09 12:58:51 -0600816void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -0700817{
Chia-I Wuf8693382015-04-16 22:02:10 +0800818 vkDestroySwapChainWSI(m_swap_chain);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600819#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800820 xcb_destroy_window(m_connection, m_window);
821 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600822#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600823}
824
Tony Barbour6918cd52015-04-09 12:58:51 -0600825void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600826{
827 if (m_images.size() == 0) return;
828
Chia-I Wuf8693382015-04-16 22:02:10 +0800829 vk_testing::Environment env;
830 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -0700831 {
Chia-I Wuf8693382015-04-16 22:02:10 +0800832 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -0700833
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600834 vkPresent.InitPresentFramework(m_images);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600835 vkPresent.CreateMyWindow();
Chia-I Wuf8693382015-04-16 22:02:10 +0800836 vkPresent.CreateSwapChain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600837 vkPresent.Run();
838 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -0700839 }
Chia-I Wuf8693382015-04-16 22:02:10 +0800840 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600841}
842
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600843//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600844// These are the default resources for TBuiltInResources, used for both
845// - parsing this string for the case where the user didn't supply one
846// - dumping out a template for user construction of a config file
847//
848static const char* DefaultConfig =
849 "MaxLights 32\n"
850 "MaxClipPlanes 6\n"
851 "MaxTextureUnits 32\n"
852 "MaxTextureCoords 32\n"
853 "MaxVertexAttribs 64\n"
854 "MaxVertexUniformComponents 4096\n"
855 "MaxVaryingFloats 64\n"
856 "MaxVertexTextureImageUnits 32\n"
857 "MaxCombinedTextureImageUnits 80\n"
858 "MaxTextureImageUnits 32\n"
859 "MaxFragmentUniformComponents 4096\n"
860 "MaxDrawBuffers 32\n"
861 "MaxVertexUniformVectors 128\n"
862 "MaxVaryingVectors 8\n"
863 "MaxFragmentUniformVectors 16\n"
864 "MaxVertexOutputVectors 16\n"
865 "MaxFragmentInputVectors 15\n"
866 "MinProgramTexelOffset -8\n"
867 "MaxProgramTexelOffset 7\n"
868 "MaxClipDistances 8\n"
869 "MaxComputeWorkGroupCountX 65535\n"
870 "MaxComputeWorkGroupCountY 65535\n"
871 "MaxComputeWorkGroupCountZ 65535\n"
872 "MaxComputeWorkGroupSizeX 1024\n"
873 "MaxComputeWorkGroupSizeY 1024\n"
874 "MaxComputeWorkGroupSizeZ 64\n"
875 "MaxComputeUniformComponents 1024\n"
876 "MaxComputeTextureImageUnits 16\n"
877 "MaxComputeImageUniforms 8\n"
878 "MaxComputeAtomicCounters 8\n"
879 "MaxComputeAtomicCounterBuffers 1\n"
880 "MaxVaryingComponents 60\n"
881 "MaxVertexOutputComponents 64\n"
882 "MaxGeometryInputComponents 64\n"
883 "MaxGeometryOutputComponents 128\n"
884 "MaxFragmentInputComponents 128\n"
885 "MaxImageUnits 8\n"
886 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
887 "MaxCombinedShaderOutputResources 8\n"
888 "MaxImageSamples 0\n"
889 "MaxVertexImageUniforms 0\n"
890 "MaxTessControlImageUniforms 0\n"
891 "MaxTessEvaluationImageUniforms 0\n"
892 "MaxGeometryImageUniforms 0\n"
893 "MaxFragmentImageUniforms 8\n"
894 "MaxCombinedImageUniforms 8\n"
895 "MaxGeometryTextureImageUnits 16\n"
896 "MaxGeometryOutputVertices 256\n"
897 "MaxGeometryTotalOutputComponents 1024\n"
898 "MaxGeometryUniformComponents 1024\n"
899 "MaxGeometryVaryingComponents 64\n"
900 "MaxTessControlInputComponents 128\n"
901 "MaxTessControlOutputComponents 128\n"
902 "MaxTessControlTextureImageUnits 16\n"
903 "MaxTessControlUniformComponents 1024\n"
904 "MaxTessControlTotalOutputComponents 4096\n"
905 "MaxTessEvaluationInputComponents 128\n"
906 "MaxTessEvaluationOutputComponents 128\n"
907 "MaxTessEvaluationTextureImageUnits 16\n"
908 "MaxTessEvaluationUniformComponents 1024\n"
909 "MaxTessPatchComponents 120\n"
910 "MaxPatchVertices 32\n"
911 "MaxTessGenLevel 64\n"
912 "MaxViewports 16\n"
913 "MaxVertexAtomicCounters 0\n"
914 "MaxTessControlAtomicCounters 0\n"
915 "MaxTessEvaluationAtomicCounters 0\n"
916 "MaxGeometryAtomicCounters 0\n"
917 "MaxFragmentAtomicCounters 8\n"
918 "MaxCombinedAtomicCounters 8\n"
919 "MaxAtomicCounterBindings 1\n"
920 "MaxVertexAtomicCounterBuffers 0\n"
921 "MaxTessControlAtomicCounterBuffers 0\n"
922 "MaxTessEvaluationAtomicCounterBuffers 0\n"
923 "MaxGeometryAtomicCounterBuffers 0\n"
924 "MaxFragmentAtomicCounterBuffers 1\n"
925 "MaxCombinedAtomicCounterBuffers 1\n"
926 "MaxAtomicCounterBufferSize 16384\n"
927 "MaxTransformFeedbackBuffers 4\n"
928 "MaxTransformFeedbackInterleavedComponents 64\n"
929 "MaxCullDistances 8\n"
930 "MaxCombinedClipAndCullDistances 8\n"
931 "MaxSamples 4\n"
932
933 "nonInductiveForLoops 1\n"
934 "whileLoops 1\n"
935 "doWhileLoops 1\n"
936 "generalUniformIndexing 1\n"
937 "generalAttributeMatrixVectorIndexing 1\n"
938 "generalVaryingIndexing 1\n"
939 "generalSamplerIndexing 1\n"
940 "generalVariableIndexing 1\n"
941 "generalConstantMatrixVectorIndexing 1\n"
942 ;
943
944//
945// *.conf => this is a config file that can set limits/resources
946//
Tony Barbour6918cd52015-04-09 12:58:51 -0600947bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600948{
949 if (name.size() < 5)
950 return false;
951
952 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
953 ConfigFile = name;
954 return true;
955 }
956
957 return false;
958}
959
960//
961// Parse either a .conf file provided by the user or the default string above.
962//
Tony Barbour6918cd52015-04-09 12:58:51 -0600963void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600964{
965 char** configStrings = 0;
966 char* config = 0;
967 if (ConfigFile.size() > 0) {
968 configStrings = ReadFileData(ConfigFile.c_str());
969 if (configStrings)
970 config = *configStrings;
971 else {
972 printf("Error opening configuration file; will instead use the default configuration\n");
973 }
974 }
975
976 if (config == 0) {
977 config = new char[strlen(DefaultConfig) + 1];
978 strcpy(config, DefaultConfig);
979 }
980
981 const char* delims = " \t\n\r";
982 const char* token = strtok(config, delims);
983 while (token) {
984 const char* valueStr = strtok(0, delims);
985 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
986 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
987 return;
988 }
989 int value = atoi(valueStr);
990
991 if (strcmp(token, "MaxLights") == 0)
992 Resources.maxLights = value;
993 else if (strcmp(token, "MaxClipPlanes") == 0)
994 Resources.maxClipPlanes = value;
995 else if (strcmp(token, "MaxTextureUnits") == 0)
996 Resources.maxTextureUnits = value;
997 else if (strcmp(token, "MaxTextureCoords") == 0)
998 Resources.maxTextureCoords = value;
999 else if (strcmp(token, "MaxVertexAttribs") == 0)
1000 Resources.maxVertexAttribs = value;
1001 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1002 Resources.maxVertexUniformComponents = value;
1003 else if (strcmp(token, "MaxVaryingFloats") == 0)
1004 Resources.maxVaryingFloats = value;
1005 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1006 Resources.maxVertexTextureImageUnits = value;
1007 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1008 Resources.maxCombinedTextureImageUnits = value;
1009 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1010 Resources.maxTextureImageUnits = value;
1011 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1012 Resources.maxFragmentUniformComponents = value;
1013 else if (strcmp(token, "MaxDrawBuffers") == 0)
1014 Resources.maxDrawBuffers = value;
1015 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1016 Resources.maxVertexUniformVectors = value;
1017 else if (strcmp(token, "MaxVaryingVectors") == 0)
1018 Resources.maxVaryingVectors = value;
1019 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1020 Resources.maxFragmentUniformVectors = value;
1021 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1022 Resources.maxVertexOutputVectors = value;
1023 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1024 Resources.maxFragmentInputVectors = value;
1025 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1026 Resources.minProgramTexelOffset = value;
1027 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1028 Resources.maxProgramTexelOffset = value;
1029 else if (strcmp(token, "MaxClipDistances") == 0)
1030 Resources.maxClipDistances = value;
1031 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1032 Resources.maxComputeWorkGroupCountX = value;
1033 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1034 Resources.maxComputeWorkGroupCountY = value;
1035 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1036 Resources.maxComputeWorkGroupCountZ = value;
1037 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1038 Resources.maxComputeWorkGroupSizeX = value;
1039 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1040 Resources.maxComputeWorkGroupSizeY = value;
1041 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1042 Resources.maxComputeWorkGroupSizeZ = value;
1043 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1044 Resources.maxComputeUniformComponents = value;
1045 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1046 Resources.maxComputeTextureImageUnits = value;
1047 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1048 Resources.maxComputeImageUniforms = value;
1049 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1050 Resources.maxComputeAtomicCounters = value;
1051 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1052 Resources.maxComputeAtomicCounterBuffers = value;
1053 else if (strcmp(token, "MaxVaryingComponents") == 0)
1054 Resources.maxVaryingComponents = value;
1055 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1056 Resources.maxVertexOutputComponents = value;
1057 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1058 Resources.maxGeometryInputComponents = value;
1059 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1060 Resources.maxGeometryOutputComponents = value;
1061 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1062 Resources.maxFragmentInputComponents = value;
1063 else if (strcmp(token, "MaxImageUnits") == 0)
1064 Resources.maxImageUnits = value;
1065 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1066 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1067 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1068 Resources.maxCombinedShaderOutputResources = value;
1069 else if (strcmp(token, "MaxImageSamples") == 0)
1070 Resources.maxImageSamples = value;
1071 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1072 Resources.maxVertexImageUniforms = value;
1073 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1074 Resources.maxTessControlImageUniforms = value;
1075 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1076 Resources.maxTessEvaluationImageUniforms = value;
1077 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1078 Resources.maxGeometryImageUniforms = value;
1079 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1080 Resources.maxFragmentImageUniforms = value;
1081 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1082 Resources.maxCombinedImageUniforms = value;
1083 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1084 Resources.maxGeometryTextureImageUnits = value;
1085 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1086 Resources.maxGeometryOutputVertices = value;
1087 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1088 Resources.maxGeometryTotalOutputComponents = value;
1089 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1090 Resources.maxGeometryUniformComponents = value;
1091 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1092 Resources.maxGeometryVaryingComponents = value;
1093 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1094 Resources.maxTessControlInputComponents = value;
1095 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1096 Resources.maxTessControlOutputComponents = value;
1097 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1098 Resources.maxTessControlTextureImageUnits = value;
1099 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1100 Resources.maxTessControlUniformComponents = value;
1101 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1102 Resources.maxTessControlTotalOutputComponents = value;
1103 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1104 Resources.maxTessEvaluationInputComponents = value;
1105 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1106 Resources.maxTessEvaluationOutputComponents = value;
1107 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1108 Resources.maxTessEvaluationTextureImageUnits = value;
1109 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1110 Resources.maxTessEvaluationUniformComponents = value;
1111 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1112 Resources.maxTessPatchComponents = value;
1113 else if (strcmp(token, "MaxPatchVertices") == 0)
1114 Resources.maxPatchVertices = value;
1115 else if (strcmp(token, "MaxTessGenLevel") == 0)
1116 Resources.maxTessGenLevel = value;
1117 else if (strcmp(token, "MaxViewports") == 0)
1118 Resources.maxViewports = value;
1119 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1120 Resources.maxVertexAtomicCounters = value;
1121 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1122 Resources.maxTessControlAtomicCounters = value;
1123 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1124 Resources.maxTessEvaluationAtomicCounters = value;
1125 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1126 Resources.maxGeometryAtomicCounters = value;
1127 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1128 Resources.maxFragmentAtomicCounters = value;
1129 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1130 Resources.maxCombinedAtomicCounters = value;
1131 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1132 Resources.maxAtomicCounterBindings = value;
1133 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1134 Resources.maxVertexAtomicCounterBuffers = value;
1135 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1136 Resources.maxTessControlAtomicCounterBuffers = value;
1137 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1138 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1139 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1140 Resources.maxGeometryAtomicCounterBuffers = value;
1141 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1142 Resources.maxFragmentAtomicCounterBuffers = value;
1143 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1144 Resources.maxCombinedAtomicCounterBuffers = value;
1145 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1146 Resources.maxAtomicCounterBufferSize = value;
1147 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1148 Resources.maxTransformFeedbackBuffers = value;
1149 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1150 Resources.maxTransformFeedbackInterleavedComponents = value;
1151 else if (strcmp(token, "MaxCullDistances") == 0)
1152 Resources.maxCullDistances = value;
1153 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1154 Resources.maxCombinedClipAndCullDistances = value;
1155 else if (strcmp(token, "MaxSamples") == 0)
1156 Resources.maxSamples = value;
1157
1158 else if (strcmp(token, "nonInductiveForLoops") == 0)
1159 Resources.limits.nonInductiveForLoops = (value != 0);
1160 else if (strcmp(token, "whileLoops") == 0)
1161 Resources.limits.whileLoops = (value != 0);
1162 else if (strcmp(token, "doWhileLoops") == 0)
1163 Resources.limits.doWhileLoops = (value != 0);
1164 else if (strcmp(token, "generalUniformIndexing") == 0)
1165 Resources.limits.generalUniformIndexing = (value != 0);
1166 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1167 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1168 else if (strcmp(token, "generalVaryingIndexing") == 0)
1169 Resources.limits.generalVaryingIndexing = (value != 0);
1170 else if (strcmp(token, "generalSamplerIndexing") == 0)
1171 Resources.limits.generalSamplerIndexing = (value != 0);
1172 else if (strcmp(token, "generalVariableIndexing") == 0)
1173 Resources.limits.generalVariableIndexing = (value != 0);
1174 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1175 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1176 else
1177 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1178
1179 token = strtok(0, delims);
1180 }
1181 if (configStrings)
1182 FreeFileData(configStrings);
1183}
1184
Tony Barbour6918cd52015-04-09 12:58:51 -06001185void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001186{
1187 if (m_compile_options & EOptionRelaxedErrors)
1188 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1189 if (m_compile_options & EOptionIntermediate)
1190 messages = (EShMessages)(messages | EShMsgAST);
1191 if (m_compile_options & EOptionSuppressWarnings)
1192 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1193}
1194
1195//
1196// Malloc a string of sufficient size and read a string into it.
1197//
Tony Barbour6918cd52015-04-09 12:58:51 -06001198char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001199{
1200 FILE *in;
1201 #if defined(_WIN32) && defined(__GNUC__)
1202 in = fopen(fileName, "r");
1203 int errorCode = in ? 0 : 1;
1204 #else
1205 int errorCode = fopen_s(&in, fileName, "r");
1206 #endif
1207
1208 char *fdata;
1209 int count = 0;
1210 const int maxSourceStrings = 5;
1211 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1212
1213 if (errorCode) {
1214 printf("Error: unable to open input file: %s\n", fileName);
1215 return 0;
1216 }
1217
1218 while (fgetc(in) != EOF)
1219 count++;
1220
1221 fseek(in, 0, SEEK_SET);
1222
1223 if (!(fdata = (char*)malloc(count+2))) {
1224 printf("Error allocating memory\n");
1225 return 0;
1226 }
1227 if (fread(fdata,1,count, in)!=count) {
1228 printf("Error reading input file: %s\n", fileName);
1229 return 0;
1230 }
1231 fdata[count] = '\0';
1232 fclose(in);
1233 if (count == 0) {
1234 return_data[0]=(char*)malloc(count+2);
1235 return_data[0][0]='\0';
1236 m_num_shader_strings = 0;
1237 return return_data;
1238 } else
1239 m_num_shader_strings = 1;
1240
1241 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1242 int ptr_len=0,i=0;
1243 while(count>0){
1244 return_data[i]=(char*)malloc(len+2);
1245 memcpy(return_data[i],fdata+ptr_len,len);
1246 return_data[i][len]='\0';
1247 count-=(len);
1248 ptr_len+=(len);
1249 if(count<len){
1250 if(count==0){
1251 m_num_shader_strings=(i+1);
1252 break;
1253 }
1254 len = count;
1255 }
1256 ++i;
1257 }
1258 return return_data;
1259}
1260
Tony Barbour6918cd52015-04-09 12:58:51 -06001261void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001262{
1263 for(int i=0;i<m_num_shader_strings;i++)
1264 free(data[i]);
1265}
1266
1267//
1268// Deduce the language from the filename. Files must end in one of the
1269// following extensions:
1270//
1271// .vert = vertex
1272// .tesc = tessellation control
1273// .tese = tessellation evaluation
1274// .geom = geometry
1275// .frag = fragment
1276// .comp = compute
1277//
Tony Barbour6918cd52015-04-09 12:58:51 -06001278EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001279{
1280 size_t ext = name.rfind('.');
1281 if (ext == std::string::npos) {
1282 return EShLangVertex;
1283 }
1284
1285 std::string suffix = name.substr(ext + 1, std::string::npos);
1286 if (suffix == "vert")
1287 return EShLangVertex;
1288 else if (suffix == "tesc")
1289 return EShLangTessControl;
1290 else if (suffix == "tese")
1291 return EShLangTessEvaluation;
1292 else if (suffix == "geom")
1293 return EShLangGeometry;
1294 else if (suffix == "frag")
1295 return EShLangFragment;
1296 else if (suffix == "comp")
1297 return EShLangCompute;
1298
1299 return EShLangVertex;
1300}
1301
1302//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001303// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001304//
Tony Barbourd1c35722015-04-16 15:59:00 -06001305EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001306{
1307 switch (shader_type) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001308 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001309 return EShLangVertex;
1310
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001311 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001312 return EShLangTessControl;
1313
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001314 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001315 return EShLangTessEvaluation;
1316
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001317 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001318 return EShLangGeometry;
1319
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001320 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001321 return EShLangFragment;
1322
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001323 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001324 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001325
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001326 default:
1327 return EShLangVertex;
1328 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001329}
1330
1331
1332//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001333// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001334// Return value of false means an error was encountered.
1335//
Tony Barbourd1c35722015-04-16 15:59:00 -06001336bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001337 const char *pshader,
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001338 std::vector<unsigned int> &spv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001339{
1340 glslang::TProgram& program = *new glslang::TProgram;
1341 const char *shaderStrings[1];
1342
1343 // TODO: Do we want to load a special config file depending on the
1344 // shader source? Optional name maybe?
1345 // SetConfigFile(fileName);
1346
1347 ProcessConfigFile();
1348
1349 EShMessages messages = EShMsgDefault;
1350 SetMessageOptions(messages);
1351
1352 EShLanguage stage = FindLanguage(shader_type);
1353 glslang::TShader* shader = new glslang::TShader(stage);
1354
1355 shaderStrings[0] = pshader;
1356 shader->setStrings(shaderStrings, 1);
1357
1358 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1359
Cody Northrop195d6622014-11-03 12:54:37 -07001360 if (! (m_compile_options & EOptionSuppressInfolog)) {
1361 puts(shader->getInfoLog());
1362 puts(shader->getInfoDebugLog());
1363 }
1364
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001365 return false; // something didn't work
1366 }
1367
1368 program.addShader(shader);
1369
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001370
1371 //
1372 // Program-level processing...
1373 //
1374
Cody Northrop195d6622014-11-03 12:54:37 -07001375 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001376
Cody Northrop195d6622014-11-03 12:54:37 -07001377 if (! (m_compile_options & EOptionSuppressInfolog)) {
1378 puts(shader->getInfoLog());
1379 puts(shader->getInfoDebugLog());
1380 }
1381
1382 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001383 }
1384
1385 if (m_compile_options & EOptionDumpReflection) {
1386 program.buildReflection();
1387 program.dumpReflection();
1388 }
1389
Cody Northrop3bfd27c2015-03-17 15:55:58 -06001390 glslang::GlslangToSpv(*program.getIntermediate(stage), spv);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001391
1392 return true;
1393}
1394
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001395
1396
Tony Barbour6918cd52015-04-09 12:58:51 -06001397VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001398 m_width( 0 ),
1399 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001400 m_data( NULL ),
1401 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001402{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001403}
1404
Tony Barbour6918cd52015-04-09 12:58:51 -06001405VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001406{
1407
1408}
1409
Tony Barbour6918cd52015-04-09 12:58:51 -06001410VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001411{
1412 m_title = copyin.m_title;
1413 m_width = copyin.m_width;
1414 m_height = copyin.m_height;
1415 m_data_size = copyin.m_data_size;
1416 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1417}
1418
Tony Barbour6918cd52015-04-09 12:58:51 -06001419ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001420{
Tony Barbour6918cd52015-04-09 12:58:51 -06001421 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1422 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001423 return output;
1424}
1425
Tony Barbour6918cd52015-04-09 12:58:51 -06001426VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001427{
1428 m_title = rhs.m_title;
1429 m_width = rhs.m_width;
1430 m_height = rhs.m_height;
1431 m_data_size = rhs.m_data_size;
1432 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001433 return *this;
1434}
1435
Tony Barbour6918cd52015-04-09 12:58:51 -06001436int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001437{
1438 if( this->m_data != rhs.m_data) return 0;
1439 return 1;
1440}
1441
1442// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001443int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001444{
1445 if( this->m_data_size < rhs.m_data_size ) return 1;
1446 return 0;
1447}
1448