blob: 3970f9a70cc346f4912f79e89cd6d71752dffcdf [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 Schultz6addd812016-02-02 17:17:23 -070025// TODO FIXME remove this once glslang doesn't define this
Jon Ashburn94207e92015-12-04 17:03:59 -070026#undef BadValue
Cody Northrop5a95b472015-06-03 13:01:54 -060027#include "SPIRV/GlslangToSpv.h"
28#include "SPIRV/SPVRemapper.h"
Tony Barbour4ab45422014-12-10 17:00:20 -070029#include <limits.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060030#include <math.h>
Jon Ashburn94207e92015-12-04 17:03:59 -070031
Tony Barbour3d69c9e2015-05-20 16:53:31 -060032#if defined(PATH_MAX) && !defined(MAX_PATH)
33#define MAX_PATH PATH_MAX
34#endif
35
Tony Barbour6a3faf02015-07-23 10:36:18 -060036#ifdef _WIN32
Mark Lobodzinskic6a62142016-09-07 16:35:55 -060037#define ERR_EXIT(err_msg, err_class) \
38 do { \
39 MessageBox(NULL, err_msg, err_class, MB_OK); \
40 exit(1); \
Karl Schultz6addd812016-02-02 17:17:23 -070041 } while (0)
42#else // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -060043
Mark Lobodzinskic6a62142016-09-07 16:35:55 -060044#define ERR_EXIT(err_msg, err_class) \
45 do { \
46 printf(err_msg); \
47 fflush(stdout); \
48 exit(1); \
Karl Schultz6addd812016-02-02 17:17:23 -070049 } while (0)
Tony Barbour6a3faf02015-07-23 10:36:18 -060050#endif // _WIN32
51
Mark Lobodzinskic6a62142016-09-07 16:35:55 -060052#define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \
53 { \
54 m_fp##entrypoint = (PFN_vk##entrypoint)vkGetInstanceProcAddr(inst, "vk" #entrypoint); \
55 if (m_fp##entrypoint == NULL) { \
56 ERR_EXIT("vkGetInstanceProcAddr failed to find vk" #entrypoint, "vkGetInstanceProcAddr Failure"); \
57 } \
Karl Schultz6addd812016-02-02 17:17:23 -070058 }
Tony Barbour6a3faf02015-07-23 10:36:18 -060059
Mark Lobodzinskic6a62142016-09-07 16:35:55 -060060#define GET_DEVICE_PROC_ADDR(dev, entrypoint) \
61 { \
62 m_fp##entrypoint = (PFN_vk##entrypoint)vkGetDeviceProcAddr(dev, "vk" #entrypoint); \
63 if (m_fp##entrypoint == NULL) { \
64 ERR_EXIT("vkGetDeviceProcAddr failed to find vk" #entrypoint, "vkGetDeviceProcAddr Failure"); \
65 } \
Karl Schultz6addd812016-02-02 17:17:23 -070066 }
Tony Barbour6a3faf02015-07-23 10:36:18 -060067
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060068// Command-line options
69enum TOptions {
Karl Schultz6addd812016-02-02 17:17:23 -070070 EOptionNone = 0x000,
71 EOptionIntermediate = 0x001,
72 EOptionSuppressInfolog = 0x002,
73 EOptionMemoryLeakMode = 0x004,
74 EOptionRelaxedErrors = 0x008,
75 EOptionGiveWarnings = 0x010,
76 EOptionLinkProgram = 0x020,
77 EOptionMultiThreaded = 0x040,
78 EOptionDumpConfig = 0x080,
79 EOptionDumpReflection = 0x100,
80 EOptionSuppressWarnings = 0x200,
81 EOptionDumpVersions = 0x400,
82 EOptionSpv = 0x800,
83 EOptionDefaultDesktop = 0x1000,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060084};
85
Mark Lobodzinskib5ccf3f2016-05-19 17:26:51 -060086struct SwapchainBuffers {
Tony Barbour6a3faf02015-07-23 10:36:18 -060087 VkImage image;
Chia-I Wu3432a0c2015-10-27 18:04:07 +080088 VkCommandBuffer cmd;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -060089 VkImageView view;
Mark Lobodzinskib5ccf3f2016-05-19 17:26:51 -060090};
Tony Barbour6a3faf02015-07-23 10:36:18 -060091
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060092#ifndef _WIN32
93
94#include <errno.h>
95
Karl Schultz6addd812016-02-02 17:17:23 -070096int fopen_s(FILE **pFile, const char *filename, const char *mode) {
97 if (!pFile || !filename || !mode) {
98 return EINVAL;
99 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600100
Karl Schultz6addd812016-02-02 17:17:23 -0700101 FILE *f = fopen(filename, mode);
102 if (!f) {
103 if (errno != 0) {
104 return errno;
105 } else {
106 return ENOENT;
107 }
108 }
109 *pFile = f;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600110
Karl Schultz6addd812016-02-02 17:17:23 -0700111 return 0;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600112}
113
114#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600115
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600116// Set up environment for GLSL compiler
117// Must be done once per process
Karl Schultz6addd812016-02-02 17:17:23 -0700118void TestEnvironment::SetUp() {
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600119 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600120 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800121
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600122 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600123}
124
Karl Schultz6addd812016-02-02 17:17:23 -0700125void TestEnvironment::TearDown() { glslang::FinalizeProcess(); }
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600126
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600127VkTestFramework::VkTestFramework() : m_compile_options(0), m_num_shader_strings(0) {}
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600128
Karl Schultz6addd812016-02-02 17:17:23 -0700129VkTestFramework::~VkTestFramework() {}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600130
131// Define all the static elements
Karl Schultz6addd812016-02-02 17:17:23 -0700132bool VkTestFramework::m_use_glsl = false;
133bool VkTestFramework::m_canonicalize_spv = false;
134bool VkTestFramework::m_strip_spv = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600135bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour6918cd52015-04-09 12:58:51 -0600136int VkTestFramework::m_width = 0;
137int VkTestFramework::m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600138
Karl Schultz6addd812016-02-02 17:17:23 -0700139bool VkTestFramework::optionMatch(const char *option, char *optionLine) {
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600140 if (strncmp(option, optionLine, strlen(option)) == 0)
141 return true;
142 else
143 return false;
144}
145
Karl Schultz6addd812016-02-02 17:17:23 -0700146void VkTestFramework::InitArgs(int *argc, char *argv[]) {
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600147 int i, n;
148
Karl Schultz6addd812016-02-02 17:17:23 -0700149 for (i = 1, n = 1; i < *argc; i++) {
Tony Barbour7b60e492016-02-02 14:43:55 -0700150 if (optionMatch("--no-SPV", argv[i]))
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600151 m_use_glsl = true;
152 else if (optionMatch("--strip-SPV", argv[i]))
Tony Barbour7b60e492016-02-02 14:43:55 -0700153 m_strip_spv = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600154 else if (optionMatch("--canonicalize-SPV", argv[i]))
155 m_canonicalize_spv = true;
Karl Schultz6addd812016-02-02 17:17:23 -0700156 else if (optionMatch("--help", argv[i]) || optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700157 printf("\nOther options:\n");
158 printf("\t--show-images\n"
159 "\t\tDisplay test images in viewer after tests complete.\n");
160 printf("\t--save-images\n"
Karl Schultz6addd812016-02-02 17:17:23 -0700161 "\t\tSave tests images as ppm files in current working "
162 "directory.\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700163 "\t\tUsed to generate golden images for compare-images.\n");
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600164 printf("\t--compare-images\n"
165 "\t\tCompare test images to 'golden' image in golden folder.\n"
166 "\t\tAlso saves the generated test image in current working\n"
167 "\t\t\tdirectory but only if the image is different from the "
168 "golden\n"
169 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can "
170 "specify\n"
171 "\t\t\tdifferent directory for golden images\n"
172 "\t\tSignal test failure if different.\n");
173 printf("\t--no-SPV\n"
174 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600175 printf("\t--strip-SPV\n"
Karl Schultz6addd812016-02-02 17:17:23 -0700176 "\t\tStrip SPIR-V debug information (line numbers, names, "
177 "etc).\n");
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600178 printf("\t--canonicalize-SPV\n"
179 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600180 exit(0);
181 } else {
182 printf("\nUnrecognized option: %s\n", argv[i]);
183 printf("\nUse --help or -h for option list.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700184 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700185 }
186
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600187 /*
188 * Since the above "consume" inputs, update argv
189 * so that it contains the trimmed list of args for glutInit
190 */
191
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600192 argv[n] = argv[i];
193 n++;
194 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600195}
196
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600197VkFormat VkTestFramework::GetFormat(VkInstance instance, vk_testing::Device *device) {
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700198 VkFormatProperties format_props;
Tony Barbour7b60e492016-02-02 14:43:55 -0700199
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600200 vkGetPhysicalDeviceFormatProperties(device->phy().handle(), VK_FORMAT_B8G8R8A8_UNORM, &format_props);
201 if (format_props.linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ||
202 format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) {
Tony Barbour7b60e492016-02-02 14:43:55 -0700203 return VK_FORMAT_B8G8R8A8_UNORM;
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700204 }
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600205 vkGetPhysicalDeviceFormatProperties(device->phy().handle(), VK_FORMAT_R8G8B8A8_UNORM, &format_props);
206 if (format_props.linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ||
207 format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) {
Tony Barbour7b60e492016-02-02 14:43:55 -0700208 return VK_FORMAT_R8G8B8A8_UNORM;
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700209 }
Karl Schultz6addd812016-02-02 17:17:23 -0700210 printf("Error - device does not support VK_FORMAT_B8G8R8A8_UNORM nor "
211 "VK_FORMAT_R8G8B8A8_UNORM - exiting\n");
Tobin Ehlise37e9732016-07-11 12:57:29 -0600212 exit(1);
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700213}
214
Karl Schultz6addd812016-02-02 17:17:23 -0700215void VkTestFramework::Finish() {}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600216
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600217//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600218// These are the default resources for TBuiltInResources, used for both
219// - parsing this string for the case where the user didn't supply one
220// - dumping out a template for user construction of a config file
221//
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600222static const char *DefaultConfig = "MaxLights 32\n"
223 "MaxClipPlanes 6\n"
224 "MaxTextureUnits 32\n"
225 "MaxTextureCoords 32\n"
226 "MaxVertexAttribs 64\n"
227 "MaxVertexUniformComponents 4096\n"
228 "MaxVaryingFloats 64\n"
229 "MaxVertexTextureImageUnits 32\n"
230 "MaxCombinedTextureImageUnits 80\n"
231 "MaxTextureImageUnits 32\n"
232 "MaxFragmentUniformComponents 4096\n"
233 "MaxDrawBuffers 32\n"
234 "MaxVertexUniformVectors 128\n"
235 "MaxVaryingVectors 8\n"
236 "MaxFragmentUniformVectors 16\n"
237 "MaxVertexOutputVectors 16\n"
238 "MaxFragmentInputVectors 15\n"
239 "MinProgramTexelOffset -8\n"
240 "MaxProgramTexelOffset 7\n"
241 "MaxClipDistances 8\n"
242 "MaxComputeWorkGroupCountX 65535\n"
243 "MaxComputeWorkGroupCountY 65535\n"
244 "MaxComputeWorkGroupCountZ 65535\n"
245 "MaxComputeWorkGroupSizeX 1024\n"
246 "MaxComputeWorkGroupSizeY 1024\n"
247 "MaxComputeWorkGroupSizeZ 64\n"
248 "MaxComputeUniformComponents 1024\n"
249 "MaxComputeTextureImageUnits 16\n"
250 "MaxComputeImageUniforms 8\n"
251 "MaxComputeAtomicCounters 8\n"
252 "MaxComputeAtomicCounterBuffers 1\n"
253 "MaxVaryingComponents 60\n"
254 "MaxVertexOutputComponents 64\n"
255 "MaxGeometryInputComponents 64\n"
256 "MaxGeometryOutputComponents 128\n"
257 "MaxFragmentInputComponents 128\n"
258 "MaxImageUnits 8\n"
259 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
260 "MaxCombinedShaderOutputResources 8\n"
261 "MaxImageSamples 0\n"
262 "MaxVertexImageUniforms 0\n"
263 "MaxTessControlImageUniforms 0\n"
264 "MaxTessEvaluationImageUniforms 0\n"
265 "MaxGeometryImageUniforms 0\n"
266 "MaxFragmentImageUniforms 8\n"
267 "MaxCombinedImageUniforms 8\n"
268 "MaxGeometryTextureImageUnits 16\n"
269 "MaxGeometryOutputVertices 256\n"
270 "MaxGeometryTotalOutputComponents 1024\n"
271 "MaxGeometryUniformComponents 1024\n"
272 "MaxGeometryVaryingComponents 64\n"
273 "MaxTessControlInputComponents 128\n"
274 "MaxTessControlOutputComponents 128\n"
275 "MaxTessControlTextureImageUnits 16\n"
276 "MaxTessControlUniformComponents 1024\n"
277 "MaxTessControlTotalOutputComponents 4096\n"
278 "MaxTessEvaluationInputComponents 128\n"
279 "MaxTessEvaluationOutputComponents 128\n"
280 "MaxTessEvaluationTextureImageUnits 16\n"
281 "MaxTessEvaluationUniformComponents 1024\n"
282 "MaxTessPatchComponents 120\n"
283 "MaxPatchVertices 32\n"
284 "MaxTessGenLevel 64\n"
285 "MaxViewports 16\n"
286 "MaxVertexAtomicCounters 0\n"
287 "MaxTessControlAtomicCounters 0\n"
288 "MaxTessEvaluationAtomicCounters 0\n"
289 "MaxGeometryAtomicCounters 0\n"
290 "MaxFragmentAtomicCounters 8\n"
291 "MaxCombinedAtomicCounters 8\n"
292 "MaxAtomicCounterBindings 1\n"
293 "MaxVertexAtomicCounterBuffers 0\n"
294 "MaxTessControlAtomicCounterBuffers 0\n"
295 "MaxTessEvaluationAtomicCounterBuffers 0\n"
296 "MaxGeometryAtomicCounterBuffers 0\n"
297 "MaxFragmentAtomicCounterBuffers 1\n"
298 "MaxCombinedAtomicCounterBuffers 1\n"
299 "MaxAtomicCounterBufferSize 16384\n"
300 "MaxTransformFeedbackBuffers 4\n"
301 "MaxTransformFeedbackInterleavedComponents 64\n"
302 "MaxCullDistances 8\n"
303 "MaxCombinedClipAndCullDistances 8\n"
304 "MaxSamples 4\n"
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600305
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600306 "nonInductiveForLoops 1\n"
307 "whileLoops 1\n"
308 "doWhileLoops 1\n"
309 "generalUniformIndexing 1\n"
310 "generalAttributeMatrixVectorIndexing 1\n"
311 "generalVaryingIndexing 1\n"
312 "generalSamplerIndexing 1\n"
313 "generalVariableIndexing 1\n"
314 "generalConstantMatrixVectorIndexing 1\n";
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600315
316//
317// *.conf => this is a config file that can set limits/resources
318//
Karl Schultz6addd812016-02-02 17:17:23 -0700319bool VkTestFramework::SetConfigFile(const std::string &name) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600320 if (name.size() < 5)
321 return false;
322
323 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
324 ConfigFile = name;
325 return true;
326 }
327
328 return false;
329}
330
331//
332// Parse either a .conf file provided by the user or the default string above.
333//
Karl Schultz6addd812016-02-02 17:17:23 -0700334void VkTestFramework::ProcessConfigFile() {
335 char **configStrings = 0;
336 char *config = 0;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600337 if (ConfigFile.size() > 0) {
338 configStrings = ReadFileData(ConfigFile.c_str());
339 if (configStrings)
340 config = *configStrings;
341 else {
Karl Schultz6addd812016-02-02 17:17:23 -0700342 printf("Error opening configuration file; will instead use the "
343 "default configuration\n");
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600344 }
345 }
346
347 if (config == 0) {
Karl Schultz6addd812016-02-02 17:17:23 -0700348 config = (char *)alloca(strlen(DefaultConfig) + 1);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600349 strcpy(config, DefaultConfig);
350 }
351
Karl Schultz6addd812016-02-02 17:17:23 -0700352 const char *delims = " \t\n\r";
353 const char *token = strtok(config, delims);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600354 while (token) {
Karl Schultz6addd812016-02-02 17:17:23 -0700355 const char *valueStr = strtok(0, delims);
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600356 if (valueStr == 0 || !(valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
Karl Schultz6addd812016-02-02 17:17:23 -0700357 printf("Error: '%s' bad .conf file. Each name must be followed by "
358 "one number.\n",
359 valueStr ? valueStr : "");
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600360 return;
361 }
362 int value = atoi(valueStr);
363
364 if (strcmp(token, "MaxLights") == 0)
365 Resources.maxLights = value;
366 else if (strcmp(token, "MaxClipPlanes") == 0)
367 Resources.maxClipPlanes = value;
368 else if (strcmp(token, "MaxTextureUnits") == 0)
369 Resources.maxTextureUnits = value;
370 else if (strcmp(token, "MaxTextureCoords") == 0)
371 Resources.maxTextureCoords = value;
372 else if (strcmp(token, "MaxVertexAttribs") == 0)
373 Resources.maxVertexAttribs = value;
374 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
375 Resources.maxVertexUniformComponents = value;
376 else if (strcmp(token, "MaxVaryingFloats") == 0)
377 Resources.maxVaryingFloats = value;
378 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
379 Resources.maxVertexTextureImageUnits = value;
380 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
381 Resources.maxCombinedTextureImageUnits = value;
382 else if (strcmp(token, "MaxTextureImageUnits") == 0)
383 Resources.maxTextureImageUnits = value;
384 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
385 Resources.maxFragmentUniformComponents = value;
386 else if (strcmp(token, "MaxDrawBuffers") == 0)
387 Resources.maxDrawBuffers = value;
388 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
389 Resources.maxVertexUniformVectors = value;
390 else if (strcmp(token, "MaxVaryingVectors") == 0)
391 Resources.maxVaryingVectors = value;
392 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
393 Resources.maxFragmentUniformVectors = value;
394 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
395 Resources.maxVertexOutputVectors = value;
396 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
397 Resources.maxFragmentInputVectors = value;
398 else if (strcmp(token, "MinProgramTexelOffset") == 0)
399 Resources.minProgramTexelOffset = value;
400 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
401 Resources.maxProgramTexelOffset = value;
402 else if (strcmp(token, "MaxClipDistances") == 0)
403 Resources.maxClipDistances = value;
404 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
405 Resources.maxComputeWorkGroupCountX = value;
406 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
407 Resources.maxComputeWorkGroupCountY = value;
408 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
409 Resources.maxComputeWorkGroupCountZ = value;
410 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
411 Resources.maxComputeWorkGroupSizeX = value;
412 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
413 Resources.maxComputeWorkGroupSizeY = value;
414 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
415 Resources.maxComputeWorkGroupSizeZ = value;
416 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
417 Resources.maxComputeUniformComponents = value;
418 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
419 Resources.maxComputeTextureImageUnits = value;
420 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
421 Resources.maxComputeImageUniforms = value;
422 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
423 Resources.maxComputeAtomicCounters = value;
424 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
425 Resources.maxComputeAtomicCounterBuffers = value;
426 else if (strcmp(token, "MaxVaryingComponents") == 0)
427 Resources.maxVaryingComponents = value;
428 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
429 Resources.maxVertexOutputComponents = value;
430 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
431 Resources.maxGeometryInputComponents = value;
432 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
433 Resources.maxGeometryOutputComponents = value;
434 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
435 Resources.maxFragmentInputComponents = value;
436 else if (strcmp(token, "MaxImageUnits") == 0)
437 Resources.maxImageUnits = value;
438 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
439 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
440 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
441 Resources.maxCombinedShaderOutputResources = value;
442 else if (strcmp(token, "MaxImageSamples") == 0)
443 Resources.maxImageSamples = value;
444 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
445 Resources.maxVertexImageUniforms = value;
446 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
447 Resources.maxTessControlImageUniforms = value;
448 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
449 Resources.maxTessEvaluationImageUniforms = value;
450 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
451 Resources.maxGeometryImageUniforms = value;
452 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
453 Resources.maxFragmentImageUniforms = value;
454 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
455 Resources.maxCombinedImageUniforms = value;
456 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
457 Resources.maxGeometryTextureImageUnits = value;
458 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
459 Resources.maxGeometryOutputVertices = value;
460 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
461 Resources.maxGeometryTotalOutputComponents = value;
462 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
463 Resources.maxGeometryUniformComponents = value;
464 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
465 Resources.maxGeometryVaryingComponents = value;
466 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
467 Resources.maxTessControlInputComponents = value;
468 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
469 Resources.maxTessControlOutputComponents = value;
470 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
471 Resources.maxTessControlTextureImageUnits = value;
472 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
473 Resources.maxTessControlUniformComponents = value;
474 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
475 Resources.maxTessControlTotalOutputComponents = value;
476 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
477 Resources.maxTessEvaluationInputComponents = value;
478 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
479 Resources.maxTessEvaluationOutputComponents = value;
480 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
481 Resources.maxTessEvaluationTextureImageUnits = value;
482 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
483 Resources.maxTessEvaluationUniformComponents = value;
484 else if (strcmp(token, "MaxTessPatchComponents") == 0)
485 Resources.maxTessPatchComponents = value;
486 else if (strcmp(token, "MaxPatchVertices") == 0)
487 Resources.maxPatchVertices = value;
488 else if (strcmp(token, "MaxTessGenLevel") == 0)
489 Resources.maxTessGenLevel = value;
490 else if (strcmp(token, "MaxViewports") == 0)
491 Resources.maxViewports = value;
492 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
493 Resources.maxVertexAtomicCounters = value;
494 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
495 Resources.maxTessControlAtomicCounters = value;
496 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
497 Resources.maxTessEvaluationAtomicCounters = value;
498 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
499 Resources.maxGeometryAtomicCounters = value;
500 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
501 Resources.maxFragmentAtomicCounters = value;
502 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
503 Resources.maxCombinedAtomicCounters = value;
504 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
505 Resources.maxAtomicCounterBindings = value;
506 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
507 Resources.maxVertexAtomicCounterBuffers = value;
508 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
509 Resources.maxTessControlAtomicCounterBuffers = value;
510 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
511 Resources.maxTessEvaluationAtomicCounterBuffers = value;
512 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
513 Resources.maxGeometryAtomicCounterBuffers = value;
514 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
515 Resources.maxFragmentAtomicCounterBuffers = value;
516 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
517 Resources.maxCombinedAtomicCounterBuffers = value;
518 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
519 Resources.maxAtomicCounterBufferSize = value;
520 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
521 Resources.maxTransformFeedbackBuffers = value;
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600522 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600523 Resources.maxTransformFeedbackInterleavedComponents = value;
524 else if (strcmp(token, "MaxCullDistances") == 0)
525 Resources.maxCullDistances = value;
526 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
527 Resources.maxCombinedClipAndCullDistances = value;
528 else if (strcmp(token, "MaxSamples") == 0)
529 Resources.maxSamples = value;
530
531 else if (strcmp(token, "nonInductiveForLoops") == 0)
532 Resources.limits.nonInductiveForLoops = (value != 0);
533 else if (strcmp(token, "whileLoops") == 0)
534 Resources.limits.whileLoops = (value != 0);
535 else if (strcmp(token, "doWhileLoops") == 0)
536 Resources.limits.doWhileLoops = (value != 0);
537 else if (strcmp(token, "generalUniformIndexing") == 0)
538 Resources.limits.generalUniformIndexing = (value != 0);
539 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600540 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600541 else if (strcmp(token, "generalVaryingIndexing") == 0)
542 Resources.limits.generalVaryingIndexing = (value != 0);
543 else if (strcmp(token, "generalSamplerIndexing") == 0)
544 Resources.limits.generalSamplerIndexing = (value != 0);
545 else if (strcmp(token, "generalVariableIndexing") == 0)
546 Resources.limits.generalVariableIndexing = (value != 0);
547 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
548 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
549 else
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600550 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600551
552 token = strtok(0, delims);
553 }
554 if (configStrings)
555 FreeFileData(configStrings);
556}
557
Karl Schultz6addd812016-02-02 17:17:23 -0700558void VkTestFramework::SetMessageOptions(EShMessages &messages) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600559 if (m_compile_options & EOptionRelaxedErrors)
560 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
561 if (m_compile_options & EOptionIntermediate)
562 messages = (EShMessages)(messages | EShMsgAST);
563 if (m_compile_options & EOptionSuppressWarnings)
564 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
565}
566
567//
568// Malloc a string of sufficient size and read a string into it.
569//
Karl Schultz6addd812016-02-02 17:17:23 -0700570char **VkTestFramework::ReadFileData(const char *fileName) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600571 FILE *in;
Karl Schultz6addd812016-02-02 17:17:23 -0700572#if defined(_WIN32) && defined(__GNUC__)
573 in = fopen(fileName, "r");
574 int errorCode = in ? 0 : 1;
575#else
576 int errorCode = fopen_s(&in, fileName, "r");
577#endif
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600578
579 char *fdata;
Jeremy Hayes3b2a3a32016-06-21 11:05:08 -0600580 size_t count = 0;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600581 const int maxSourceStrings = 5;
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600582 char **return_data = (char **)malloc(sizeof(char *) * (maxSourceStrings + 1));
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600583
584 if (errorCode) {
585 printf("Error: unable to open input file: %s\n", fileName);
586 return 0;
587 }
588
589 while (fgetc(in) != EOF)
590 count++;
591
592 fseek(in, 0, SEEK_SET);
593
Karl Schultz6addd812016-02-02 17:17:23 -0700594 if (!(fdata = (char *)malloc(count + 2))) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600595 printf("Error allocating memory\n");
596 return 0;
597 }
Karl Schultz6addd812016-02-02 17:17:23 -0700598 if (fread(fdata, 1, count, in) != count) {
599 printf("Error reading input file: %s\n", fileName);
600 return 0;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600601 }
602 fdata[count] = '\0';
603 fclose(in);
604 if (count == 0) {
Karl Schultz6addd812016-02-02 17:17:23 -0700605 return_data[0] = (char *)malloc(count + 2);
606 return_data[0][0] = '\0';
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600607 m_num_shader_strings = 0;
608 return return_data;
609 } else
610 m_num_shader_strings = 1;
611
Jeremy Hayes3b2a3a32016-06-21 11:05:08 -0600612 size_t len = (int)(ceil)((float)count / (float)m_num_shader_strings);
613 size_t ptr_len = 0, i = 0;
Karl Schultz6addd812016-02-02 17:17:23 -0700614 while (count > 0) {
615 return_data[i] = (char *)malloc(len + 2);
616 memcpy(return_data[i], fdata + ptr_len, len);
617 return_data[i][len] = '\0';
618 count -= (len);
619 ptr_len += (len);
620 if (count < len) {
621 if (count == 0) {
622 m_num_shader_strings = (i + 1);
623 break;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600624 }
Karl Schultz6addd812016-02-02 17:17:23 -0700625 len = count;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600626 }
627 ++i;
628 }
629 return return_data;
630}
631
Karl Schultz6addd812016-02-02 17:17:23 -0700632void VkTestFramework::FreeFileData(char **data) {
633 for (int i = 0; i < m_num_shader_strings; i++)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600634 free(data[i]);
635}
636
637//
638// Deduce the language from the filename. Files must end in one of the
639// following extensions:
640//
641// .vert = vertex
642// .tesc = tessellation control
643// .tese = tessellation evaluation
644// .geom = geometry
645// .frag = fragment
646// .comp = compute
647//
Karl Schultz6addd812016-02-02 17:17:23 -0700648EShLanguage VkTestFramework::FindLanguage(const std::string &name) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600649 size_t ext = name.rfind('.');
650 if (ext == std::string::npos) {
651 return EShLangVertex;
652 }
653
654 std::string suffix = name.substr(ext + 1, std::string::npos);
655 if (suffix == "vert")
656 return EShLangVertex;
657 else if (suffix == "tesc")
658 return EShLangTessControl;
659 else if (suffix == "tese")
660 return EShLangTessEvaluation;
661 else if (suffix == "geom")
662 return EShLangGeometry;
663 else if (suffix == "frag")
664 return EShLangFragment;
665 else if (suffix == "comp")
666 return EShLangCompute;
667
668 return EShLangVertex;
669}
670
671//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600672// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600673//
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600674EShLanguage VkTestFramework::FindLanguage(const VkShaderStageFlagBits shader_type) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600675 switch (shader_type) {
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600676 case VK_SHADER_STAGE_VERTEX_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600677 return EShLangVertex;
678
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600679 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600680 return EShLangTessControl;
681
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600682 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600683 return EShLangTessEvaluation;
684
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600685 case VK_SHADER_STAGE_GEOMETRY_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600686 return EShLangGeometry;
687
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600688 case VK_SHADER_STAGE_FRAGMENT_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600689 return EShLangFragment;
690
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600691 case VK_SHADER_STAGE_COMPUTE_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600692 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600693
Chia-I Wub4c2aa42014-12-15 23:50:11 +0800694 default:
695 return EShLangVertex;
696 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600697}
698
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600699//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600700// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600701// Return value of false means an error was encountered.
702//
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600703bool VkTestFramework::GLSLtoSPV(const VkShaderStageFlagBits shader_type, const char *pshader, std::vector<unsigned int> &spirv) {
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -0600704 glslang::TProgram program;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600705 const char *shaderStrings[1];
706
707 // TODO: Do we want to load a special config file depending on the
708 // shader source? Optional name maybe?
709 // SetConfigFile(fileName);
710
711 ProcessConfigFile();
712
713 EShMessages messages = EShMsgDefault;
714 SetMessageOptions(messages);
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600715 messages = static_cast<EShMessages>(messages | EShMsgSpvRules | EShMsgVulkanRules);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600716
717 EShLanguage stage = FindLanguage(shader_type);
Karl Schultz6addd812016-02-02 17:17:23 -0700718 glslang::TShader *shader = new glslang::TShader(stage);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600719
720 shaderStrings[0] = pshader;
721 shader->setStrings(shaderStrings, 1);
722
Mark Lobodzinskic6a62142016-09-07 16:35:55 -0600723 if (!shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600724
Karl Schultz6addd812016-02-02 17:17:23 -0700725 if (!(m_compile_options & EOptionSuppressInfolog)) {
Cody Northrop195d6622014-11-03 12:54:37 -0700726 puts(shader->getInfoLog());
727 puts(shader->getInfoDebugLog());
728 }
729
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600730 return false; // something didn't work
731 }
732
733 program.addShader(shader);
734
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600735 //
736 // Program-level processing...
737 //
738
Karl Schultz6addd812016-02-02 17:17:23 -0700739 if (!program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600740
Karl Schultz6addd812016-02-02 17:17:23 -0700741 if (!(m_compile_options & EOptionSuppressInfolog)) {
Cody Northrop195d6622014-11-03 12:54:37 -0700742 puts(shader->getInfoLog());
743 puts(shader->getInfoDebugLog());
744 }
745
746 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600747 }
748
749 if (m_compile_options & EOptionDumpReflection) {
750 program.buildReflection();
751 program.dumpReflection();
752 }
753
Cody Northrop5a95b472015-06-03 13:01:54 -0600754 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
755
756 //
757 // Test the different modes of SPIR-V modification
758 //
759 if (this->m_canonicalize_spv) {
760 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
761 }
762
763 if (this->m_strip_spv) {
764 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
765 }
766
767 if (this->m_do_everything_spv) {
768 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
769 }
770
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -0600771 delete shader;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600772
773 return true;
774}