blob: 44abe652cae665a3e972a735c2ce8a893a8bd581 [file] [log] [blame]
Karl Schultz6addd812016-02-02 17:17:23 -07001/*
2 * Copyright (c) 2015-2016 The Khronos Group Inc.
3 * Copyright (c) 2015-2016 Valve Corporation
4 * Copyright (c) 2015-2016 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and/or associated documentation files (the "Materials"), to
8 * deal in the Materials without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Materials, and to permit persons to whom the Materials are
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice(s) and this permission notice shall be included in
14 * all copies or substantial portions of the Materials.
15 *
16 * The Materials are Confidential Information as defined by the Khronos
17 * Membership Agreement until designated non-confidential by Khronos, at which
18 * point this condition clause shall be removed.
19 *
20 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 *
24 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
25 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
26 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
27 * USE OR OTHER DEALINGS IN THE MATERIALS.
28 *
29 * Author: Chia-I Wu <olvaffe@gmail.com>
30 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
31 * Author: Tony Barbour <tony@LunarG.com>
32 */
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -060033
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060034#include "vktestframework.h"
35#include "vkrenderframework.h"
Karl Schultz6addd812016-02-02 17:17:23 -070036// TODO FIXME remove this once glslang doesn't define this
Jon Ashburn94207e92015-12-04 17:03:59 -070037#undef BadValue
Cody Northrop5a95b472015-06-03 13:01:54 -060038#include "SPIRV/GlslangToSpv.h"
39#include "SPIRV/SPVRemapper.h"
Tony Barbour4ab45422014-12-10 17:00:20 -070040#include <limits.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060041#include <math.h>
Jon Ashburn94207e92015-12-04 17:03:59 -070042
Tony Barbour3d69c9e2015-05-20 16:53:31 -060043#if defined(PATH_MAX) && !defined(MAX_PATH)
44#define MAX_PATH PATH_MAX
45#endif
46
Tony Barbour6a3faf02015-07-23 10:36:18 -060047#ifdef _WIN32
Karl Schultz6addd812016-02-02 17:17:23 -070048#define ERR_EXIT(err_msg, err_class) \
49 do { \
50 MessageBox(NULL, err_msg, err_class, MB_OK); \
51 exit(1); \
52 } while (0)
53#else // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -060054
Karl Schultz6addd812016-02-02 17:17:23 -070055#define ERR_EXIT(err_msg, err_class) \
56 do { \
57 printf(err_msg); \
58 fflush(stdout); \
59 exit(1); \
60 } while (0)
Tony Barbour6a3faf02015-07-23 10:36:18 -060061#endif // _WIN32
62
Karl Schultz6addd812016-02-02 17:17:23 -070063#define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \
64 { \
65 m_fp##entrypoint = \
66 (PFN_vk##entrypoint)vkGetInstanceProcAddr(inst, "vk" #entrypoint); \
67 if (m_fp##entrypoint == NULL) { \
68 ERR_EXIT("vkGetInstanceProcAddr failed to find vk" #entrypoint, \
69 "vkGetInstanceProcAddr Failure"); \
70 } \
71 }
Tony Barbour6a3faf02015-07-23 10:36:18 -060072
Karl Schultz6addd812016-02-02 17:17:23 -070073#define GET_DEVICE_PROC_ADDR(dev, entrypoint) \
74 { \
75 m_fp##entrypoint = \
76 (PFN_vk##entrypoint)vkGetDeviceProcAddr(dev, "vk" #entrypoint); \
77 if (m_fp##entrypoint == NULL) { \
78 ERR_EXIT("vkGetDeviceProcAddr failed to find vk" #entrypoint, \
79 "vkGetDeviceProcAddr Failure"); \
80 } \
81 }
Tony Barbour6a3faf02015-07-23 10:36:18 -060082
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060083// Command-line options
84enum TOptions {
Karl Schultz6addd812016-02-02 17:17:23 -070085 EOptionNone = 0x000,
86 EOptionIntermediate = 0x001,
87 EOptionSuppressInfolog = 0x002,
88 EOptionMemoryLeakMode = 0x004,
89 EOptionRelaxedErrors = 0x008,
90 EOptionGiveWarnings = 0x010,
91 EOptionLinkProgram = 0x020,
92 EOptionMultiThreaded = 0x040,
93 EOptionDumpConfig = 0x080,
94 EOptionDumpReflection = 0x100,
95 EOptionSuppressWarnings = 0x200,
96 EOptionDumpVersions = 0x400,
97 EOptionSpv = 0x800,
98 EOptionDefaultDesktop = 0x1000,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060099};
100
Ian Elliott7e40db92015-08-21 15:09:33 -0600101typedef struct _SwapchainBuffers {
Tony Barbour6a3faf02015-07-23 10:36:18 -0600102 VkImage image;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800103 VkCommandBuffer cmd;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600104 VkImageView view;
Ian Elliott7e40db92015-08-21 15:09:33 -0600105} SwapchainBuffers;
Tony Barbour6a3faf02015-07-23 10:36:18 -0600106
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600107#ifndef _WIN32
108
109#include <errno.h>
110
Karl Schultz6addd812016-02-02 17:17:23 -0700111int fopen_s(FILE **pFile, const char *filename, const char *mode) {
112 if (!pFile || !filename || !mode) {
113 return EINVAL;
114 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600115
Karl Schultz6addd812016-02-02 17:17:23 -0700116 FILE *f = fopen(filename, mode);
117 if (!f) {
118 if (errno != 0) {
119 return errno;
120 } else {
121 return ENOENT;
122 }
123 }
124 *pFile = f;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600125
Karl Schultz6addd812016-02-02 17:17:23 -0700126 return 0;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600127}
128
129#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600130
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600131// Set up environment for GLSL compiler
132// Must be done once per process
Karl Schultz6addd812016-02-02 17:17:23 -0700133void TestEnvironment::SetUp() {
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600134 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600135 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800136
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600137 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600138}
139
Karl Schultz6addd812016-02-02 17:17:23 -0700140void TestEnvironment::TearDown() { glslang::FinalizeProcess(); }
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600141
Karl Schultz6addd812016-02-02 17:17:23 -0700142VkTestFramework::VkTestFramework()
143 : m_compile_options(0), m_num_shader_strings(0) {}
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600144
Karl Schultz6addd812016-02-02 17:17:23 -0700145VkTestFramework::~VkTestFramework() {}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600146
147// Define all the static elements
Karl Schultz6addd812016-02-02 17:17:23 -0700148bool VkTestFramework::m_use_glsl = false;
149bool VkTestFramework::m_canonicalize_spv = false;
150bool VkTestFramework::m_strip_spv = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600151bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour6918cd52015-04-09 12:58:51 -0600152int VkTestFramework::m_width = 0;
153int VkTestFramework::m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600154
Karl Schultz6addd812016-02-02 17:17:23 -0700155bool VkTestFramework::optionMatch(const char *option, char *optionLine) {
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600156 if (strncmp(option, optionLine, strlen(option)) == 0)
157 return true;
158 else
159 return false;
160}
161
Karl Schultz6addd812016-02-02 17:17:23 -0700162void VkTestFramework::InitArgs(int *argc, char *argv[]) {
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600163 int i, n;
164
Karl Schultz6addd812016-02-02 17:17:23 -0700165 for (i = 1, n = 1; i < *argc; i++) {
Tony Barbour7b60e492016-02-02 14:43:55 -0700166 if (optionMatch("--no-SPV", argv[i]))
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600167 m_use_glsl = true;
168 else if (optionMatch("--strip-SPV", argv[i]))
Tony Barbour7b60e492016-02-02 14:43:55 -0700169 m_strip_spv = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600170 else if (optionMatch("--canonicalize-SPV", argv[i]))
171 m_canonicalize_spv = true;
Karl Schultz6addd812016-02-02 17:17:23 -0700172 else if (optionMatch("--help", argv[i]) || optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700173 printf("\nOther options:\n");
174 printf("\t--show-images\n"
175 "\t\tDisplay test images in viewer after tests complete.\n");
176 printf("\t--save-images\n"
Karl Schultz6addd812016-02-02 17:17:23 -0700177 "\t\tSave tests images as ppm files in current working "
178 "directory.\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700179 "\t\tUsed to generate golden images for compare-images.\n");
Karl Schultz6addd812016-02-02 17:17:23 -0700180 printf(
181 "\t--compare-images\n"
182 "\t\tCompare test images to 'golden' image in golden folder.\n"
183 "\t\tAlso saves the generated test image in current working\n"
184 "\t\t\tdirectory but only if the image is different from the "
185 "golden\n"
186 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can "
187 "specify\n"
188 "\t\t\tdifferent directory for golden images\n"
189 "\t\tSignal test failure if different.\n");
190 printf(
191 "\t--no-SPV\n"
192 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600193 printf("\t--strip-SPV\n"
Karl Schultz6addd812016-02-02 17:17:23 -0700194 "\t\tStrip SPIR-V debug information (line numbers, names, "
195 "etc).\n");
196 printf(
197 "\t--canonicalize-SPV\n"
198 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600199 exit(0);
200 } else {
201 printf("\nUnrecognized option: %s\n", argv[i]);
202 printf("\nUse --help or -h for option list.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700203 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700204 }
205
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600206 /*
207 * Since the above "consume" inputs, update argv
208 * so that it contains the trimmed list of args for glutInit
209 */
210
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600211 argv[n] = argv[i];
212 n++;
213 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600214}
215
Karl Schultz6addd812016-02-02 17:17:23 -0700216VkFormat VkTestFramework::GetFormat(VkInstance instance,
217 vk_testing::Device *device) {
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700218 VkFormatProperties format_props;
Tony Barbour7b60e492016-02-02 14:43:55 -0700219
Karl Schultz6addd812016-02-02 17:17:23 -0700220 vkGetPhysicalDeviceFormatProperties(
221 device->phy().handle(), VK_FORMAT_B8G8R8A8_UNORM, &format_props);
222 if (format_props.linearTilingFeatures &
223 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ||
224 format_props.optimalTilingFeatures &
225 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) {
Tony Barbour7b60e492016-02-02 14:43:55 -0700226 return VK_FORMAT_B8G8R8A8_UNORM;
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700227 }
Karl Schultz6addd812016-02-02 17:17:23 -0700228 vkGetPhysicalDeviceFormatProperties(
229 device->phy().handle(), VK_FORMAT_R8G8B8A8_UNORM, &format_props);
230 if (format_props.linearTilingFeatures &
231 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ||
232 format_props.optimalTilingFeatures &
233 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) {
Tony Barbour7b60e492016-02-02 14:43:55 -0700234 return VK_FORMAT_R8G8B8A8_UNORM;
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700235 }
Karl Schultz6addd812016-02-02 17:17:23 -0700236 printf("Error - device does not support VK_FORMAT_B8G8R8A8_UNORM nor "
237 "VK_FORMAT_R8G8B8A8_UNORM - exiting\n");
Tony Barbour7b60e492016-02-02 14:43:55 -0700238 exit(0);
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700239}
240
Karl Schultz6addd812016-02-02 17:17:23 -0700241void VkTestFramework::Finish() {}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600242
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600243//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600244// These are the default resources for TBuiltInResources, used for both
245// - parsing this string for the case where the user didn't supply one
246// - dumping out a template for user construction of a config file
247//
Karl Schultz6addd812016-02-02 17:17:23 -0700248static const char *DefaultConfig =
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600249 "MaxLights 32\n"
250 "MaxClipPlanes 6\n"
251 "MaxTextureUnits 32\n"
252 "MaxTextureCoords 32\n"
253 "MaxVertexAttribs 64\n"
254 "MaxVertexUniformComponents 4096\n"
255 "MaxVaryingFloats 64\n"
256 "MaxVertexTextureImageUnits 32\n"
257 "MaxCombinedTextureImageUnits 80\n"
258 "MaxTextureImageUnits 32\n"
259 "MaxFragmentUniformComponents 4096\n"
260 "MaxDrawBuffers 32\n"
261 "MaxVertexUniformVectors 128\n"
262 "MaxVaryingVectors 8\n"
263 "MaxFragmentUniformVectors 16\n"
264 "MaxVertexOutputVectors 16\n"
265 "MaxFragmentInputVectors 15\n"
266 "MinProgramTexelOffset -8\n"
267 "MaxProgramTexelOffset 7\n"
268 "MaxClipDistances 8\n"
269 "MaxComputeWorkGroupCountX 65535\n"
270 "MaxComputeWorkGroupCountY 65535\n"
271 "MaxComputeWorkGroupCountZ 65535\n"
272 "MaxComputeWorkGroupSizeX 1024\n"
273 "MaxComputeWorkGroupSizeY 1024\n"
274 "MaxComputeWorkGroupSizeZ 64\n"
275 "MaxComputeUniformComponents 1024\n"
276 "MaxComputeTextureImageUnits 16\n"
277 "MaxComputeImageUniforms 8\n"
278 "MaxComputeAtomicCounters 8\n"
279 "MaxComputeAtomicCounterBuffers 1\n"
280 "MaxVaryingComponents 60\n"
281 "MaxVertexOutputComponents 64\n"
282 "MaxGeometryInputComponents 64\n"
283 "MaxGeometryOutputComponents 128\n"
284 "MaxFragmentInputComponents 128\n"
285 "MaxImageUnits 8\n"
286 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
287 "MaxCombinedShaderOutputResources 8\n"
288 "MaxImageSamples 0\n"
289 "MaxVertexImageUniforms 0\n"
290 "MaxTessControlImageUniforms 0\n"
291 "MaxTessEvaluationImageUniforms 0\n"
292 "MaxGeometryImageUniforms 0\n"
293 "MaxFragmentImageUniforms 8\n"
294 "MaxCombinedImageUniforms 8\n"
295 "MaxGeometryTextureImageUnits 16\n"
296 "MaxGeometryOutputVertices 256\n"
297 "MaxGeometryTotalOutputComponents 1024\n"
298 "MaxGeometryUniformComponents 1024\n"
299 "MaxGeometryVaryingComponents 64\n"
300 "MaxTessControlInputComponents 128\n"
301 "MaxTessControlOutputComponents 128\n"
302 "MaxTessControlTextureImageUnits 16\n"
303 "MaxTessControlUniformComponents 1024\n"
304 "MaxTessControlTotalOutputComponents 4096\n"
305 "MaxTessEvaluationInputComponents 128\n"
306 "MaxTessEvaluationOutputComponents 128\n"
307 "MaxTessEvaluationTextureImageUnits 16\n"
308 "MaxTessEvaluationUniformComponents 1024\n"
309 "MaxTessPatchComponents 120\n"
310 "MaxPatchVertices 32\n"
311 "MaxTessGenLevel 64\n"
312 "MaxViewports 16\n"
313 "MaxVertexAtomicCounters 0\n"
314 "MaxTessControlAtomicCounters 0\n"
315 "MaxTessEvaluationAtomicCounters 0\n"
316 "MaxGeometryAtomicCounters 0\n"
317 "MaxFragmentAtomicCounters 8\n"
318 "MaxCombinedAtomicCounters 8\n"
319 "MaxAtomicCounterBindings 1\n"
320 "MaxVertexAtomicCounterBuffers 0\n"
321 "MaxTessControlAtomicCounterBuffers 0\n"
322 "MaxTessEvaluationAtomicCounterBuffers 0\n"
323 "MaxGeometryAtomicCounterBuffers 0\n"
324 "MaxFragmentAtomicCounterBuffers 1\n"
325 "MaxCombinedAtomicCounterBuffers 1\n"
326 "MaxAtomicCounterBufferSize 16384\n"
327 "MaxTransformFeedbackBuffers 4\n"
328 "MaxTransformFeedbackInterleavedComponents 64\n"
329 "MaxCullDistances 8\n"
330 "MaxCombinedClipAndCullDistances 8\n"
331 "MaxSamples 4\n"
332
333 "nonInductiveForLoops 1\n"
334 "whileLoops 1\n"
335 "doWhileLoops 1\n"
336 "generalUniformIndexing 1\n"
337 "generalAttributeMatrixVectorIndexing 1\n"
338 "generalVaryingIndexing 1\n"
339 "generalSamplerIndexing 1\n"
340 "generalVariableIndexing 1\n"
Karl Schultz6addd812016-02-02 17:17:23 -0700341 "generalConstantMatrixVectorIndexing 1\n";
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600342
343//
344// *.conf => this is a config file that can set limits/resources
345//
Karl Schultz6addd812016-02-02 17:17:23 -0700346bool VkTestFramework::SetConfigFile(const std::string &name) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600347 if (name.size() < 5)
348 return false;
349
350 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
351 ConfigFile = name;
352 return true;
353 }
354
355 return false;
356}
357
358//
359// Parse either a .conf file provided by the user or the default string above.
360//
Karl Schultz6addd812016-02-02 17:17:23 -0700361void VkTestFramework::ProcessConfigFile() {
362 char **configStrings = 0;
363 char *config = 0;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600364 if (ConfigFile.size() > 0) {
365 configStrings = ReadFileData(ConfigFile.c_str());
366 if (configStrings)
367 config = *configStrings;
368 else {
Karl Schultz6addd812016-02-02 17:17:23 -0700369 printf("Error opening configuration file; will instead use the "
370 "default configuration\n");
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600371 }
372 }
373
374 if (config == 0) {
Karl Schultz6addd812016-02-02 17:17:23 -0700375 config = (char *)alloca(strlen(DefaultConfig) + 1);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600376 strcpy(config, DefaultConfig);
377 }
378
Karl Schultz6addd812016-02-02 17:17:23 -0700379 const char *delims = " \t\n\r";
380 const char *token = strtok(config, delims);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600381 while (token) {
Karl Schultz6addd812016-02-02 17:17:23 -0700382 const char *valueStr = strtok(0, delims);
383 if (valueStr == 0 ||
384 !(valueStr[0] == '-' ||
385 (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
386 printf("Error: '%s' bad .conf file. Each name must be followed by "
387 "one number.\n",
388 valueStr ? valueStr : "");
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600389 return;
390 }
391 int value = atoi(valueStr);
392
393 if (strcmp(token, "MaxLights") == 0)
394 Resources.maxLights = value;
395 else if (strcmp(token, "MaxClipPlanes") == 0)
396 Resources.maxClipPlanes = value;
397 else if (strcmp(token, "MaxTextureUnits") == 0)
398 Resources.maxTextureUnits = value;
399 else if (strcmp(token, "MaxTextureCoords") == 0)
400 Resources.maxTextureCoords = value;
401 else if (strcmp(token, "MaxVertexAttribs") == 0)
402 Resources.maxVertexAttribs = value;
403 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
404 Resources.maxVertexUniformComponents = value;
405 else if (strcmp(token, "MaxVaryingFloats") == 0)
406 Resources.maxVaryingFloats = value;
407 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
408 Resources.maxVertexTextureImageUnits = value;
409 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
410 Resources.maxCombinedTextureImageUnits = value;
411 else if (strcmp(token, "MaxTextureImageUnits") == 0)
412 Resources.maxTextureImageUnits = value;
413 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
414 Resources.maxFragmentUniformComponents = value;
415 else if (strcmp(token, "MaxDrawBuffers") == 0)
416 Resources.maxDrawBuffers = value;
417 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
418 Resources.maxVertexUniformVectors = value;
419 else if (strcmp(token, "MaxVaryingVectors") == 0)
420 Resources.maxVaryingVectors = value;
421 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
422 Resources.maxFragmentUniformVectors = value;
423 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
424 Resources.maxVertexOutputVectors = value;
425 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
426 Resources.maxFragmentInputVectors = value;
427 else if (strcmp(token, "MinProgramTexelOffset") == 0)
428 Resources.minProgramTexelOffset = value;
429 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
430 Resources.maxProgramTexelOffset = value;
431 else if (strcmp(token, "MaxClipDistances") == 0)
432 Resources.maxClipDistances = value;
433 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
434 Resources.maxComputeWorkGroupCountX = value;
435 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
436 Resources.maxComputeWorkGroupCountY = value;
437 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
438 Resources.maxComputeWorkGroupCountZ = value;
439 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
440 Resources.maxComputeWorkGroupSizeX = value;
441 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
442 Resources.maxComputeWorkGroupSizeY = value;
443 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
444 Resources.maxComputeWorkGroupSizeZ = value;
445 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
446 Resources.maxComputeUniformComponents = value;
447 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
448 Resources.maxComputeTextureImageUnits = value;
449 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
450 Resources.maxComputeImageUniforms = value;
451 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
452 Resources.maxComputeAtomicCounters = value;
453 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
454 Resources.maxComputeAtomicCounterBuffers = value;
455 else if (strcmp(token, "MaxVaryingComponents") == 0)
456 Resources.maxVaryingComponents = value;
457 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
458 Resources.maxVertexOutputComponents = value;
459 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
460 Resources.maxGeometryInputComponents = value;
461 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
462 Resources.maxGeometryOutputComponents = value;
463 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
464 Resources.maxFragmentInputComponents = value;
465 else if (strcmp(token, "MaxImageUnits") == 0)
466 Resources.maxImageUnits = value;
467 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
468 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
469 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
470 Resources.maxCombinedShaderOutputResources = value;
471 else if (strcmp(token, "MaxImageSamples") == 0)
472 Resources.maxImageSamples = value;
473 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
474 Resources.maxVertexImageUniforms = value;
475 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
476 Resources.maxTessControlImageUniforms = value;
477 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
478 Resources.maxTessEvaluationImageUniforms = value;
479 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
480 Resources.maxGeometryImageUniforms = value;
481 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
482 Resources.maxFragmentImageUniforms = value;
483 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
484 Resources.maxCombinedImageUniforms = value;
485 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
486 Resources.maxGeometryTextureImageUnits = value;
487 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
488 Resources.maxGeometryOutputVertices = value;
489 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
490 Resources.maxGeometryTotalOutputComponents = value;
491 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
492 Resources.maxGeometryUniformComponents = value;
493 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
494 Resources.maxGeometryVaryingComponents = value;
495 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
496 Resources.maxTessControlInputComponents = value;
497 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
498 Resources.maxTessControlOutputComponents = value;
499 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
500 Resources.maxTessControlTextureImageUnits = value;
501 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
502 Resources.maxTessControlUniformComponents = value;
503 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
504 Resources.maxTessControlTotalOutputComponents = value;
505 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
506 Resources.maxTessEvaluationInputComponents = value;
507 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
508 Resources.maxTessEvaluationOutputComponents = value;
509 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
510 Resources.maxTessEvaluationTextureImageUnits = value;
511 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
512 Resources.maxTessEvaluationUniformComponents = value;
513 else if (strcmp(token, "MaxTessPatchComponents") == 0)
514 Resources.maxTessPatchComponents = value;
515 else if (strcmp(token, "MaxPatchVertices") == 0)
516 Resources.maxPatchVertices = value;
517 else if (strcmp(token, "MaxTessGenLevel") == 0)
518 Resources.maxTessGenLevel = value;
519 else if (strcmp(token, "MaxViewports") == 0)
520 Resources.maxViewports = value;
521 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
522 Resources.maxVertexAtomicCounters = value;
523 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
524 Resources.maxTessControlAtomicCounters = value;
525 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
526 Resources.maxTessEvaluationAtomicCounters = value;
527 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
528 Resources.maxGeometryAtomicCounters = value;
529 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
530 Resources.maxFragmentAtomicCounters = value;
531 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
532 Resources.maxCombinedAtomicCounters = value;
533 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
534 Resources.maxAtomicCounterBindings = value;
535 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
536 Resources.maxVertexAtomicCounterBuffers = value;
537 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
538 Resources.maxTessControlAtomicCounterBuffers = value;
539 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
540 Resources.maxTessEvaluationAtomicCounterBuffers = value;
541 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
542 Resources.maxGeometryAtomicCounterBuffers = value;
543 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
544 Resources.maxFragmentAtomicCounterBuffers = value;
545 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
546 Resources.maxCombinedAtomicCounterBuffers = value;
547 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
548 Resources.maxAtomicCounterBufferSize = value;
549 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
550 Resources.maxTransformFeedbackBuffers = value;
Karl Schultz6addd812016-02-02 17:17:23 -0700551 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") ==
552 0)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600553 Resources.maxTransformFeedbackInterleavedComponents = value;
554 else if (strcmp(token, "MaxCullDistances") == 0)
555 Resources.maxCullDistances = value;
556 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
557 Resources.maxCombinedClipAndCullDistances = value;
558 else if (strcmp(token, "MaxSamples") == 0)
559 Resources.maxSamples = value;
560
561 else if (strcmp(token, "nonInductiveForLoops") == 0)
562 Resources.limits.nonInductiveForLoops = (value != 0);
563 else if (strcmp(token, "whileLoops") == 0)
564 Resources.limits.whileLoops = (value != 0);
565 else if (strcmp(token, "doWhileLoops") == 0)
566 Resources.limits.doWhileLoops = (value != 0);
567 else if (strcmp(token, "generalUniformIndexing") == 0)
568 Resources.limits.generalUniformIndexing = (value != 0);
569 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
Karl Schultz6addd812016-02-02 17:17:23 -0700570 Resources.limits.generalAttributeMatrixVectorIndexing =
571 (value != 0);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600572 else if (strcmp(token, "generalVaryingIndexing") == 0)
573 Resources.limits.generalVaryingIndexing = (value != 0);
574 else if (strcmp(token, "generalSamplerIndexing") == 0)
575 Resources.limits.generalSamplerIndexing = (value != 0);
576 else if (strcmp(token, "generalVariableIndexing") == 0)
577 Resources.limits.generalVariableIndexing = (value != 0);
578 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
579 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
580 else
Karl Schultz6addd812016-02-02 17:17:23 -0700581 printf("Warning: unrecognized limit (%s) in configuration file.\n",
582 token);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600583
584 token = strtok(0, delims);
585 }
586 if (configStrings)
587 FreeFileData(configStrings);
588}
589
Karl Schultz6addd812016-02-02 17:17:23 -0700590void VkTestFramework::SetMessageOptions(EShMessages &messages) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600591 if (m_compile_options & EOptionRelaxedErrors)
592 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
593 if (m_compile_options & EOptionIntermediate)
594 messages = (EShMessages)(messages | EShMsgAST);
595 if (m_compile_options & EOptionSuppressWarnings)
596 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
597}
598
599//
600// Malloc a string of sufficient size and read a string into it.
601//
Karl Schultz6addd812016-02-02 17:17:23 -0700602char **VkTestFramework::ReadFileData(const char *fileName) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600603 FILE *in;
Karl Schultz6addd812016-02-02 17:17:23 -0700604#if defined(_WIN32) && defined(__GNUC__)
605 in = fopen(fileName, "r");
606 int errorCode = in ? 0 : 1;
607#else
608 int errorCode = fopen_s(&in, fileName, "r");
609#endif
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600610
611 char *fdata;
612 int count = 0;
613 const int maxSourceStrings = 5;
Karl Schultz6addd812016-02-02 17:17:23 -0700614 char **return_data =
615 (char **)malloc(sizeof(char *) * (maxSourceStrings + 1));
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600616
617 if (errorCode) {
618 printf("Error: unable to open input file: %s\n", fileName);
619 return 0;
620 }
621
622 while (fgetc(in) != EOF)
623 count++;
624
625 fseek(in, 0, SEEK_SET);
626
Karl Schultz6addd812016-02-02 17:17:23 -0700627 if (!(fdata = (char *)malloc(count + 2))) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600628 printf("Error allocating memory\n");
629 return 0;
630 }
Karl Schultz6addd812016-02-02 17:17:23 -0700631 if (fread(fdata, 1, count, in) != count) {
632 printf("Error reading input file: %s\n", fileName);
633 return 0;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600634 }
635 fdata[count] = '\0';
636 fclose(in);
637 if (count == 0) {
Karl Schultz6addd812016-02-02 17:17:23 -0700638 return_data[0] = (char *)malloc(count + 2);
639 return_data[0][0] = '\0';
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600640 m_num_shader_strings = 0;
641 return return_data;
642 } else
643 m_num_shader_strings = 1;
644
Karl Schultz6addd812016-02-02 17:17:23 -0700645 int len = (int)(ceil)((float)count / (float)m_num_shader_strings);
646 int ptr_len = 0, i = 0;
647 while (count > 0) {
648 return_data[i] = (char *)malloc(len + 2);
649 memcpy(return_data[i], fdata + ptr_len, len);
650 return_data[i][len] = '\0';
651 count -= (len);
652 ptr_len += (len);
653 if (count < len) {
654 if (count == 0) {
655 m_num_shader_strings = (i + 1);
656 break;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600657 }
Karl Schultz6addd812016-02-02 17:17:23 -0700658 len = count;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600659 }
660 ++i;
661 }
662 return return_data;
663}
664
Karl Schultz6addd812016-02-02 17:17:23 -0700665void VkTestFramework::FreeFileData(char **data) {
666 for (int i = 0; i < m_num_shader_strings; i++)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600667 free(data[i]);
668}
669
670//
671// Deduce the language from the filename. Files must end in one of the
672// following extensions:
673//
674// .vert = vertex
675// .tesc = tessellation control
676// .tese = tessellation evaluation
677// .geom = geometry
678// .frag = fragment
679// .comp = compute
680//
Karl Schultz6addd812016-02-02 17:17:23 -0700681EShLanguage VkTestFramework::FindLanguage(const std::string &name) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600682 size_t ext = name.rfind('.');
683 if (ext == std::string::npos) {
684 return EShLangVertex;
685 }
686
687 std::string suffix = name.substr(ext + 1, std::string::npos);
688 if (suffix == "vert")
689 return EShLangVertex;
690 else if (suffix == "tesc")
691 return EShLangTessControl;
692 else if (suffix == "tese")
693 return EShLangTessEvaluation;
694 else if (suffix == "geom")
695 return EShLangGeometry;
696 else if (suffix == "frag")
697 return EShLangFragment;
698 else if (suffix == "comp")
699 return EShLangCompute;
700
701 return EShLangVertex;
702}
703
704//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600705// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600706//
Karl Schultz6addd812016-02-02 17:17:23 -0700707EShLanguage
708VkTestFramework::FindLanguage(const VkShaderStageFlagBits shader_type) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600709 switch (shader_type) {
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600710 case VK_SHADER_STAGE_VERTEX_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600711 return EShLangVertex;
712
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600713 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600714 return EShLangTessControl;
715
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600716 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600717 return EShLangTessEvaluation;
718
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600719 case VK_SHADER_STAGE_GEOMETRY_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600720 return EShLangGeometry;
721
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600722 case VK_SHADER_STAGE_FRAGMENT_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600723 return EShLangFragment;
724
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600725 case VK_SHADER_STAGE_COMPUTE_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600726 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600727
Chia-I Wub4c2aa42014-12-15 23:50:11 +0800728 default:
729 return EShLangVertex;
730 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600731}
732
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600733//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600734// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600735// Return value of false means an error was encountered.
736//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600737bool VkTestFramework::GLSLtoSPV(const VkShaderStageFlagBits shader_type,
Karl Schultz6addd812016-02-02 17:17:23 -0700738 const char *pshader,
739 std::vector<unsigned int> &spirv) {
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -0600740 glslang::TProgram program;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600741 const char *shaderStrings[1];
742
743 // TODO: Do we want to load a special config file depending on the
744 // shader source? Optional name maybe?
745 // SetConfigFile(fileName);
746
747 ProcessConfigFile();
748
749 EShMessages messages = EShMsgDefault;
750 SetMessageOptions(messages);
Karl Schultz6addd812016-02-02 17:17:23 -0700751 messages =
752 static_cast<EShMessages>(messages | EShMsgSpvRules | EShMsgVulkanRules);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600753
754 EShLanguage stage = FindLanguage(shader_type);
Karl Schultz6addd812016-02-02 17:17:23 -0700755 glslang::TShader *shader = new glslang::TShader(stage);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600756
757 shaderStrings[0] = pshader;
758 shader->setStrings(shaderStrings, 1);
759
Karl Schultz6addd812016-02-02 17:17:23 -0700760 if (!shader->parse(&Resources,
761 (m_compile_options & EOptionDefaultDesktop) ? 110 : 100,
762 false, messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600763
Karl Schultz6addd812016-02-02 17:17:23 -0700764 if (!(m_compile_options & EOptionSuppressInfolog)) {
Cody Northrop195d6622014-11-03 12:54:37 -0700765 puts(shader->getInfoLog());
766 puts(shader->getInfoDebugLog());
767 }
768
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600769 return false; // something didn't work
770 }
771
772 program.addShader(shader);
773
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600774 //
775 // Program-level processing...
776 //
777
Karl Schultz6addd812016-02-02 17:17:23 -0700778 if (!program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600779
Karl Schultz6addd812016-02-02 17:17:23 -0700780 if (!(m_compile_options & EOptionSuppressInfolog)) {
Cody Northrop195d6622014-11-03 12:54:37 -0700781 puts(shader->getInfoLog());
782 puts(shader->getInfoDebugLog());
783 }
784
785 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600786 }
787
788 if (m_compile_options & EOptionDumpReflection) {
789 program.buildReflection();
790 program.dumpReflection();
791 }
792
Cody Northrop5a95b472015-06-03 13:01:54 -0600793 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
794
795 //
796 // Test the different modes of SPIR-V modification
797 //
798 if (this->m_canonicalize_spv) {
799 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
800 }
801
802 if (this->m_strip_spv) {
803 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
804 }
805
806 if (this->m_do_everything_spv) {
807 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
808 }
809
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -0600810 delete shader;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600811
812 return true;
813}