blob: 0ae8e4ff015fa34badcf9ca92667269d153a7571 [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
Tony Barbour6918cd52015-04-09 12:58:51 -0600167bool VkTestFramework::m_use_spv = 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
Tony Barbour6918cd52015-04-09 12:58:51 -0600172bool VkTestFramework::m_use_spv = true;
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
Tony Barbour6918cd52015-04-09 12:58:51 -0600183void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600184{
185 int i, n;
186
187 for (i=0, n=0; i< *argc; i++) {
188 if (strncmp("--show-images", argv[i], 13) == 0) {
189 m_show_images = true;
190 continue;
191 }
192 if (strncmp("--save-images", argv[i], 13) == 0) {
193 m_save_images = true;
194 continue;
195 }
196
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600197 if (strncmp("--use-SPV", argv[i], 13) == 0) {
198 m_use_spv = true;
Courtney Goeltzenleuchterb666dc62014-10-09 09:13:56 -0600199 continue;
200 }
201
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600202 if (strncmp("--no-SPV", argv[i], 13) == 0) {
203 m_use_spv = false;
Courtney Goeltzenleuchterc44e3ee2014-10-31 14:13:33 -0600204 continue;
205 }
206
Tony Barbour247bf372014-10-30 14:29:04 -0600207 if (strncmp("--compare-images", argv[i], 16) == 0) {
208 m_compare_images = true;
209 continue;
210 }
211
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600212 /*
213 * Since the above "consume" inputs, update argv
214 * so that it contains the trimmed list of args for glutInit
215 */
Tony Barboura98d3932014-12-11 09:52:49 -0700216 if (strncmp("--help", argv[i], 6) == 0 || strncmp("-h", argv[i], 2) == 0) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700217 printf("\nOther options:\n");
218 printf("\t--show-images\n"
219 "\t\tDisplay test images in viewer after tests complete.\n");
220 printf("\t--save-images\n"
221 "\t\tSave tests images as ppm files in current working directory.\n"
222 "\t\tUsed to generate golden images for compare-images.\n");
223 printf("\t--compare-images\n"
224 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barboura98d3932014-12-11 09:52:49 -0700225 "\t\tAlso saves the generated test image in current working\n"
226 "\t\t\tdirectory but only if the image is different from the golden\n"
227 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
228 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700229 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600230 printf("\t--use-SPV\n"
231 "\t\tUse SPV code path (default).\n");
232 printf("\t--no-SPV\n"
233 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700234 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700235 }
236
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600237 argv[n] = argv[i];
238 n++;
239 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600240}
241
Tony Barbour6918cd52015-04-09 12:58:51 -0600242void VkTestFramework::WritePPM( const char *basename, VkImageObj *image )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600243{
244 string filename;
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600245 VkResult err;
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600246 uint32_t x, y;
Tony Barbour6918cd52015-04-09 12:58:51 -0600247 VkImageObj displayImage(image->device());
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600248 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Tony Barbour84d448c2015-04-02 14:02:33 -0600249
Tony Barbour4c97d7a2015-04-22 15:10:33 -0600250 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, VK_IMAGE_TILING_LINEAR, reqs);
Tony Barbour84d448c2015-04-02 14:02:33 -0600251 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600252
253 filename.append(basename);
254 filename.append(".ppm");
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600255
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600256 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600257 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600258 };
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600259 VkSubresourceLayout sr_layout;
Chia-I Wu99ff89d2014-12-27 14:14:50 +0800260 size_t data_size = sizeof(sr_layout);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600261
262 err = vkGetImageSubresourceInfo(image->device()->device(), displayImage.image(), &sr,
Tony Barbourd1c35722015-04-16 15:59:00 -0600263 VK_SUBRESOURCE_INFO_TYPE_LAYOUT,
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600264 &data_size, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600265 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600266 ASSERT_EQ(data_size, sizeof(sr_layout));
267
Tony Barbour84d448c2015-04-02 14:02:33 -0600268 char *ptr;
269 ptr = (char *) displayImage.map();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600270 ptr += sr_layout.offset;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600271 ofstream file (filename.c_str(), ios::binary);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600272 ASSERT_TRUE(file.is_open()) << "Unable to open file: " << filename;
273
274 file << "P6\n";
Tony Barbour84d448c2015-04-02 14:02:33 -0600275 file << displayImage.width() << "\n";
276 file << displayImage.height() << "\n";
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600277 file << 255 << "\n";
278
Tony Barbour84d448c2015-04-02 14:02:33 -0600279 for (y = 0; y < displayImage.height(); y++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700280 const int *row = (const int *) ptr;
281 int swapped;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600282
Tony Barbourd1c35722015-04-16 15:59:00 -0600283 if (displayImage.format() == VK_FORMAT_B8G8R8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700284 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600285 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700286 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
287 file.write((char *) &swapped, 3);
288 row++;
289 }
290 }
Tony Barbourd1c35722015-04-16 15:59:00 -0600291 else if (displayImage.format() == VK_FORMAT_R8G8B8A8_UNORM)
Tony Barboura53a6942015-02-25 11:25:11 -0700292 {
Tony Barbour84d448c2015-04-02 14:02:33 -0600293 for (x = 0; x < displayImage.width(); x++) {
Tony Barboura53a6942015-02-25 11:25:11 -0700294 file.write((char *) row, 3);
295 row++;
296 }
297 }
298 else {
299 printf("Unrecognized image format - will not write image files");
300 break;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600301 }
302
303 ptr += sr_layout.rowPitch;
304 }
305
306 file.close();
Tony Barbour84d448c2015-04-02 14:02:33 -0600307 displayImage.unmap();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600308}
309
Tony Barbour6918cd52015-04-09 12:58:51 -0600310void VkTestFramework::Compare(const char *basename, VkImageObj *image )
Tony Barbour247bf372014-10-30 14:29:04 -0600311{
312
313 MagickWand *magick_wand_1;
314 MagickWand *magick_wand_2;
315 MagickWand *compare_wand;
316 MagickBooleanType status;
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600317 char testimage[256],golden[MAX_PATH+256],golddir[MAX_PATH] = "./golden";
Tony Barbour247bf372014-10-30 14:29:04 -0600318 double differenz;
319
Tony Barbour4ab45422014-12-10 17:00:20 -0700320 if (getenv("RENDERTEST_GOLDEN_DIR"))
321 {
322 strcpy(golddir,getenv("RENDERTEST_GOLDEN_DIR"));
323 }
324
Tony Barbour247bf372014-10-30 14:29:04 -0600325 MagickWandGenesis();
326 magick_wand_1=NewMagickWand();
327 sprintf(testimage,"%s.ppm",basename);
328 status=MagickReadImage(magick_wand_1,testimage);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600329 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << testimage;
Tony Barbour247bf372014-10-30 14:29:04 -0600330
331
332 MagickWandGenesis();
333 magick_wand_2=NewMagickWand();
Tony Barbour4ab45422014-12-10 17:00:20 -0700334 sprintf(golden,"%s/%s.ppm",golddir,basename);
Tony Barbour247bf372014-10-30 14:29:04 -0600335 status=MagickReadImage(magick_wand_2,golden);
Tony Barbour7ea6aa22015-05-22 09:44:58 -0600336 ASSERT_EQ(status, MagickTrue) << "Unable to open file: " << golden;
Tony Barbour247bf372014-10-30 14:29:04 -0600337
Tony Barbour247bf372014-10-30 14:29:04 -0600338 compare_wand=MagickCompareImages(magick_wand_1,magick_wand_2, MeanAbsoluteErrorMetric, &differenz);
339 if (differenz != 0.0)
340 {
341 char difference[256];
342
343 sprintf(difference,"%s-diff.ppm",basename);
344 status = MagickWriteImage(compare_wand, difference);
345 ASSERT_TRUE(differenz == 0.0) << "Image comparison failed - diff file written";
346 }
347 DestroyMagickWand(compare_wand);
348
349 DestroyMagickWand(magick_wand_1);
350 DestroyMagickWand(magick_wand_2);
351 MagickWandTerminus();
Courtney Goeltzenleuchterfcda72d2014-12-05 15:41:02 -0700352
353 if (differenz == 0.0)
354 {
355 /*
356 * If test image and golden image match, we do not need to
357 * keep around the test image.
358 */
359 remove(testimage);
360 }
Tony Barbour247bf372014-10-30 14:29:04 -0600361}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600362
Tony Barbour6918cd52015-04-09 12:58:51 -0600363void VkTestFramework::Show(const char *comment, VkImageObj *image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600364{
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600365 VkResult err;
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600366 VkSubresourceLayout sr_layout;
367 char *ptr;
368 VkTestImageRecord record;
369 size_t data_size = sizeof(sr_layout);
370 VkImageObj displayImage(image->device());
371 VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
372
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600373 displayImage.init(image->extent().width, image->extent().height, image->format(), 0, VK_IMAGE_TILING_LINEAR, reqs);
374 displayImage.CopyImage(*image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600375
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600376 const VkImageSubresource sr = {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600377 VK_IMAGE_ASPECT_COLOR, 0, 0
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600378 };
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600379
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600380 err = vkGetImageSubresourceInfo(displayImage.device()->device(), displayImage.image(), &sr,
381 VK_SUBRESOURCE_INFO_TYPE_LAYOUT,
382 &data_size, &sr_layout);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600383 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600384 ASSERT_EQ(data_size, sizeof(sr_layout));
385
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600386 err = displayImage.MapMemory( (void **) &ptr );
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600387 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600388
389 ptr += sr_layout.offset;
390
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600391 record.m_title.append(comment);
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600392 record.m_width = displayImage.width();
393 record.m_height = displayImage.height();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600394 // TODO: Need to make this more robust to handle different image formats
Tony-LunarG399dfca2015-05-19 14:08:26 -0600395 record.m_data_size = displayImage.width() * displayImage.height() * 4;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600396 record.m_data = malloc(record.m_data_size);
397 memcpy(record.m_data, ptr, record.m_data_size);
398 m_images.push_back(record);
399 m_display_image = --m_images.end();
400
Courtney Goeltzenleuchterfcf43ab2015-04-29 10:53:31 -0600401 err = displayImage.UnmapMemory();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600402 ASSERT_VK_SUCCESS( err );
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600403}
404
Tony Barbour6918cd52015-04-09 12:58:51 -0600405void VkTestFramework::RecordImages(vector<VkImageObj *> images)
Tony Barbour247bf372014-10-30 14:29:04 -0600406{
Courtney Goeltzenleuchtere5f0e6c2015-04-02 14:17:44 -0600407 for (int32_t i = 0; i < images.size(); i++) {
408 RecordImage(images[i]);
Tony Barbour247bf372014-10-30 14:29:04 -0600409 }
410}
411
Tony Barbour6918cd52015-04-09 12:58:51 -0600412void VkTestFramework::RecordImage(VkImageObj * image)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600413{
414 const ::testing::TestInfo* const test_info =
415 ::testing::UnitTest::GetInstance()->current_test_info();
Tony Barbour247bf372014-10-30 14:29:04 -0600416 ostringstream filestream;
417 string filename;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600418
Tony Barbour247bf372014-10-30 14:29:04 -0600419 m_width = 40;
420
421 if (strcmp(test_info->name(), m_testName.c_str())) {
422 filestream << test_info->name();
423 m_testName.assign(test_info->name());
Tony Barboura0e2ee82014-11-18 17:02:36 -0700424 m_frameNum = 2;
425 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600426 }
427 else {
428 filestream << test_info->name() << "-" << m_frameNum;
429 m_frameNum++;
Tony Barboura0e2ee82014-11-18 17:02:36 -0700430 filename = filestream.str();
Tony Barbour247bf372014-10-30 14:29:04 -0600431 }
432
Tony Barbour247bf372014-10-30 14:29:04 -0600433 // ToDo - scrub string for bad characters
434
435 if (m_save_images || m_compare_images) {
436 WritePPM(filename.c_str(), image);
437 if (m_compare_images) {
438 Compare(filename.c_str(), image);
439 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600440 }
441
442 if (m_show_images) {
Courtney Goeltzenleuchter02d33c12014-10-08 14:26:40 -0600443 Show(test_info->name(), image);
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600444 }
445}
446
Chia-I Wuf8693382015-04-16 22:02:10 +0800447TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
448 m_device(device),
Courtney Goeltzenleuchterb4337c12015-03-05 16:47:18 -0700449 m_queue(*m_device.graphics_queues()[0]),
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600450 m_cmdbuf(m_device, vk_testing::CmdBuffer::create_info(m_device.graphics_queue_node_index_))
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600451{
Tony Barbour96db8822015-02-25 12:28:39 -0700452 m_quit = false;
453 m_pause = false;
454 m_width = 0;
455 m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600456}
457
Tony Barbour6918cd52015-04-09 12:58:51 -0600458void TestFrameworkVkPresent::Display()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600459{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600460 VkResult U_ASSERT_ONLY err;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600461 vk_testing::Buffer buf;
462 void *dest_ptr;
463
464 if (m_persistent_images.size() != 2) {
465 return;
466 }
467
468 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
469 buf.init(m_device, (VkDeviceSize)m_display_image->m_data_size, flags);
470 dest_ptr = buf.map();
471 memcpy(dest_ptr, m_display_image->m_data, m_display_image->m_data_size);
472 buf.unmap();
473
474 m_cmdbuf.begin();
475
476 VkBufferImageCopy region = {};
477 region.imageExtent.height = m_display_image->m_height;
478 region.imageExtent.width = m_display_image->m_width;
479 region.imageExtent.depth = 1;
480
481 vkCmdCopyBufferToImage(m_cmdbuf.obj(),
482 buf.obj(),
483 m_persistent_images[m_current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
484 1, &region);
485 m_cmdbuf.end();
486
487 VkCmdBuffer cmdBufs[1];
488 cmdBufs[0] = m_cmdbuf.obj();
489
490 vkQueueSubmit(m_queue.obj(), 1, cmdBufs, NULL);
491 m_queue.wait();
Tony Barbour96db8822015-02-25 12:28:39 -0700492
Chia-I Wuf8693382015-04-16 22:02:10 +0800493 VkPresentInfoWSI present = {};
494 present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_WSI;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600495 present.image = m_persistent_images[m_current_buffer].image;
Chia-I Wuf8693382015-04-16 22:02:10 +0800496 present.flipInterval = 1;
Tony Barbour96db8822015-02-25 12:28:39 -0700497
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600498#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800499 xcb_change_property (m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700500 XCB_PROP_MODE_REPLACE,
501 m_window,
502 XCB_ATOM_WM_NAME,
503 XCB_ATOM_STRING,
504 8,
505 m_display_image->m_title.size(),
506 m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600507#endif
Chia-I Wuf8693382015-04-16 22:02:10 +0800508 err = vkQueuePresentWSI(m_queue.obj(), &present);
Tony Barbour96db8822015-02-25 12:28:39 -0700509 assert(!err);
510
511 m_queue.wait();
Tony-LunarG399dfca2015-05-19 14:08:26 -0600512 m_current_buffer = (m_current_buffer + 1) % 2;
Tony Barbour96db8822015-02-25 12:28:39 -0700513
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600514}
515
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600516#ifdef _WIN32
Tony-LunarG399dfca2015-05-19 14:08:26 -0600517# define PREVIOUSLY_DOWN 1<<29
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600518// MS-Windows event handling function:
519LRESULT CALLBACK TestFrameworkVkPresent::WndProc(HWND hWnd,
520 UINT uMsg,
521 WPARAM wParam,
522 LPARAM lParam)
523{
524
525 switch(uMsg)
526 {
527 case WM_CLOSE:
528 PostQuitMessage(0);
529 break;
530
531 case WM_PAINT:
532 {
533 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
534 if (me) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600535 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600536 me->Display();
537 }
538 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600539 break;
540
541 case WM_KEYDOWN:
542 {
543 if (lParam & (PREVIOUSLY_DOWN)){
544 break;
545 }
546 // To be able to be a CALLBACK, WndProc had to be static, so it doesn't get a this pointer. When we created
547 // the window, we put the this pointer into the window's user data so we could get it back now
548 TestFrameworkVkPresent* me = reinterpret_cast<TestFrameworkVkPresent*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
549 switch (wParam)
550 {
551 case VK_ESCAPE: me->m_quit = true;
552 break;
553
554 case VK_LEFT: // left arrow key
555 if (me->m_display_image == me->m_images.begin()) {
556 me->m_display_image = --me->m_images.end();
557 }
558 else {
559 --me->m_display_image;
560 }
561 break;
562
563 case VK_RIGHT: // right arrow key
564 ++me->m_display_image;
565 if (me->m_display_image == me->m_images.end()) {
566 me->m_display_image = me->m_images.begin();
567 }
568 break;
569
570 default:
571 break;
572 }
573 SetWindowText(hWnd, me->m_display_image->m_title.c_str());
574 me->Display();
575 }
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600576 }
577 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
578}
579
580void TestFrameworkVkPresent::Run()
581{
582 MSG msg; // message
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600583
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600584 /* main message loop*/
Tony-LunarG399dfca2015-05-19 14:08:26 -0600585 while(! m_quit) {
586 GetMessage(&msg, m_window, 0, 0);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600587 if (msg.message == WM_QUIT) {
Tony-LunarG399dfca2015-05-19 14:08:26 -0600588 m_quit = true; //if found, quit app
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600589 } else {
590 /* Translate and dispatch to event queue*/
591 TranslateMessage(&msg);
592 DispatchMessage(&msg);
593 }
594 }
595}
596
597#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600598void TestFrameworkVkPresent::HandleEvent(xcb_generic_event_t *event)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600599{
Tony Barbour0dd968a2015-04-02 15:48:24 -0600600 uint8_t event_code = event->response_type & 0x7f;
Tony Barbour96db8822015-02-25 12:28:39 -0700601 switch (event_code) {
602 case XCB_EXPOSE:
603 Display(); // TODO: handle resize
604 break;
605 case XCB_CLIENT_MESSAGE:
606 if((*(xcb_client_message_event_t*)event).data.data32[0] ==
607 (m_atom_wm_delete_window)->atom) {
608 m_quit = true;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600609 }
610 break;
Tony Barbour96db8822015-02-25 12:28:39 -0700611 case XCB_KEY_RELEASE:
612 {
613 const xcb_key_release_event_t *key =
614 (const xcb_key_release_event_t *) event;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600615
Tony Barbour96db8822015-02-25 12:28:39 -0700616 switch (key->detail) {
617 case 0x9: // Escape
618 m_quit = true;
619 break;
620 case 0x71: // left arrow key
621 if (m_display_image == m_images.begin()) {
622 m_display_image = --m_images.end();
623 } else {
624 --m_display_image;
625 }
626 break;
627 case 0x72: // right arrow key
628 ++m_display_image;
629 if (m_display_image == m_images.end()) {
630 m_display_image = m_images.begin();
631 }
632 break;
633 case 0x41:
634 m_pause = !m_pause;
635 break;
636 }
637 Display();
638 }
639 break;
640 default:
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600641 break;
642 }
Tony Barbour96db8822015-02-25 12:28:39 -0700643}
644
Tony Barbour6918cd52015-04-09 12:58:51 -0600645void TestFrameworkVkPresent::Run()
Tony Barbour96db8822015-02-25 12:28:39 -0700646{
Chia-I Wuf8693382015-04-16 22:02:10 +0800647 xcb_flush(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700648
649 while (! m_quit) {
650 xcb_generic_event_t *event;
651
652 if (m_pause) {
Chia-I Wuf8693382015-04-16 22:02:10 +0800653 event = xcb_wait_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700654 } else {
Chia-I Wuf8693382015-04-16 22:02:10 +0800655 event = xcb_poll_for_event(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700656 }
657 if (event) {
658 HandleEvent(event);
659 free(event);
660 }
661 }
662}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600663#endif // _WIN32
Tony Barbour96db8822015-02-25 12:28:39 -0700664
Chia-I Wuf8693382015-04-16 22:02:10 +0800665void TestFrameworkVkPresent::CreateSwapChain()
Tony Barbour96db8822015-02-25 12:28:39 -0700666{
Tony Barbourf20f87b2015-04-22 09:02:32 -0600667 VkResult U_ASSERT_ONLY err;
Tony Barbour96db8822015-02-25 12:28:39 -0700668
Tony-LunarG399dfca2015-05-19 14:08:26 -0600669 m_display_image = m_images.begin();
670 m_current_buffer = 0;
671
Chia-I Wuf8693382015-04-16 22:02:10 +0800672 VkSwapChainCreateInfoWSI swap_chain = {};
673 swap_chain.sType = VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI;
674 swap_chain.pNativeWindowSystemHandle = (void *) m_connection;
675 swap_chain.pNativeWindowHandle = (void *) (intptr_t) m_window;
Tony-LunarG399dfca2015-05-19 14:08:26 -0600676 swap_chain.imageCount = 2;
Chia-I Wuf8693382015-04-16 22:02:10 +0800677 swap_chain.imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
678 swap_chain.imageExtent.width = m_width;
679 swap_chain.imageExtent.height = m_height;
680 swap_chain.imageArraySize = 1;
681 swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT;
682 swap_chain.swapModeFlags = VK_SWAP_MODE_FLIP_BIT_WSI |
683 VK_SWAP_MODE_BLIT_BIT_WSI;
684
685 err = vkCreateSwapChainWSI(m_device.obj(), &swap_chain, &m_swap_chain);
686 assert(!err);
687
Tony-LunarG399dfca2015-05-19 14:08:26 -0600688 size_t size = sizeof(VkSwapChainImageInfoWSI) * 2;
689 VkSwapChainImageInfoWSI infos[2];
690
Chia-I Wuf8693382015-04-16 22:02:10 +0800691 err = vkGetSwapChainInfoWSI(m_swap_chain,
692 VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI,
Tony-LunarG399dfca2015-05-19 14:08:26 -0600693 &size, &infos);
694 assert(!err && size == sizeof(VkSwapChainImageInfoWSI) * 2);
695 m_persistent_images.push_back(infos[0]);
696 m_persistent_images.push_back(infos[1]);
Tony Barbour96db8822015-02-25 12:28:39 -0700697}
698
Tony Barbour6918cd52015-04-09 12:58:51 -0600699void TestFrameworkVkPresent::InitPresentFramework(std::list<VkTestImageRecord> &imagesIn)
Tony Barbour96db8822015-02-25 12:28:39 -0700700{
701 m_images = imagesIn;
702}
703
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600704#ifdef _WIN32
705void TestFrameworkVkPresent::CreateMyWindow()
706{
707 WNDCLASSEX win_class;
708 // const ::testing::TestInfo* const test_info =
709 // ::testing::UnitTest::GetInstance()->current_test_info();
710 m_connection = GetModuleHandle(NULL);
711
712 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
713 it != m_images.end(); it++) {
714 if (m_width < it->m_width)
715 m_width = it->m_width;
716 if (m_height < it->m_height)
717 m_height = it->m_height;
718 }
719 // Initialize the window class structure:
720 win_class.cbSize = sizeof(WNDCLASSEX);
721 win_class.style = CS_HREDRAW | CS_VREDRAW;
722 win_class.lpfnWndProc = (WNDPROC) &TestFrameworkVkPresent::WndProc;
723 win_class.cbClsExtra = 0;
724 win_class.cbWndExtra = 0;
725 win_class.hInstance = m_connection; // hInstance
726 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
727 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
728 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
729 win_class.lpszMenuName = NULL;
730 win_class.lpszClassName = "Test";
731 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
732 // Register window class:
733 if (!RegisterClassEx(&win_class)) {
734 // It didn't work, so try to give a useful error:
735 printf("Unexpected error trying to start the application!\n");
736 fflush(stdout);
737 exit(1);
738 }
739 // Create window with the registered class:
740 m_window = CreateWindowEx(0,
741 "Test", // class name
742 "Test", // app name
743 WS_OVERLAPPEDWINDOW | // window style
744 WS_VISIBLE |
745 WS_SYSMENU,
746 100,100, // x/y coords
747 m_width, // width
748 m_height, // height
749 NULL, // handle to parent
750 NULL, // handle to menu
751 m_connection, // hInstance
752 NULL); // no extra parameters
753
754 if (!m_window) {
755 // It didn't work, so try to give a useful error:
756 DWORD error = GetLastError();
757 char message[120];
758 sprintf(message, "Cannot create a window in which to draw!\n GetLastError = %d", error);
759 MessageBox(NULL, message, "Error", MB_OK);
760 exit(1);
761 }
Tony-LunarG399dfca2015-05-19 14:08:26 -0600762 // Put our this pointer into the window's user data so our WndProc can use it when it starts.
763 SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR) this);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600764}
765#else
Tony Barbour6918cd52015-04-09 12:58:51 -0600766void TestFrameworkVkPresent::CreateMyWindow()
Tony Barbour96db8822015-02-25 12:28:39 -0700767{
Chia-I Wuf8693382015-04-16 22:02:10 +0800768 const xcb_setup_t *setup;
769 xcb_screen_iterator_t iter;
770 int scr;
Tony Barbour96db8822015-02-25 12:28:39 -0700771 uint32_t value_mask, value_list[32];
772
Chia-I Wuf8693382015-04-16 22:02:10 +0800773 m_connection = xcb_connect(NULL, &scr);
774
775 setup = xcb_get_setup(m_connection);
776 iter = xcb_setup_roots_iterator(setup);
777 while (scr-- > 0)
778 xcb_screen_next(&iter);
779
780 m_screen = iter.data;
781
782 for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
783 it != m_images.end(); it++) {
784 if (m_width < it->m_width)
785 m_width = it->m_width;
786 if (m_height < it->m_height)
787 m_height = it->m_height;
788 }
789
790 m_window = xcb_generate_id(m_connection);
Tony Barbour96db8822015-02-25 12:28:39 -0700791
792 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
Chia-I Wuf8693382015-04-16 22:02:10 +0800793 value_list[0] = m_screen->black_pixel;
Tony Barbour96db8822015-02-25 12:28:39 -0700794 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
795 XCB_EVENT_MASK_EXPOSURE |
796 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
797
Chia-I Wuf8693382015-04-16 22:02:10 +0800798 xcb_create_window(m_connection,
Tony Barbour96db8822015-02-25 12:28:39 -0700799 XCB_COPY_FROM_PARENT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800800 m_window, m_screen->root,
Tony Barbour96db8822015-02-25 12:28:39 -0700801 0, 0, m_width, m_height, 0,
802 XCB_WINDOW_CLASS_INPUT_OUTPUT,
Chia-I Wuf8693382015-04-16 22:02:10 +0800803 m_screen->root_visual,
Tony Barbour96db8822015-02-25 12:28:39 -0700804 value_mask, value_list);
805
806 /* Magic code that will send notification when window is destroyed */
Chia-I Wuf8693382015-04-16 22:02:10 +0800807 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
Tony Barbour96db8822015-02-25 12:28:39 -0700808 "WM_PROTOCOLS");
Chia-I Wuf8693382015-04-16 22:02:10 +0800809 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
Tony Barbour96db8822015-02-25 12:28:39 -0700810
Chia-I Wuf8693382015-04-16 22:02:10 +0800811 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
812 m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
Tony Barbour96db8822015-02-25 12:28:39 -0700813
Chia-I Wuf8693382015-04-16 22:02:10 +0800814 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
Tony Barbour96db8822015-02-25 12:28:39 -0700815 m_window, (*reply).atom, 4, 32, 1,
816 &(*m_atom_wm_delete_window).atom);
817 free(reply);
818
Chia-I Wuf8693382015-04-16 22:02:10 +0800819 xcb_map_window(m_connection, m_window);
Tony Barbour96db8822015-02-25 12:28:39 -0700820}
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600821#endif
Tony Barbour96db8822015-02-25 12:28:39 -0700822
Tony Barbour6918cd52015-04-09 12:58:51 -0600823void TestFrameworkVkPresent::TearDown()
Tony Barbour96db8822015-02-25 12:28:39 -0700824{
Chia-I Wuf8693382015-04-16 22:02:10 +0800825 vkDestroySwapChainWSI(m_swap_chain);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600826#ifndef _WIN32
Chia-I Wuf8693382015-04-16 22:02:10 +0800827 xcb_destroy_window(m_connection, m_window);
828 xcb_disconnect(m_connection);
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600829#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600830}
831
Tony Barbour6918cd52015-04-09 12:58:51 -0600832void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600833{
834 if (m_images.size() == 0) return;
835
Chia-I Wuf8693382015-04-16 22:02:10 +0800836 vk_testing::Environment env;
837 env.SetUp();
Tony Barbour96db8822015-02-25 12:28:39 -0700838 {
Chia-I Wuf8693382015-04-16 22:02:10 +0800839 TestFrameworkVkPresent vkPresent(env.default_device());
Tony Barbour96db8822015-02-25 12:28:39 -0700840
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600841 vkPresent.InitPresentFramework(m_images);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600842 vkPresent.CreateMyWindow();
Chia-I Wuf8693382015-04-16 22:02:10 +0800843 vkPresent.CreateSwapChain();
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600844 vkPresent.Run();
845 vkPresent.TearDown();
Tony Barbour96db8822015-02-25 12:28:39 -0700846 }
Chia-I Wuf8693382015-04-16 22:02:10 +0800847 env.TearDown();
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600848}
849
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600850//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600851// These are the default resources for TBuiltInResources, used for both
852// - parsing this string for the case where the user didn't supply one
853// - dumping out a template for user construction of a config file
854//
855static const char* DefaultConfig =
856 "MaxLights 32\n"
857 "MaxClipPlanes 6\n"
858 "MaxTextureUnits 32\n"
859 "MaxTextureCoords 32\n"
860 "MaxVertexAttribs 64\n"
861 "MaxVertexUniformComponents 4096\n"
862 "MaxVaryingFloats 64\n"
863 "MaxVertexTextureImageUnits 32\n"
864 "MaxCombinedTextureImageUnits 80\n"
865 "MaxTextureImageUnits 32\n"
866 "MaxFragmentUniformComponents 4096\n"
867 "MaxDrawBuffers 32\n"
868 "MaxVertexUniformVectors 128\n"
869 "MaxVaryingVectors 8\n"
870 "MaxFragmentUniformVectors 16\n"
871 "MaxVertexOutputVectors 16\n"
872 "MaxFragmentInputVectors 15\n"
873 "MinProgramTexelOffset -8\n"
874 "MaxProgramTexelOffset 7\n"
875 "MaxClipDistances 8\n"
876 "MaxComputeWorkGroupCountX 65535\n"
877 "MaxComputeWorkGroupCountY 65535\n"
878 "MaxComputeWorkGroupCountZ 65535\n"
879 "MaxComputeWorkGroupSizeX 1024\n"
880 "MaxComputeWorkGroupSizeY 1024\n"
881 "MaxComputeWorkGroupSizeZ 64\n"
882 "MaxComputeUniformComponents 1024\n"
883 "MaxComputeTextureImageUnits 16\n"
884 "MaxComputeImageUniforms 8\n"
885 "MaxComputeAtomicCounters 8\n"
886 "MaxComputeAtomicCounterBuffers 1\n"
887 "MaxVaryingComponents 60\n"
888 "MaxVertexOutputComponents 64\n"
889 "MaxGeometryInputComponents 64\n"
890 "MaxGeometryOutputComponents 128\n"
891 "MaxFragmentInputComponents 128\n"
892 "MaxImageUnits 8\n"
893 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
894 "MaxCombinedShaderOutputResources 8\n"
895 "MaxImageSamples 0\n"
896 "MaxVertexImageUniforms 0\n"
897 "MaxTessControlImageUniforms 0\n"
898 "MaxTessEvaluationImageUniforms 0\n"
899 "MaxGeometryImageUniforms 0\n"
900 "MaxFragmentImageUniforms 8\n"
901 "MaxCombinedImageUniforms 8\n"
902 "MaxGeometryTextureImageUnits 16\n"
903 "MaxGeometryOutputVertices 256\n"
904 "MaxGeometryTotalOutputComponents 1024\n"
905 "MaxGeometryUniformComponents 1024\n"
906 "MaxGeometryVaryingComponents 64\n"
907 "MaxTessControlInputComponents 128\n"
908 "MaxTessControlOutputComponents 128\n"
909 "MaxTessControlTextureImageUnits 16\n"
910 "MaxTessControlUniformComponents 1024\n"
911 "MaxTessControlTotalOutputComponents 4096\n"
912 "MaxTessEvaluationInputComponents 128\n"
913 "MaxTessEvaluationOutputComponents 128\n"
914 "MaxTessEvaluationTextureImageUnits 16\n"
915 "MaxTessEvaluationUniformComponents 1024\n"
916 "MaxTessPatchComponents 120\n"
917 "MaxPatchVertices 32\n"
918 "MaxTessGenLevel 64\n"
919 "MaxViewports 16\n"
920 "MaxVertexAtomicCounters 0\n"
921 "MaxTessControlAtomicCounters 0\n"
922 "MaxTessEvaluationAtomicCounters 0\n"
923 "MaxGeometryAtomicCounters 0\n"
924 "MaxFragmentAtomicCounters 8\n"
925 "MaxCombinedAtomicCounters 8\n"
926 "MaxAtomicCounterBindings 1\n"
927 "MaxVertexAtomicCounterBuffers 0\n"
928 "MaxTessControlAtomicCounterBuffers 0\n"
929 "MaxTessEvaluationAtomicCounterBuffers 0\n"
930 "MaxGeometryAtomicCounterBuffers 0\n"
931 "MaxFragmentAtomicCounterBuffers 1\n"
932 "MaxCombinedAtomicCounterBuffers 1\n"
933 "MaxAtomicCounterBufferSize 16384\n"
934 "MaxTransformFeedbackBuffers 4\n"
935 "MaxTransformFeedbackInterleavedComponents 64\n"
936 "MaxCullDistances 8\n"
937 "MaxCombinedClipAndCullDistances 8\n"
938 "MaxSamples 4\n"
939
940 "nonInductiveForLoops 1\n"
941 "whileLoops 1\n"
942 "doWhileLoops 1\n"
943 "generalUniformIndexing 1\n"
944 "generalAttributeMatrixVectorIndexing 1\n"
945 "generalVaryingIndexing 1\n"
946 "generalSamplerIndexing 1\n"
947 "generalVariableIndexing 1\n"
948 "generalConstantMatrixVectorIndexing 1\n"
949 ;
950
951//
952// *.conf => this is a config file that can set limits/resources
953//
Tony Barbour6918cd52015-04-09 12:58:51 -0600954bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600955{
956 if (name.size() < 5)
957 return false;
958
959 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
960 ConfigFile = name;
961 return true;
962 }
963
964 return false;
965}
966
967//
968// Parse either a .conf file provided by the user or the default string above.
969//
Tony Barbour6918cd52015-04-09 12:58:51 -0600970void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600971{
972 char** configStrings = 0;
973 char* config = 0;
974 if (ConfigFile.size() > 0) {
975 configStrings = ReadFileData(ConfigFile.c_str());
976 if (configStrings)
977 config = *configStrings;
978 else {
979 printf("Error opening configuration file; will instead use the default configuration\n");
980 }
981 }
982
983 if (config == 0) {
984 config = new char[strlen(DefaultConfig) + 1];
985 strcpy(config, DefaultConfig);
986 }
987
988 const char* delims = " \t\n\r";
989 const char* token = strtok(config, delims);
990 while (token) {
991 const char* valueStr = strtok(0, delims);
992 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
993 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
994 return;
995 }
996 int value = atoi(valueStr);
997
998 if (strcmp(token, "MaxLights") == 0)
999 Resources.maxLights = value;
1000 else if (strcmp(token, "MaxClipPlanes") == 0)
1001 Resources.maxClipPlanes = value;
1002 else if (strcmp(token, "MaxTextureUnits") == 0)
1003 Resources.maxTextureUnits = value;
1004 else if (strcmp(token, "MaxTextureCoords") == 0)
1005 Resources.maxTextureCoords = value;
1006 else if (strcmp(token, "MaxVertexAttribs") == 0)
1007 Resources.maxVertexAttribs = value;
1008 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
1009 Resources.maxVertexUniformComponents = value;
1010 else if (strcmp(token, "MaxVaryingFloats") == 0)
1011 Resources.maxVaryingFloats = value;
1012 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
1013 Resources.maxVertexTextureImageUnits = value;
1014 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
1015 Resources.maxCombinedTextureImageUnits = value;
1016 else if (strcmp(token, "MaxTextureImageUnits") == 0)
1017 Resources.maxTextureImageUnits = value;
1018 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
1019 Resources.maxFragmentUniformComponents = value;
1020 else if (strcmp(token, "MaxDrawBuffers") == 0)
1021 Resources.maxDrawBuffers = value;
1022 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
1023 Resources.maxVertexUniformVectors = value;
1024 else if (strcmp(token, "MaxVaryingVectors") == 0)
1025 Resources.maxVaryingVectors = value;
1026 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
1027 Resources.maxFragmentUniformVectors = value;
1028 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
1029 Resources.maxVertexOutputVectors = value;
1030 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
1031 Resources.maxFragmentInputVectors = value;
1032 else if (strcmp(token, "MinProgramTexelOffset") == 0)
1033 Resources.minProgramTexelOffset = value;
1034 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
1035 Resources.maxProgramTexelOffset = value;
1036 else if (strcmp(token, "MaxClipDistances") == 0)
1037 Resources.maxClipDistances = value;
1038 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
1039 Resources.maxComputeWorkGroupCountX = value;
1040 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
1041 Resources.maxComputeWorkGroupCountY = value;
1042 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
1043 Resources.maxComputeWorkGroupCountZ = value;
1044 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
1045 Resources.maxComputeWorkGroupSizeX = value;
1046 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
1047 Resources.maxComputeWorkGroupSizeY = value;
1048 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
1049 Resources.maxComputeWorkGroupSizeZ = value;
1050 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
1051 Resources.maxComputeUniformComponents = value;
1052 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
1053 Resources.maxComputeTextureImageUnits = value;
1054 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
1055 Resources.maxComputeImageUniforms = value;
1056 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
1057 Resources.maxComputeAtomicCounters = value;
1058 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
1059 Resources.maxComputeAtomicCounterBuffers = value;
1060 else if (strcmp(token, "MaxVaryingComponents") == 0)
1061 Resources.maxVaryingComponents = value;
1062 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
1063 Resources.maxVertexOutputComponents = value;
1064 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
1065 Resources.maxGeometryInputComponents = value;
1066 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
1067 Resources.maxGeometryOutputComponents = value;
1068 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
1069 Resources.maxFragmentInputComponents = value;
1070 else if (strcmp(token, "MaxImageUnits") == 0)
1071 Resources.maxImageUnits = value;
1072 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
1073 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
1074 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
1075 Resources.maxCombinedShaderOutputResources = value;
1076 else if (strcmp(token, "MaxImageSamples") == 0)
1077 Resources.maxImageSamples = value;
1078 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
1079 Resources.maxVertexImageUniforms = value;
1080 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
1081 Resources.maxTessControlImageUniforms = value;
1082 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
1083 Resources.maxTessEvaluationImageUniforms = value;
1084 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
1085 Resources.maxGeometryImageUniforms = value;
1086 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
1087 Resources.maxFragmentImageUniforms = value;
1088 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
1089 Resources.maxCombinedImageUniforms = value;
1090 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
1091 Resources.maxGeometryTextureImageUnits = value;
1092 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
1093 Resources.maxGeometryOutputVertices = value;
1094 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
1095 Resources.maxGeometryTotalOutputComponents = value;
1096 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
1097 Resources.maxGeometryUniformComponents = value;
1098 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
1099 Resources.maxGeometryVaryingComponents = value;
1100 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
1101 Resources.maxTessControlInputComponents = value;
1102 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
1103 Resources.maxTessControlOutputComponents = value;
1104 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
1105 Resources.maxTessControlTextureImageUnits = value;
1106 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
1107 Resources.maxTessControlUniformComponents = value;
1108 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
1109 Resources.maxTessControlTotalOutputComponents = value;
1110 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
1111 Resources.maxTessEvaluationInputComponents = value;
1112 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
1113 Resources.maxTessEvaluationOutputComponents = value;
1114 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
1115 Resources.maxTessEvaluationTextureImageUnits = value;
1116 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
1117 Resources.maxTessEvaluationUniformComponents = value;
1118 else if (strcmp(token, "MaxTessPatchComponents") == 0)
1119 Resources.maxTessPatchComponents = value;
1120 else if (strcmp(token, "MaxPatchVertices") == 0)
1121 Resources.maxPatchVertices = value;
1122 else if (strcmp(token, "MaxTessGenLevel") == 0)
1123 Resources.maxTessGenLevel = value;
1124 else if (strcmp(token, "MaxViewports") == 0)
1125 Resources.maxViewports = value;
1126 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
1127 Resources.maxVertexAtomicCounters = value;
1128 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
1129 Resources.maxTessControlAtomicCounters = value;
1130 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
1131 Resources.maxTessEvaluationAtomicCounters = value;
1132 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
1133 Resources.maxGeometryAtomicCounters = value;
1134 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
1135 Resources.maxFragmentAtomicCounters = value;
1136 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
1137 Resources.maxCombinedAtomicCounters = value;
1138 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
1139 Resources.maxAtomicCounterBindings = value;
1140 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
1141 Resources.maxVertexAtomicCounterBuffers = value;
1142 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
1143 Resources.maxTessControlAtomicCounterBuffers = value;
1144 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
1145 Resources.maxTessEvaluationAtomicCounterBuffers = value;
1146 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
1147 Resources.maxGeometryAtomicCounterBuffers = value;
1148 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
1149 Resources.maxFragmentAtomicCounterBuffers = value;
1150 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
1151 Resources.maxCombinedAtomicCounterBuffers = value;
1152 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
1153 Resources.maxAtomicCounterBufferSize = value;
1154 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
1155 Resources.maxTransformFeedbackBuffers = value;
1156 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
1157 Resources.maxTransformFeedbackInterleavedComponents = value;
1158 else if (strcmp(token, "MaxCullDistances") == 0)
1159 Resources.maxCullDistances = value;
1160 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
1161 Resources.maxCombinedClipAndCullDistances = value;
1162 else if (strcmp(token, "MaxSamples") == 0)
1163 Resources.maxSamples = value;
1164
1165 else if (strcmp(token, "nonInductiveForLoops") == 0)
1166 Resources.limits.nonInductiveForLoops = (value != 0);
1167 else if (strcmp(token, "whileLoops") == 0)
1168 Resources.limits.whileLoops = (value != 0);
1169 else if (strcmp(token, "doWhileLoops") == 0)
1170 Resources.limits.doWhileLoops = (value != 0);
1171 else if (strcmp(token, "generalUniformIndexing") == 0)
1172 Resources.limits.generalUniformIndexing = (value != 0);
1173 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
1174 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
1175 else if (strcmp(token, "generalVaryingIndexing") == 0)
1176 Resources.limits.generalVaryingIndexing = (value != 0);
1177 else if (strcmp(token, "generalSamplerIndexing") == 0)
1178 Resources.limits.generalSamplerIndexing = (value != 0);
1179 else if (strcmp(token, "generalVariableIndexing") == 0)
1180 Resources.limits.generalVariableIndexing = (value != 0);
1181 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
1182 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
1183 else
1184 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
1185
1186 token = strtok(0, delims);
1187 }
1188 if (configStrings)
1189 FreeFileData(configStrings);
1190}
1191
Tony Barbour6918cd52015-04-09 12:58:51 -06001192void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001193{
1194 if (m_compile_options & EOptionRelaxedErrors)
1195 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
1196 if (m_compile_options & EOptionIntermediate)
1197 messages = (EShMessages)(messages | EShMsgAST);
1198 if (m_compile_options & EOptionSuppressWarnings)
1199 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
1200}
1201
1202//
1203// Malloc a string of sufficient size and read a string into it.
1204//
Tony Barbour6918cd52015-04-09 12:58:51 -06001205char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001206{
1207 FILE *in;
1208 #if defined(_WIN32) && defined(__GNUC__)
1209 in = fopen(fileName, "r");
1210 int errorCode = in ? 0 : 1;
1211 #else
1212 int errorCode = fopen_s(&in, fileName, "r");
1213 #endif
1214
1215 char *fdata;
1216 int count = 0;
1217 const int maxSourceStrings = 5;
1218 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
1219
1220 if (errorCode) {
1221 printf("Error: unable to open input file: %s\n", fileName);
1222 return 0;
1223 }
1224
1225 while (fgetc(in) != EOF)
1226 count++;
1227
1228 fseek(in, 0, SEEK_SET);
1229
1230 if (!(fdata = (char*)malloc(count+2))) {
1231 printf("Error allocating memory\n");
1232 return 0;
1233 }
1234 if (fread(fdata,1,count, in)!=count) {
1235 printf("Error reading input file: %s\n", fileName);
1236 return 0;
1237 }
1238 fdata[count] = '\0';
1239 fclose(in);
1240 if (count == 0) {
1241 return_data[0]=(char*)malloc(count+2);
1242 return_data[0][0]='\0';
1243 m_num_shader_strings = 0;
1244 return return_data;
1245 } else
1246 m_num_shader_strings = 1;
1247
1248 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
1249 int ptr_len=0,i=0;
1250 while(count>0){
1251 return_data[i]=(char*)malloc(len+2);
1252 memcpy(return_data[i],fdata+ptr_len,len);
1253 return_data[i][len]='\0';
1254 count-=(len);
1255 ptr_len+=(len);
1256 if(count<len){
1257 if(count==0){
1258 m_num_shader_strings=(i+1);
1259 break;
1260 }
1261 len = count;
1262 }
1263 ++i;
1264 }
1265 return return_data;
1266}
1267
Tony Barbour6918cd52015-04-09 12:58:51 -06001268void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001269{
1270 for(int i=0;i<m_num_shader_strings;i++)
1271 free(data[i]);
1272}
1273
1274//
1275// Deduce the language from the filename. Files must end in one of the
1276// following extensions:
1277//
1278// .vert = vertex
1279// .tesc = tessellation control
1280// .tese = tessellation evaluation
1281// .geom = geometry
1282// .frag = fragment
1283// .comp = compute
1284//
Tony Barbour6918cd52015-04-09 12:58:51 -06001285EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001286{
1287 size_t ext = name.rfind('.');
1288 if (ext == std::string::npos) {
1289 return EShLangVertex;
1290 }
1291
1292 std::string suffix = name.substr(ext + 1, std::string::npos);
1293 if (suffix == "vert")
1294 return EShLangVertex;
1295 else if (suffix == "tesc")
1296 return EShLangTessControl;
1297 else if (suffix == "tese")
1298 return EShLangTessEvaluation;
1299 else if (suffix == "geom")
1300 return EShLangGeometry;
1301 else if (suffix == "frag")
1302 return EShLangFragment;
1303 else if (suffix == "comp")
1304 return EShLangCompute;
1305
1306 return EShLangVertex;
1307}
1308
1309//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001310// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001311//
Tony Barbourd1c35722015-04-16 15:59:00 -06001312EShLanguage VkTestFramework::FindLanguage(const VkShaderStage shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001313{
1314 switch (shader_type) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001315 case VK_SHADER_STAGE_VERTEX:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001316 return EShLangVertex;
1317
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001318 case VK_SHADER_STAGE_TESS_CONTROL:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001319 return EShLangTessControl;
1320
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001321 case VK_SHADER_STAGE_TESS_EVALUATION:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001322 return EShLangTessEvaluation;
1323
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001324 case VK_SHADER_STAGE_GEOMETRY:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001325 return EShLangGeometry;
1326
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001327 case VK_SHADER_STAGE_FRAGMENT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001328 return EShLangFragment;
1329
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001330 case VK_SHADER_STAGE_COMPUTE:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001331 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001332
Chia-I Wub4c2aa42014-12-15 23:50:11 +08001333 default:
1334 return EShLangVertex;
1335 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001336}
1337
1338
1339//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001340// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001341// Return value of false means an error was encountered.
1342//
Tony Barbourd1c35722015-04-16 15:59:00 -06001343bool VkTestFramework::GLSLtoSPV(const VkShaderStage shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001344 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -06001345 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001346{
1347 glslang::TProgram& program = *new glslang::TProgram;
1348 const char *shaderStrings[1];
1349
1350 // TODO: Do we want to load a special config file depending on the
1351 // shader source? Optional name maybe?
1352 // SetConfigFile(fileName);
1353
1354 ProcessConfigFile();
1355
1356 EShMessages messages = EShMsgDefault;
1357 SetMessageOptions(messages);
1358
1359 EShLanguage stage = FindLanguage(shader_type);
1360 glslang::TShader* shader = new glslang::TShader(stage);
1361
1362 shaderStrings[0] = pshader;
1363 shader->setStrings(shaderStrings, 1);
1364
1365 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
1366
Cody Northrop195d6622014-11-03 12:54:37 -07001367 if (! (m_compile_options & EOptionSuppressInfolog)) {
1368 puts(shader->getInfoLog());
1369 puts(shader->getInfoDebugLog());
1370 }
1371
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001372 return false; // something didn't work
1373 }
1374
1375 program.addShader(shader);
1376
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001377
1378 //
1379 // Program-level processing...
1380 //
1381
Cody Northrop195d6622014-11-03 12:54:37 -07001382 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001383
Cody Northrop195d6622014-11-03 12:54:37 -07001384 if (! (m_compile_options & EOptionSuppressInfolog)) {
1385 puts(shader->getInfoLog());
1386 puts(shader->getInfoDebugLog());
1387 }
1388
1389 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001390 }
1391
1392 if (m_compile_options & EOptionDumpReflection) {
1393 program.buildReflection();
1394 program.dumpReflection();
1395 }
1396
Cody Northrop5a95b472015-06-03 13:01:54 -06001397 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
1398
1399 //
1400 // Test the different modes of SPIR-V modification
1401 //
1402 if (this->m_canonicalize_spv) {
1403 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
1404 }
1405
1406 if (this->m_strip_spv) {
1407 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
1408 }
1409
1410 if (this->m_do_everything_spv) {
1411 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
1412 }
1413
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -06001414
1415 return true;
1416}
1417
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001418
1419
Tony Barbour6918cd52015-04-09 12:58:51 -06001420VkTestImageRecord::VkTestImageRecord() : // Constructor
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001421 m_width( 0 ),
1422 m_height( 0 ),
Chia-I Wu837f9952014-12-15 23:29:34 +08001423 m_data( NULL ),
1424 m_data_size( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001425{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001426}
1427
Tony Barbour6918cd52015-04-09 12:58:51 -06001428VkTestImageRecord::~VkTestImageRecord()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001429{
1430
1431}
1432
Tony Barbour6918cd52015-04-09 12:58:51 -06001433VkTestImageRecord::VkTestImageRecord(const VkTestImageRecord &copyin) // Copy constructor to handle pass by value.
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001434{
1435 m_title = copyin.m_title;
1436 m_width = copyin.m_width;
1437 m_height = copyin.m_height;
1438 m_data_size = copyin.m_data_size;
1439 m_data = copyin.m_data; // TODO: Do we need to copy the data or is pointer okay?
1440}
1441
Tony Barbour6918cd52015-04-09 12:58:51 -06001442ostream &operator<<(ostream &output, const VkTestImageRecord &VkTestImageRecord)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001443{
Tony Barbour6918cd52015-04-09 12:58:51 -06001444 output << VkTestImageRecord.m_title << " (" << VkTestImageRecord.m_width <<
1445 "," << VkTestImageRecord.m_height << ")" << endl;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001446 return output;
1447}
1448
Tony Barbour6918cd52015-04-09 12:58:51 -06001449VkTestImageRecord& VkTestImageRecord::operator=(const VkTestImageRecord &rhs)
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001450{
1451 m_title = rhs.m_title;
1452 m_width = rhs.m_width;
1453 m_height = rhs.m_height;
1454 m_data_size = rhs.m_data_size;
1455 m_data = rhs.m_data;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001456 return *this;
1457}
1458
Tony Barbour6918cd52015-04-09 12:58:51 -06001459int VkTestImageRecord::operator==(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001460{
1461 if( this->m_data != rhs.m_data) return 0;
1462 return 1;
1463}
1464
1465// This function is required for built-in STL list functions like sort
Tony Barbour6918cd52015-04-09 12:58:51 -06001466int VkTestImageRecord::operator<(const VkTestImageRecord &rhs) const
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001467{
1468 if( this->m_data_size < rhs.m_data_size ) return 1;
1469 return 0;
1470}
1471