blob: 8ff75b348849c7a2cfd6fc359dcdd2b524c20b46 [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 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -06006 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
Karl Schultz6addd812016-02-02 17:17:23 -07009 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060010 * http://www.apache.org/licenses/LICENSE-2.0
Karl Schultz6addd812016-02-02 17:17:23 -070011 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060012 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
Karl Schultz6addd812016-02-02 17:17:23 -070017 *
18 * Author: Chia-I Wu <olvaffe@gmail.com>
19 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
20 * Author: Tony Barbour <tony@LunarG.com>
21 */
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -060022
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060023#include "vktestframework.h"
24#include "vkrenderframework.h"
Karl Schultz80b8aca2017-01-24 14:44:26 -080025
26// For versions prior to VS 2015, suppress the warning
27// caused by the inconsistent redefinition of snprintf
28// between a vulkan header and a glslang header.
29#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/)
30#pragma warning(push)
31#pragma warning(disable : 4005)
32#endif
Karl Schultz6addd812016-02-02 17:17:23 -070033// TODO FIXME remove this once glslang doesn't define this
Jon Ashburn94207e92015-12-04 17:03:59 -070034#undef BadValue
Cody Northrop5a95b472015-06-03 13:01:54 -060035#include "SPIRV/GlslangToSpv.h"
36#include "SPIRV/SPVRemapper.h"
Karl Schultz80b8aca2017-01-24 14:44:26 -080037#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/)
38#pragma warning(pop)
39#endif
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
Mark Lobodzinskic6a62142016-09-07 16:35:55 -060048#define ERR_EXIT(err_msg, err_class) \
49 do { \
50 MessageBox(NULL, err_msg, err_class, MB_OK); \
51 exit(1); \
Karl Schultz6addd812016-02-02 17:17:23 -070052 } while (0)
53#else // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -060054
Mark Lobodzinskic6a62142016-09-07 16:35:55 -060055#define ERR_EXIT(err_msg, err_class) \
56 do { \
57 printf(err_msg); \
58 fflush(stdout); \
59 exit(1); \
Karl Schultz6addd812016-02-02 17:17:23 -070060 } while (0)
Tony Barbour6a3faf02015-07-23 10:36:18 -060061#endif // _WIN32
62
Mark Lobodzinskic6a62142016-09-07 16:35:55 -060063#define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \
64 { \
65 m_fp##entrypoint = (PFN_vk##entrypoint)vkGetInstanceProcAddr(inst, "vk" #entrypoint); \
66 if (m_fp##entrypoint == NULL) { \
67 ERR_EXIT("vkGetInstanceProcAddr failed to find vk" #entrypoint, "vkGetInstanceProcAddr Failure"); \
68 } \
Karl Schultz6addd812016-02-02 17:17:23 -070069 }
Tony Barbour6a3faf02015-07-23 10:36:18 -060070
Mark Lobodzinskic6a62142016-09-07 16:35:55 -060071#define GET_DEVICE_PROC_ADDR(dev, entrypoint) \
72 { \
73 m_fp##entrypoint = (PFN_vk##entrypoint)vkGetDeviceProcAddr(dev, "vk" #entrypoint); \
74 if (m_fp##entrypoint == NULL) { \
75 ERR_EXIT("vkGetDeviceProcAddr failed to find vk" #entrypoint, "vkGetDeviceProcAddr Failure"); \
76 } \
Karl Schultz6addd812016-02-02 17:17:23 -070077 }
Tony Barbour6a3faf02015-07-23 10:36:18 -060078
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060079// Command-line options
80enum TOptions {
Karl Schultz6addd812016-02-02 17:17:23 -070081 EOptionNone = 0x000,
82 EOptionIntermediate = 0x001,
83 EOptionSuppressInfolog = 0x002,
84 EOptionMemoryLeakMode = 0x004,
85 EOptionRelaxedErrors = 0x008,
86 EOptionGiveWarnings = 0x010,
87 EOptionLinkProgram = 0x020,
88 EOptionMultiThreaded = 0x040,
89 EOptionDumpConfig = 0x080,
90 EOptionDumpReflection = 0x100,
91 EOptionSuppressWarnings = 0x200,
92 EOptionDumpVersions = 0x400,
93 EOptionSpv = 0x800,
94 EOptionDefaultDesktop = 0x1000,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060095};
96
Mark Lobodzinskib5ccf3f2016-05-19 17:26:51 -060097struct SwapchainBuffers {
Tony Barbour6a3faf02015-07-23 10:36:18 -060098 VkImage image;
Chia-I Wu3432a0c2015-10-27 18:04:07 +080099 VkCommandBuffer cmd;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -0600100 VkImageView view;
Mark Lobodzinskib5ccf3f2016-05-19 17:26:51 -0600101};
Tony Barbour6a3faf02015-07-23 10:36:18 -0600102
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600103#ifndef _WIN32
104
105#include <errno.h>
106
Karl Schultz6addd812016-02-02 17:17:23 -0700107int fopen_s(FILE **pFile, const char *filename, const char *mode) {
108 if (!pFile || !filename || !mode) {
109 return EINVAL;
110 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600111
Karl Schultz6addd812016-02-02 17:17:23 -0700112 FILE *f = fopen(filename, mode);
113 if (!f) {
114 if (errno != 0) {
115 return errno;
116 } else {
117 return ENOENT;
118 }
119 }
120 *pFile = f;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600121
Karl Schultz6addd812016-02-02 17:17:23 -0700122 return 0;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600123}
124
125#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600126
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600127// Set up environment for GLSL compiler
128// Must be done once per process
Karl Schultz6addd812016-02-02 17:17:23 -0700129void TestEnvironment::SetUp() {
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600130 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600131 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800132
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600133 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600134}
135
Karl Schultz6addd812016-02-02 17:17:23 -0700136void TestEnvironment::TearDown() { glslang::FinalizeProcess(); }
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600137
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600138VkTestFramework::VkTestFramework() : m_compile_options(0), m_num_shader_strings(0) {}
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600139
Karl Schultz6addd812016-02-02 17:17:23 -0700140VkTestFramework::~VkTestFramework() {}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600141
142// Define all the static elements
Karl Schultz6addd812016-02-02 17:17:23 -0700143bool VkTestFramework::m_use_glsl = false;
144bool VkTestFramework::m_canonicalize_spv = false;
145bool VkTestFramework::m_strip_spv = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600146bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour6918cd52015-04-09 12:58:51 -0600147int VkTestFramework::m_width = 0;
148int VkTestFramework::m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600149
Karl Schultz6addd812016-02-02 17:17:23 -0700150bool VkTestFramework::optionMatch(const char *option, char *optionLine) {
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600151 if (strncmp(option, optionLine, strlen(option)) == 0)
152 return true;
153 else
154 return false;
155}
156
Karl Schultz6addd812016-02-02 17:17:23 -0700157void VkTestFramework::InitArgs(int *argc, char *argv[]) {
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600158 int i, n;
159
Karl Schultz6addd812016-02-02 17:17:23 -0700160 for (i = 1, n = 1; i < *argc; i++) {
Tony Barbour7b60e492016-02-02 14:43:55 -0700161 if (optionMatch("--no-SPV", argv[i]))
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600162 m_use_glsl = true;
163 else if (optionMatch("--strip-SPV", argv[i]))
Tony Barbour7b60e492016-02-02 14:43:55 -0700164 m_strip_spv = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600165 else if (optionMatch("--canonicalize-SPV", argv[i]))
166 m_canonicalize_spv = true;
Karl Schultz6addd812016-02-02 17:17:23 -0700167 else if (optionMatch("--help", argv[i]) || optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700168 printf("\nOther options:\n");
169 printf("\t--show-images\n"
170 "\t\tDisplay test images in viewer after tests complete.\n");
171 printf("\t--save-images\n"
Karl Schultz6addd812016-02-02 17:17:23 -0700172 "\t\tSave tests images as ppm files in current working "
173 "directory.\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700174 "\t\tUsed to generate golden images for compare-images.\n");
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600175 printf("\t--compare-images\n"
176 "\t\tCompare test images to 'golden' image in golden folder.\n"
177 "\t\tAlso saves the generated test image in current working\n"
178 "\t\t\tdirectory but only if the image is different from the "
179 "golden\n"
180 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can "
181 "specify\n"
182 "\t\t\tdifferent directory for golden images\n"
183 "\t\tSignal test failure if different.\n");
184 printf("\t--no-SPV\n"
185 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600186 printf("\t--strip-SPV\n"
Karl Schultz6addd812016-02-02 17:17:23 -0700187 "\t\tStrip SPIR-V debug information (line numbers, names, "
188 "etc).\n");
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600189 printf("\t--canonicalize-SPV\n"
190 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600191 exit(0);
192 } else {
193 printf("\nUnrecognized option: %s\n", argv[i]);
194 printf("\nUse --help or -h for option list.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700195 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700196 }
197
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600198 /*
199 * Since the above "consume" inputs, update argv
200 * so that it contains the trimmed list of args for glutInit
201 */
202
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600203 argv[n] = argv[i];
204 n++;
205 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600206}
207
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600208VkFormat VkTestFramework::GetFormat(VkInstance instance, vk_testing::Device *device) {
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700209 VkFormatProperties format_props;
Tony Barbour7b60e492016-02-02 14:43:55 -0700210
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600211 vkGetPhysicalDeviceFormatProperties(device->phy().handle(), VK_FORMAT_B8G8R8A8_UNORM, &format_props);
212 if (format_props.linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ||
213 format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) {
Tony Barbour7b60e492016-02-02 14:43:55 -0700214 return VK_FORMAT_B8G8R8A8_UNORM;
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700215 }
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600216 vkGetPhysicalDeviceFormatProperties(device->phy().handle(), VK_FORMAT_R8G8B8A8_UNORM, &format_props);
217 if (format_props.linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ||
218 format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) {
Tony Barbour7b60e492016-02-02 14:43:55 -0700219 return VK_FORMAT_R8G8B8A8_UNORM;
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700220 }
Karl Schultz6addd812016-02-02 17:17:23 -0700221 printf("Error - device does not support VK_FORMAT_B8G8R8A8_UNORM nor "
222 "VK_FORMAT_R8G8B8A8_UNORM - exiting\n");
Tobin Ehlise37e9732016-07-11 12:57:29 -0600223 exit(1);
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700224}
225
Karl Schultz6addd812016-02-02 17:17:23 -0700226void VkTestFramework::Finish() {}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600227
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600228//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600229// These are the default resources for TBuiltInResources, used for both
230// - parsing this string for the case where the user didn't supply one
231// - dumping out a template for user construction of a config file
232//
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600233static const char *DefaultConfig = "MaxLights 32\n"
234 "MaxClipPlanes 6\n"
235 "MaxTextureUnits 32\n"
236 "MaxTextureCoords 32\n"
237 "MaxVertexAttribs 64\n"
238 "MaxVertexUniformComponents 4096\n"
239 "MaxVaryingFloats 64\n"
240 "MaxVertexTextureImageUnits 32\n"
241 "MaxCombinedTextureImageUnits 80\n"
242 "MaxTextureImageUnits 32\n"
243 "MaxFragmentUniformComponents 4096\n"
244 "MaxDrawBuffers 32\n"
245 "MaxVertexUniformVectors 128\n"
246 "MaxVaryingVectors 8\n"
247 "MaxFragmentUniformVectors 16\n"
248 "MaxVertexOutputVectors 16\n"
249 "MaxFragmentInputVectors 15\n"
250 "MinProgramTexelOffset -8\n"
251 "MaxProgramTexelOffset 7\n"
252 "MaxClipDistances 8\n"
253 "MaxComputeWorkGroupCountX 65535\n"
254 "MaxComputeWorkGroupCountY 65535\n"
255 "MaxComputeWorkGroupCountZ 65535\n"
256 "MaxComputeWorkGroupSizeX 1024\n"
257 "MaxComputeWorkGroupSizeY 1024\n"
258 "MaxComputeWorkGroupSizeZ 64\n"
259 "MaxComputeUniformComponents 1024\n"
260 "MaxComputeTextureImageUnits 16\n"
261 "MaxComputeImageUniforms 8\n"
262 "MaxComputeAtomicCounters 8\n"
263 "MaxComputeAtomicCounterBuffers 1\n"
264 "MaxVaryingComponents 60\n"
265 "MaxVertexOutputComponents 64\n"
266 "MaxGeometryInputComponents 64\n"
267 "MaxGeometryOutputComponents 128\n"
268 "MaxFragmentInputComponents 128\n"
269 "MaxImageUnits 8\n"
270 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
271 "MaxCombinedShaderOutputResources 8\n"
272 "MaxImageSamples 0\n"
273 "MaxVertexImageUniforms 0\n"
274 "MaxTessControlImageUniforms 0\n"
275 "MaxTessEvaluationImageUniforms 0\n"
276 "MaxGeometryImageUniforms 0\n"
277 "MaxFragmentImageUniforms 8\n"
278 "MaxCombinedImageUniforms 8\n"
279 "MaxGeometryTextureImageUnits 16\n"
280 "MaxGeometryOutputVertices 256\n"
281 "MaxGeometryTotalOutputComponents 1024\n"
282 "MaxGeometryUniformComponents 1024\n"
283 "MaxGeometryVaryingComponents 64\n"
284 "MaxTessControlInputComponents 128\n"
285 "MaxTessControlOutputComponents 128\n"
286 "MaxTessControlTextureImageUnits 16\n"
287 "MaxTessControlUniformComponents 1024\n"
288 "MaxTessControlTotalOutputComponents 4096\n"
289 "MaxTessEvaluationInputComponents 128\n"
290 "MaxTessEvaluationOutputComponents 128\n"
291 "MaxTessEvaluationTextureImageUnits 16\n"
292 "MaxTessEvaluationUniformComponents 1024\n"
293 "MaxTessPatchComponents 120\n"
294 "MaxPatchVertices 32\n"
295 "MaxTessGenLevel 64\n"
296 "MaxViewports 16\n"
297 "MaxVertexAtomicCounters 0\n"
298 "MaxTessControlAtomicCounters 0\n"
299 "MaxTessEvaluationAtomicCounters 0\n"
300 "MaxGeometryAtomicCounters 0\n"
301 "MaxFragmentAtomicCounters 8\n"
302 "MaxCombinedAtomicCounters 8\n"
303 "MaxAtomicCounterBindings 1\n"
304 "MaxVertexAtomicCounterBuffers 0\n"
305 "MaxTessControlAtomicCounterBuffers 0\n"
306 "MaxTessEvaluationAtomicCounterBuffers 0\n"
307 "MaxGeometryAtomicCounterBuffers 0\n"
308 "MaxFragmentAtomicCounterBuffers 1\n"
309 "MaxCombinedAtomicCounterBuffers 1\n"
310 "MaxAtomicCounterBufferSize 16384\n"
311 "MaxTransformFeedbackBuffers 4\n"
312 "MaxTransformFeedbackInterleavedComponents 64\n"
313 "MaxCullDistances 8\n"
314 "MaxCombinedClipAndCullDistances 8\n"
315 "MaxSamples 4\n"
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600316
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600317 "nonInductiveForLoops 1\n"
318 "whileLoops 1\n"
319 "doWhileLoops 1\n"
320 "generalUniformIndexing 1\n"
321 "generalAttributeMatrixVectorIndexing 1\n"
322 "generalVaryingIndexing 1\n"
323 "generalSamplerIndexing 1\n"
324 "generalVariableIndexing 1\n"
325 "generalConstantMatrixVectorIndexing 1\n";
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600326
327//
328// *.conf => this is a config file that can set limits/resources
329//
Karl Schultz6addd812016-02-02 17:17:23 -0700330bool VkTestFramework::SetConfigFile(const std::string &name) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600331 if (name.size() < 5)
332 return false;
333
334 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
335 ConfigFile = name;
336 return true;
337 }
338
339 return false;
340}
341
342//
343// Parse either a .conf file provided by the user or the default string above.
344//
Karl Schultz6addd812016-02-02 17:17:23 -0700345void VkTestFramework::ProcessConfigFile() {
346 char **configStrings = 0;
347 char *config = 0;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600348 if (ConfigFile.size() > 0) {
349 configStrings = ReadFileData(ConfigFile.c_str());
350 if (configStrings)
351 config = *configStrings;
352 else {
Karl Schultz6addd812016-02-02 17:17:23 -0700353 printf("Error opening configuration file; will instead use the "
354 "default configuration\n");
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600355 }
356 }
357
358 if (config == 0) {
Karl Schultz6addd812016-02-02 17:17:23 -0700359 config = (char *)alloca(strlen(DefaultConfig) + 1);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600360 strcpy(config, DefaultConfig);
361 }
362
Karl Schultz6addd812016-02-02 17:17:23 -0700363 const char *delims = " \t\n\r";
364 const char *token = strtok(config, delims);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600365 while (token) {
Karl Schultz6addd812016-02-02 17:17:23 -0700366 const char *valueStr = strtok(0, delims);
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600367 if (valueStr == 0 || !(valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
Karl Schultz6addd812016-02-02 17:17:23 -0700368 printf("Error: '%s' bad .conf file. Each name must be followed by "
369 "one number.\n",
370 valueStr ? valueStr : "");
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600371 return;
372 }
373 int value = atoi(valueStr);
374
375 if (strcmp(token, "MaxLights") == 0)
376 Resources.maxLights = value;
377 else if (strcmp(token, "MaxClipPlanes") == 0)
378 Resources.maxClipPlanes = value;
379 else if (strcmp(token, "MaxTextureUnits") == 0)
380 Resources.maxTextureUnits = value;
381 else if (strcmp(token, "MaxTextureCoords") == 0)
382 Resources.maxTextureCoords = value;
383 else if (strcmp(token, "MaxVertexAttribs") == 0)
384 Resources.maxVertexAttribs = value;
385 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
386 Resources.maxVertexUniformComponents = value;
387 else if (strcmp(token, "MaxVaryingFloats") == 0)
388 Resources.maxVaryingFloats = value;
389 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
390 Resources.maxVertexTextureImageUnits = value;
391 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
392 Resources.maxCombinedTextureImageUnits = value;
393 else if (strcmp(token, "MaxTextureImageUnits") == 0)
394 Resources.maxTextureImageUnits = value;
395 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
396 Resources.maxFragmentUniformComponents = value;
397 else if (strcmp(token, "MaxDrawBuffers") == 0)
398 Resources.maxDrawBuffers = value;
399 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
400 Resources.maxVertexUniformVectors = value;
401 else if (strcmp(token, "MaxVaryingVectors") == 0)
402 Resources.maxVaryingVectors = value;
403 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
404 Resources.maxFragmentUniformVectors = value;
405 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
406 Resources.maxVertexOutputVectors = value;
407 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
408 Resources.maxFragmentInputVectors = value;
409 else if (strcmp(token, "MinProgramTexelOffset") == 0)
410 Resources.minProgramTexelOffset = value;
411 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
412 Resources.maxProgramTexelOffset = value;
413 else if (strcmp(token, "MaxClipDistances") == 0)
414 Resources.maxClipDistances = value;
415 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
416 Resources.maxComputeWorkGroupCountX = value;
417 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
418 Resources.maxComputeWorkGroupCountY = value;
419 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
420 Resources.maxComputeWorkGroupCountZ = value;
421 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
422 Resources.maxComputeWorkGroupSizeX = value;
423 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
424 Resources.maxComputeWorkGroupSizeY = value;
425 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
426 Resources.maxComputeWorkGroupSizeZ = value;
427 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
428 Resources.maxComputeUniformComponents = value;
429 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
430 Resources.maxComputeTextureImageUnits = value;
431 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
432 Resources.maxComputeImageUniforms = value;
433 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
434 Resources.maxComputeAtomicCounters = value;
435 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
436 Resources.maxComputeAtomicCounterBuffers = value;
437 else if (strcmp(token, "MaxVaryingComponents") == 0)
438 Resources.maxVaryingComponents = value;
439 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
440 Resources.maxVertexOutputComponents = value;
441 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
442 Resources.maxGeometryInputComponents = value;
443 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
444 Resources.maxGeometryOutputComponents = value;
445 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
446 Resources.maxFragmentInputComponents = value;
447 else if (strcmp(token, "MaxImageUnits") == 0)
448 Resources.maxImageUnits = value;
449 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
450 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
451 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
452 Resources.maxCombinedShaderOutputResources = value;
453 else if (strcmp(token, "MaxImageSamples") == 0)
454 Resources.maxImageSamples = value;
455 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
456 Resources.maxVertexImageUniforms = value;
457 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
458 Resources.maxTessControlImageUniforms = value;
459 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
460 Resources.maxTessEvaluationImageUniforms = value;
461 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
462 Resources.maxGeometryImageUniforms = value;
463 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
464 Resources.maxFragmentImageUniforms = value;
465 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
466 Resources.maxCombinedImageUniforms = value;
467 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
468 Resources.maxGeometryTextureImageUnits = value;
469 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
470 Resources.maxGeometryOutputVertices = value;
471 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
472 Resources.maxGeometryTotalOutputComponents = value;
473 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
474 Resources.maxGeometryUniformComponents = value;
475 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
476 Resources.maxGeometryVaryingComponents = value;
477 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
478 Resources.maxTessControlInputComponents = value;
479 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
480 Resources.maxTessControlOutputComponents = value;
481 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
482 Resources.maxTessControlTextureImageUnits = value;
483 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
484 Resources.maxTessControlUniformComponents = value;
485 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
486 Resources.maxTessControlTotalOutputComponents = value;
487 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
488 Resources.maxTessEvaluationInputComponents = value;
489 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
490 Resources.maxTessEvaluationOutputComponents = value;
491 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
492 Resources.maxTessEvaluationTextureImageUnits = value;
493 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
494 Resources.maxTessEvaluationUniformComponents = value;
495 else if (strcmp(token, "MaxTessPatchComponents") == 0)
496 Resources.maxTessPatchComponents = value;
497 else if (strcmp(token, "MaxPatchVertices") == 0)
498 Resources.maxPatchVertices = value;
499 else if (strcmp(token, "MaxTessGenLevel") == 0)
500 Resources.maxTessGenLevel = value;
501 else if (strcmp(token, "MaxViewports") == 0)
502 Resources.maxViewports = value;
503 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
504 Resources.maxVertexAtomicCounters = value;
505 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
506 Resources.maxTessControlAtomicCounters = value;
507 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
508 Resources.maxTessEvaluationAtomicCounters = value;
509 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
510 Resources.maxGeometryAtomicCounters = value;
511 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
512 Resources.maxFragmentAtomicCounters = value;
513 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
514 Resources.maxCombinedAtomicCounters = value;
515 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
516 Resources.maxAtomicCounterBindings = value;
517 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
518 Resources.maxVertexAtomicCounterBuffers = value;
519 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
520 Resources.maxTessControlAtomicCounterBuffers = value;
521 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
522 Resources.maxTessEvaluationAtomicCounterBuffers = value;
523 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
524 Resources.maxGeometryAtomicCounterBuffers = value;
525 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
526 Resources.maxFragmentAtomicCounterBuffers = value;
527 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
528 Resources.maxCombinedAtomicCounterBuffers = value;
529 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
530 Resources.maxAtomicCounterBufferSize = value;
531 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
532 Resources.maxTransformFeedbackBuffers = value;
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600533 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600534 Resources.maxTransformFeedbackInterleavedComponents = value;
535 else if (strcmp(token, "MaxCullDistances") == 0)
536 Resources.maxCullDistances = value;
537 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
538 Resources.maxCombinedClipAndCullDistances = value;
539 else if (strcmp(token, "MaxSamples") == 0)
540 Resources.maxSamples = value;
541
542 else if (strcmp(token, "nonInductiveForLoops") == 0)
543 Resources.limits.nonInductiveForLoops = (value != 0);
544 else if (strcmp(token, "whileLoops") == 0)
545 Resources.limits.whileLoops = (value != 0);
546 else if (strcmp(token, "doWhileLoops") == 0)
547 Resources.limits.doWhileLoops = (value != 0);
548 else if (strcmp(token, "generalUniformIndexing") == 0)
549 Resources.limits.generalUniformIndexing = (value != 0);
550 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600551 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600552 else if (strcmp(token, "generalVaryingIndexing") == 0)
553 Resources.limits.generalVaryingIndexing = (value != 0);
554 else if (strcmp(token, "generalSamplerIndexing") == 0)
555 Resources.limits.generalSamplerIndexing = (value != 0);
556 else if (strcmp(token, "generalVariableIndexing") == 0)
557 Resources.limits.generalVariableIndexing = (value != 0);
558 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
559 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
560 else
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600561 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600562
563 token = strtok(0, delims);
564 }
565 if (configStrings)
566 FreeFileData(configStrings);
567}
568
Karl Schultz6addd812016-02-02 17:17:23 -0700569void VkTestFramework::SetMessageOptions(EShMessages &messages) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600570 if (m_compile_options & EOptionRelaxedErrors)
571 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
572 if (m_compile_options & EOptionIntermediate)
573 messages = (EShMessages)(messages | EShMsgAST);
574 if (m_compile_options & EOptionSuppressWarnings)
575 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
576}
577
578//
579// Malloc a string of sufficient size and read a string into it.
580//
Karl Schultz6addd812016-02-02 17:17:23 -0700581char **VkTestFramework::ReadFileData(const char *fileName) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600582 FILE *in;
Karl Schultz6addd812016-02-02 17:17:23 -0700583#if defined(_WIN32) && defined(__GNUC__)
584 in = fopen(fileName, "r");
585 int errorCode = in ? 0 : 1;
586#else
587 int errorCode = fopen_s(&in, fileName, "r");
588#endif
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600589
590 char *fdata;
Jeremy Hayes3b2a3a32016-06-21 11:05:08 -0600591 size_t count = 0;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600592 const int maxSourceStrings = 5;
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600593 char **return_data = (char **)malloc(sizeof(char *) * (maxSourceStrings + 1));
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600594
595 if (errorCode) {
596 printf("Error: unable to open input file: %s\n", fileName);
597 return 0;
598 }
599
600 while (fgetc(in) != EOF)
601 count++;
602
603 fseek(in, 0, SEEK_SET);
604
Karl Schultz6addd812016-02-02 17:17:23 -0700605 if (!(fdata = (char *)malloc(count + 2))) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600606 printf("Error allocating memory\n");
607 return 0;
608 }
Karl Schultz6addd812016-02-02 17:17:23 -0700609 if (fread(fdata, 1, count, in) != count) {
610 printf("Error reading input file: %s\n", fileName);
611 return 0;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600612 }
613 fdata[count] = '\0';
614 fclose(in);
615 if (count == 0) {
Karl Schultz6addd812016-02-02 17:17:23 -0700616 return_data[0] = (char *)malloc(count + 2);
617 return_data[0][0] = '\0';
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600618 m_num_shader_strings = 0;
619 return return_data;
620 } else
621 m_num_shader_strings = 1;
622
Jeremy Hayes3b2a3a32016-06-21 11:05:08 -0600623 size_t len = (int)(ceil)((float)count / (float)m_num_shader_strings);
624 size_t ptr_len = 0, i = 0;
Karl Schultz6addd812016-02-02 17:17:23 -0700625 while (count > 0) {
626 return_data[i] = (char *)malloc(len + 2);
627 memcpy(return_data[i], fdata + ptr_len, len);
628 return_data[i][len] = '\0';
629 count -= (len);
630 ptr_len += (len);
631 if (count < len) {
632 if (count == 0) {
633 m_num_shader_strings = (i + 1);
634 break;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600635 }
Karl Schultz6addd812016-02-02 17:17:23 -0700636 len = count;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600637 }
638 ++i;
639 }
640 return return_data;
641}
642
Karl Schultz6addd812016-02-02 17:17:23 -0700643void VkTestFramework::FreeFileData(char **data) {
644 for (int i = 0; i < m_num_shader_strings; i++)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600645 free(data[i]);
646}
647
648//
649// Deduce the language from the filename. Files must end in one of the
650// following extensions:
651//
652// .vert = vertex
653// .tesc = tessellation control
654// .tese = tessellation evaluation
655// .geom = geometry
656// .frag = fragment
657// .comp = compute
658//
Karl Schultz6addd812016-02-02 17:17:23 -0700659EShLanguage VkTestFramework::FindLanguage(const std::string &name) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600660 size_t ext = name.rfind('.');
661 if (ext == std::string::npos) {
662 return EShLangVertex;
663 }
664
665 std::string suffix = name.substr(ext + 1, std::string::npos);
666 if (suffix == "vert")
667 return EShLangVertex;
668 else if (suffix == "tesc")
669 return EShLangTessControl;
670 else if (suffix == "tese")
671 return EShLangTessEvaluation;
672 else if (suffix == "geom")
673 return EShLangGeometry;
674 else if (suffix == "frag")
675 return EShLangFragment;
676 else if (suffix == "comp")
677 return EShLangCompute;
678
679 return EShLangVertex;
680}
681
682//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600683// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600684//
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600685EShLanguage VkTestFramework::FindLanguage(const VkShaderStageFlagBits shader_type) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600686 switch (shader_type) {
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600687 case VK_SHADER_STAGE_VERTEX_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600688 return EShLangVertex;
689
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600690 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600691 return EShLangTessControl;
692
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600693 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600694 return EShLangTessEvaluation;
695
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600696 case VK_SHADER_STAGE_GEOMETRY_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600697 return EShLangGeometry;
698
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600699 case VK_SHADER_STAGE_FRAGMENT_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600700 return EShLangFragment;
701
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600702 case VK_SHADER_STAGE_COMPUTE_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600703 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600704
Chia-I Wub4c2aa42014-12-15 23:50:11 +0800705 default:
706 return EShLangVertex;
707 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600708}
709
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600710//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600711// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600712// Return value of false means an error was encountered.
713//
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600714bool VkTestFramework::GLSLtoSPV(const VkShaderStageFlagBits shader_type, const char *pshader, std::vector<unsigned int> &spirv) {
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -0600715 glslang::TProgram program;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600716 const char *shaderStrings[1];
717
718 // TODO: Do we want to load a special config file depending on the
719 // shader source? Optional name maybe?
720 // SetConfigFile(fileName);
721
722 ProcessConfigFile();
723
724 EShMessages messages = EShMsgDefault;
725 SetMessageOptions(messages);
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600726 messages = static_cast<EShMessages>(messages | EShMsgSpvRules | EShMsgVulkanRules);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600727
728 EShLanguage stage = FindLanguage(shader_type);
Karl Schultz6addd812016-02-02 17:17:23 -0700729 glslang::TShader *shader = new glslang::TShader(stage);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600730
731 shaderStrings[0] = pshader;
732 shader->setStrings(shaderStrings, 1);
733
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600734 if (!shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600735
Karl Schultz6addd812016-02-02 17:17:23 -0700736 if (!(m_compile_options & EOptionSuppressInfolog)) {
Cody Northrop195d6622014-11-03 12:54:37 -0700737 puts(shader->getInfoLog());
738 puts(shader->getInfoDebugLog());
739 }
740
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600741 return false; // something didn't work
742 }
743
744 program.addShader(shader);
745
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600746 //
747 // Program-level processing...
748 //
749
Karl Schultz6addd812016-02-02 17:17:23 -0700750 if (!program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600751
Karl Schultz6addd812016-02-02 17:17:23 -0700752 if (!(m_compile_options & EOptionSuppressInfolog)) {
Cody Northrop195d6622014-11-03 12:54:37 -0700753 puts(shader->getInfoLog());
754 puts(shader->getInfoDebugLog());
755 }
756
757 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600758 }
759
760 if (m_compile_options & EOptionDumpReflection) {
761 program.buildReflection();
762 program.dumpReflection();
763 }
764
Cody Northrop5a95b472015-06-03 13:01:54 -0600765 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
766
767 //
768 // Test the different modes of SPIR-V modification
769 //
770 if (this->m_canonicalize_spv) {
771 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
772 }
773
774 if (this->m_strip_spv) {
775 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
776 }
777
778 if (this->m_do_everything_spv) {
779 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
780 }
781
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -0600782 delete shader;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600783
784 return true;
785}