blob: 3323cf46f8933f0ae1ce0204c50ebbc80f32e951 [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
Karl Schultz6addd812016-02-02 17:17:23 -070037#define ERR_EXIT(err_msg, err_class) \
38 do { \
39 MessageBox(NULL, err_msg, err_class, MB_OK); \
40 exit(1); \
41 } while (0)
42#else // _WIN32
Tony Barbour6a3faf02015-07-23 10:36:18 -060043
Karl Schultz6addd812016-02-02 17:17:23 -070044#define ERR_EXIT(err_msg, err_class) \
45 do { \
46 printf(err_msg); \
47 fflush(stdout); \
48 exit(1); \
49 } while (0)
Tony Barbour6a3faf02015-07-23 10:36:18 -060050#endif // _WIN32
51
Karl Schultz6addd812016-02-02 17:17:23 -070052#define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \
53 { \
54 m_fp##entrypoint = \
55 (PFN_vk##entrypoint)vkGetInstanceProcAddr(inst, "vk" #entrypoint); \
56 if (m_fp##entrypoint == NULL) { \
57 ERR_EXIT("vkGetInstanceProcAddr failed to find vk" #entrypoint, \
58 "vkGetInstanceProcAddr Failure"); \
59 } \
60 }
Tony Barbour6a3faf02015-07-23 10:36:18 -060061
Karl Schultz6addd812016-02-02 17:17:23 -070062#define GET_DEVICE_PROC_ADDR(dev, entrypoint) \
63 { \
64 m_fp##entrypoint = \
65 (PFN_vk##entrypoint)vkGetDeviceProcAddr(dev, "vk" #entrypoint); \
66 if (m_fp##entrypoint == NULL) { \
67 ERR_EXIT("vkGetDeviceProcAddr failed to find vk" #entrypoint, \
68 "vkGetDeviceProcAddr Failure"); \
69 } \
70 }
Tony Barbour6a3faf02015-07-23 10:36:18 -060071
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060072// Command-line options
73enum TOptions {
Karl Schultz6addd812016-02-02 17:17:23 -070074 EOptionNone = 0x000,
75 EOptionIntermediate = 0x001,
76 EOptionSuppressInfolog = 0x002,
77 EOptionMemoryLeakMode = 0x004,
78 EOptionRelaxedErrors = 0x008,
79 EOptionGiveWarnings = 0x010,
80 EOptionLinkProgram = 0x020,
81 EOptionMultiThreaded = 0x040,
82 EOptionDumpConfig = 0x080,
83 EOptionDumpReflection = 0x100,
84 EOptionSuppressWarnings = 0x200,
85 EOptionDumpVersions = 0x400,
86 EOptionSpv = 0x800,
87 EOptionDefaultDesktop = 0x1000,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060088};
89
Mark Lobodzinskib5ccf3f2016-05-19 17:26:51 -060090struct SwapchainBuffers {
Tony Barbour6a3faf02015-07-23 10:36:18 -060091 VkImage image;
Chia-I Wu3432a0c2015-10-27 18:04:07 +080092 VkCommandBuffer cmd;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -060093 VkImageView view;
Mark Lobodzinskib5ccf3f2016-05-19 17:26:51 -060094};
Tony Barbour6a3faf02015-07-23 10:36:18 -060095
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060096#ifndef _WIN32
97
98#include <errno.h>
99
Karl Schultz6addd812016-02-02 17:17:23 -0700100int fopen_s(FILE **pFile, const char *filename, const char *mode) {
101 if (!pFile || !filename || !mode) {
102 return EINVAL;
103 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600104
Karl Schultz6addd812016-02-02 17:17:23 -0700105 FILE *f = fopen(filename, mode);
106 if (!f) {
107 if (errno != 0) {
108 return errno;
109 } else {
110 return ENOENT;
111 }
112 }
113 *pFile = f;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600114
Karl Schultz6addd812016-02-02 17:17:23 -0700115 return 0;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600116}
117
118#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600119
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600120// Set up environment for GLSL compiler
121// Must be done once per process
Karl Schultz6addd812016-02-02 17:17:23 -0700122void TestEnvironment::SetUp() {
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600123 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600124 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800125
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600126 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600127}
128
Karl Schultz6addd812016-02-02 17:17:23 -0700129void TestEnvironment::TearDown() { glslang::FinalizeProcess(); }
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600130
Karl Schultz6addd812016-02-02 17:17:23 -0700131VkTestFramework::VkTestFramework()
132 : m_compile_options(0), m_num_shader_strings(0) {}
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600133
Karl Schultz6addd812016-02-02 17:17:23 -0700134VkTestFramework::~VkTestFramework() {}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600135
136// Define all the static elements
Karl Schultz6addd812016-02-02 17:17:23 -0700137bool VkTestFramework::m_use_glsl = false;
138bool VkTestFramework::m_canonicalize_spv = false;
139bool VkTestFramework::m_strip_spv = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600140bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour6918cd52015-04-09 12:58:51 -0600141int VkTestFramework::m_width = 0;
142int VkTestFramework::m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600143
Karl Schultz6addd812016-02-02 17:17:23 -0700144bool VkTestFramework::optionMatch(const char *option, char *optionLine) {
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600145 if (strncmp(option, optionLine, strlen(option)) == 0)
146 return true;
147 else
148 return false;
149}
150
Karl Schultz6addd812016-02-02 17:17:23 -0700151void VkTestFramework::InitArgs(int *argc, char *argv[]) {
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600152 int i, n;
153
Karl Schultz6addd812016-02-02 17:17:23 -0700154 for (i = 1, n = 1; i < *argc; i++) {
Tony Barbour7b60e492016-02-02 14:43:55 -0700155 if (optionMatch("--no-SPV", argv[i]))
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600156 m_use_glsl = true;
157 else if (optionMatch("--strip-SPV", argv[i]))
Tony Barbour7b60e492016-02-02 14:43:55 -0700158 m_strip_spv = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600159 else if (optionMatch("--canonicalize-SPV", argv[i]))
160 m_canonicalize_spv = true;
Karl Schultz6addd812016-02-02 17:17:23 -0700161 else if (optionMatch("--help", argv[i]) || optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700162 printf("\nOther options:\n");
163 printf("\t--show-images\n"
164 "\t\tDisplay test images in viewer after tests complete.\n");
165 printf("\t--save-images\n"
Karl Schultz6addd812016-02-02 17:17:23 -0700166 "\t\tSave tests images as ppm files in current working "
167 "directory.\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700168 "\t\tUsed to generate golden images for compare-images.\n");
Karl Schultz6addd812016-02-02 17:17:23 -0700169 printf(
170 "\t--compare-images\n"
171 "\t\tCompare test images to 'golden' image in golden folder.\n"
172 "\t\tAlso saves the generated test image in current working\n"
173 "\t\t\tdirectory but only if the image is different from the "
174 "golden\n"
175 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can "
176 "specify\n"
177 "\t\t\tdifferent directory for golden images\n"
178 "\t\tSignal test failure if different.\n");
179 printf(
180 "\t--no-SPV\n"
181 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600182 printf("\t--strip-SPV\n"
Karl Schultz6addd812016-02-02 17:17:23 -0700183 "\t\tStrip SPIR-V debug information (line numbers, names, "
184 "etc).\n");
185 printf(
186 "\t--canonicalize-SPV\n"
187 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600188 exit(0);
189 } else {
190 printf("\nUnrecognized option: %s\n", argv[i]);
191 printf("\nUse --help or -h for option list.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700192 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700193 }
194
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600195 /*
196 * Since the above "consume" inputs, update argv
197 * so that it contains the trimmed list of args for glutInit
198 */
199
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600200 argv[n] = argv[i];
201 n++;
202 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600203}
204
Karl Schultz6addd812016-02-02 17:17:23 -0700205VkFormat VkTestFramework::GetFormat(VkInstance instance,
206 vk_testing::Device *device) {
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700207 VkFormatProperties format_props;
Tony Barbour7b60e492016-02-02 14:43:55 -0700208
Karl Schultz6addd812016-02-02 17:17:23 -0700209 vkGetPhysicalDeviceFormatProperties(
210 device->phy().handle(), VK_FORMAT_B8G8R8A8_UNORM, &format_props);
211 if (format_props.linearTilingFeatures &
212 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ||
213 format_props.optimalTilingFeatures &
214 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) {
Tony Barbour7b60e492016-02-02 14:43:55 -0700215 return VK_FORMAT_B8G8R8A8_UNORM;
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700216 }
Karl Schultz6addd812016-02-02 17:17:23 -0700217 vkGetPhysicalDeviceFormatProperties(
218 device->phy().handle(), VK_FORMAT_R8G8B8A8_UNORM, &format_props);
219 if (format_props.linearTilingFeatures &
220 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ||
221 format_props.optimalTilingFeatures &
222 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) {
Tony Barbour7b60e492016-02-02 14:43:55 -0700223 return VK_FORMAT_R8G8B8A8_UNORM;
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700224 }
Karl Schultz6addd812016-02-02 17:17:23 -0700225 printf("Error - device does not support VK_FORMAT_B8G8R8A8_UNORM nor "
226 "VK_FORMAT_R8G8B8A8_UNORM - exiting\n");
Tony Barbour7b60e492016-02-02 14:43:55 -0700227 exit(0);
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700228}
229
Karl Schultz6addd812016-02-02 17:17:23 -0700230void VkTestFramework::Finish() {}
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600231
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600232//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600233// These are the default resources for TBuiltInResources, used for both
234// - parsing this string for the case where the user didn't supply one
235// - dumping out a template for user construction of a config file
236//
Karl Schultz6addd812016-02-02 17:17:23 -0700237static const char *DefaultConfig =
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600238 "MaxLights 32\n"
239 "MaxClipPlanes 6\n"
240 "MaxTextureUnits 32\n"
241 "MaxTextureCoords 32\n"
242 "MaxVertexAttribs 64\n"
243 "MaxVertexUniformComponents 4096\n"
244 "MaxVaryingFloats 64\n"
245 "MaxVertexTextureImageUnits 32\n"
246 "MaxCombinedTextureImageUnits 80\n"
247 "MaxTextureImageUnits 32\n"
248 "MaxFragmentUniformComponents 4096\n"
249 "MaxDrawBuffers 32\n"
250 "MaxVertexUniformVectors 128\n"
251 "MaxVaryingVectors 8\n"
252 "MaxFragmentUniformVectors 16\n"
253 "MaxVertexOutputVectors 16\n"
254 "MaxFragmentInputVectors 15\n"
255 "MinProgramTexelOffset -8\n"
256 "MaxProgramTexelOffset 7\n"
257 "MaxClipDistances 8\n"
258 "MaxComputeWorkGroupCountX 65535\n"
259 "MaxComputeWorkGroupCountY 65535\n"
260 "MaxComputeWorkGroupCountZ 65535\n"
261 "MaxComputeWorkGroupSizeX 1024\n"
262 "MaxComputeWorkGroupSizeY 1024\n"
263 "MaxComputeWorkGroupSizeZ 64\n"
264 "MaxComputeUniformComponents 1024\n"
265 "MaxComputeTextureImageUnits 16\n"
266 "MaxComputeImageUniforms 8\n"
267 "MaxComputeAtomicCounters 8\n"
268 "MaxComputeAtomicCounterBuffers 1\n"
269 "MaxVaryingComponents 60\n"
270 "MaxVertexOutputComponents 64\n"
271 "MaxGeometryInputComponents 64\n"
272 "MaxGeometryOutputComponents 128\n"
273 "MaxFragmentInputComponents 128\n"
274 "MaxImageUnits 8\n"
275 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
276 "MaxCombinedShaderOutputResources 8\n"
277 "MaxImageSamples 0\n"
278 "MaxVertexImageUniforms 0\n"
279 "MaxTessControlImageUniforms 0\n"
280 "MaxTessEvaluationImageUniforms 0\n"
281 "MaxGeometryImageUniforms 0\n"
282 "MaxFragmentImageUniforms 8\n"
283 "MaxCombinedImageUniforms 8\n"
284 "MaxGeometryTextureImageUnits 16\n"
285 "MaxGeometryOutputVertices 256\n"
286 "MaxGeometryTotalOutputComponents 1024\n"
287 "MaxGeometryUniformComponents 1024\n"
288 "MaxGeometryVaryingComponents 64\n"
289 "MaxTessControlInputComponents 128\n"
290 "MaxTessControlOutputComponents 128\n"
291 "MaxTessControlTextureImageUnits 16\n"
292 "MaxTessControlUniformComponents 1024\n"
293 "MaxTessControlTotalOutputComponents 4096\n"
294 "MaxTessEvaluationInputComponents 128\n"
295 "MaxTessEvaluationOutputComponents 128\n"
296 "MaxTessEvaluationTextureImageUnits 16\n"
297 "MaxTessEvaluationUniformComponents 1024\n"
298 "MaxTessPatchComponents 120\n"
299 "MaxPatchVertices 32\n"
300 "MaxTessGenLevel 64\n"
301 "MaxViewports 16\n"
302 "MaxVertexAtomicCounters 0\n"
303 "MaxTessControlAtomicCounters 0\n"
304 "MaxTessEvaluationAtomicCounters 0\n"
305 "MaxGeometryAtomicCounters 0\n"
306 "MaxFragmentAtomicCounters 8\n"
307 "MaxCombinedAtomicCounters 8\n"
308 "MaxAtomicCounterBindings 1\n"
309 "MaxVertexAtomicCounterBuffers 0\n"
310 "MaxTessControlAtomicCounterBuffers 0\n"
311 "MaxTessEvaluationAtomicCounterBuffers 0\n"
312 "MaxGeometryAtomicCounterBuffers 0\n"
313 "MaxFragmentAtomicCounterBuffers 1\n"
314 "MaxCombinedAtomicCounterBuffers 1\n"
315 "MaxAtomicCounterBufferSize 16384\n"
316 "MaxTransformFeedbackBuffers 4\n"
317 "MaxTransformFeedbackInterleavedComponents 64\n"
318 "MaxCullDistances 8\n"
319 "MaxCombinedClipAndCullDistances 8\n"
320 "MaxSamples 4\n"
321
322 "nonInductiveForLoops 1\n"
323 "whileLoops 1\n"
324 "doWhileLoops 1\n"
325 "generalUniformIndexing 1\n"
326 "generalAttributeMatrixVectorIndexing 1\n"
327 "generalVaryingIndexing 1\n"
328 "generalSamplerIndexing 1\n"
329 "generalVariableIndexing 1\n"
Karl Schultz6addd812016-02-02 17:17:23 -0700330 "generalConstantMatrixVectorIndexing 1\n";
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600331
332//
333// *.conf => this is a config file that can set limits/resources
334//
Karl Schultz6addd812016-02-02 17:17:23 -0700335bool VkTestFramework::SetConfigFile(const std::string &name) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600336 if (name.size() < 5)
337 return false;
338
339 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
340 ConfigFile = name;
341 return true;
342 }
343
344 return false;
345}
346
347//
348// Parse either a .conf file provided by the user or the default string above.
349//
Karl Schultz6addd812016-02-02 17:17:23 -0700350void VkTestFramework::ProcessConfigFile() {
351 char **configStrings = 0;
352 char *config = 0;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600353 if (ConfigFile.size() > 0) {
354 configStrings = ReadFileData(ConfigFile.c_str());
355 if (configStrings)
356 config = *configStrings;
357 else {
Karl Schultz6addd812016-02-02 17:17:23 -0700358 printf("Error opening configuration file; will instead use the "
359 "default configuration\n");
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600360 }
361 }
362
363 if (config == 0) {
Karl Schultz6addd812016-02-02 17:17:23 -0700364 config = (char *)alloca(strlen(DefaultConfig) + 1);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600365 strcpy(config, DefaultConfig);
366 }
367
Karl Schultz6addd812016-02-02 17:17:23 -0700368 const char *delims = " \t\n\r";
369 const char *token = strtok(config, delims);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600370 while (token) {
Karl Schultz6addd812016-02-02 17:17:23 -0700371 const char *valueStr = strtok(0, delims);
372 if (valueStr == 0 ||
373 !(valueStr[0] == '-' ||
374 (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
375 printf("Error: '%s' bad .conf file. Each name must be followed by "
376 "one number.\n",
377 valueStr ? valueStr : "");
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600378 return;
379 }
380 int value = atoi(valueStr);
381
382 if (strcmp(token, "MaxLights") == 0)
383 Resources.maxLights = value;
384 else if (strcmp(token, "MaxClipPlanes") == 0)
385 Resources.maxClipPlanes = value;
386 else if (strcmp(token, "MaxTextureUnits") == 0)
387 Resources.maxTextureUnits = value;
388 else if (strcmp(token, "MaxTextureCoords") == 0)
389 Resources.maxTextureCoords = value;
390 else if (strcmp(token, "MaxVertexAttribs") == 0)
391 Resources.maxVertexAttribs = value;
392 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
393 Resources.maxVertexUniformComponents = value;
394 else if (strcmp(token, "MaxVaryingFloats") == 0)
395 Resources.maxVaryingFloats = value;
396 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
397 Resources.maxVertexTextureImageUnits = value;
398 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
399 Resources.maxCombinedTextureImageUnits = value;
400 else if (strcmp(token, "MaxTextureImageUnits") == 0)
401 Resources.maxTextureImageUnits = value;
402 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
403 Resources.maxFragmentUniformComponents = value;
404 else if (strcmp(token, "MaxDrawBuffers") == 0)
405 Resources.maxDrawBuffers = value;
406 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
407 Resources.maxVertexUniformVectors = value;
408 else if (strcmp(token, "MaxVaryingVectors") == 0)
409 Resources.maxVaryingVectors = value;
410 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
411 Resources.maxFragmentUniformVectors = value;
412 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
413 Resources.maxVertexOutputVectors = value;
414 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
415 Resources.maxFragmentInputVectors = value;
416 else if (strcmp(token, "MinProgramTexelOffset") == 0)
417 Resources.minProgramTexelOffset = value;
418 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
419 Resources.maxProgramTexelOffset = value;
420 else if (strcmp(token, "MaxClipDistances") == 0)
421 Resources.maxClipDistances = value;
422 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
423 Resources.maxComputeWorkGroupCountX = value;
424 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
425 Resources.maxComputeWorkGroupCountY = value;
426 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
427 Resources.maxComputeWorkGroupCountZ = value;
428 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
429 Resources.maxComputeWorkGroupSizeX = value;
430 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
431 Resources.maxComputeWorkGroupSizeY = value;
432 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
433 Resources.maxComputeWorkGroupSizeZ = value;
434 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
435 Resources.maxComputeUniformComponents = value;
436 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
437 Resources.maxComputeTextureImageUnits = value;
438 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
439 Resources.maxComputeImageUniforms = value;
440 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
441 Resources.maxComputeAtomicCounters = value;
442 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
443 Resources.maxComputeAtomicCounterBuffers = value;
444 else if (strcmp(token, "MaxVaryingComponents") == 0)
445 Resources.maxVaryingComponents = value;
446 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
447 Resources.maxVertexOutputComponents = value;
448 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
449 Resources.maxGeometryInputComponents = value;
450 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
451 Resources.maxGeometryOutputComponents = value;
452 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
453 Resources.maxFragmentInputComponents = value;
454 else if (strcmp(token, "MaxImageUnits") == 0)
455 Resources.maxImageUnits = value;
456 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
457 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
458 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
459 Resources.maxCombinedShaderOutputResources = value;
460 else if (strcmp(token, "MaxImageSamples") == 0)
461 Resources.maxImageSamples = value;
462 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
463 Resources.maxVertexImageUniforms = value;
464 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
465 Resources.maxTessControlImageUniforms = value;
466 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
467 Resources.maxTessEvaluationImageUniforms = value;
468 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
469 Resources.maxGeometryImageUniforms = value;
470 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
471 Resources.maxFragmentImageUniforms = value;
472 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
473 Resources.maxCombinedImageUniforms = value;
474 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
475 Resources.maxGeometryTextureImageUnits = value;
476 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
477 Resources.maxGeometryOutputVertices = value;
478 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
479 Resources.maxGeometryTotalOutputComponents = value;
480 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
481 Resources.maxGeometryUniformComponents = value;
482 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
483 Resources.maxGeometryVaryingComponents = value;
484 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
485 Resources.maxTessControlInputComponents = value;
486 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
487 Resources.maxTessControlOutputComponents = value;
488 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
489 Resources.maxTessControlTextureImageUnits = value;
490 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
491 Resources.maxTessControlUniformComponents = value;
492 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
493 Resources.maxTessControlTotalOutputComponents = value;
494 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
495 Resources.maxTessEvaluationInputComponents = value;
496 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
497 Resources.maxTessEvaluationOutputComponents = value;
498 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
499 Resources.maxTessEvaluationTextureImageUnits = value;
500 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
501 Resources.maxTessEvaluationUniformComponents = value;
502 else if (strcmp(token, "MaxTessPatchComponents") == 0)
503 Resources.maxTessPatchComponents = value;
504 else if (strcmp(token, "MaxPatchVertices") == 0)
505 Resources.maxPatchVertices = value;
506 else if (strcmp(token, "MaxTessGenLevel") == 0)
507 Resources.maxTessGenLevel = value;
508 else if (strcmp(token, "MaxViewports") == 0)
509 Resources.maxViewports = value;
510 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
511 Resources.maxVertexAtomicCounters = value;
512 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
513 Resources.maxTessControlAtomicCounters = value;
514 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
515 Resources.maxTessEvaluationAtomicCounters = value;
516 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
517 Resources.maxGeometryAtomicCounters = value;
518 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
519 Resources.maxFragmentAtomicCounters = value;
520 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
521 Resources.maxCombinedAtomicCounters = value;
522 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
523 Resources.maxAtomicCounterBindings = value;
524 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
525 Resources.maxVertexAtomicCounterBuffers = value;
526 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
527 Resources.maxTessControlAtomicCounterBuffers = value;
528 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
529 Resources.maxTessEvaluationAtomicCounterBuffers = value;
530 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
531 Resources.maxGeometryAtomicCounterBuffers = value;
532 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
533 Resources.maxFragmentAtomicCounterBuffers = value;
534 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
535 Resources.maxCombinedAtomicCounterBuffers = value;
536 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
537 Resources.maxAtomicCounterBufferSize = value;
538 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
539 Resources.maxTransformFeedbackBuffers = value;
Karl Schultz6addd812016-02-02 17:17:23 -0700540 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") ==
541 0)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600542 Resources.maxTransformFeedbackInterleavedComponents = value;
543 else if (strcmp(token, "MaxCullDistances") == 0)
544 Resources.maxCullDistances = value;
545 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
546 Resources.maxCombinedClipAndCullDistances = value;
547 else if (strcmp(token, "MaxSamples") == 0)
548 Resources.maxSamples = value;
549
550 else if (strcmp(token, "nonInductiveForLoops") == 0)
551 Resources.limits.nonInductiveForLoops = (value != 0);
552 else if (strcmp(token, "whileLoops") == 0)
553 Resources.limits.whileLoops = (value != 0);
554 else if (strcmp(token, "doWhileLoops") == 0)
555 Resources.limits.doWhileLoops = (value != 0);
556 else if (strcmp(token, "generalUniformIndexing") == 0)
557 Resources.limits.generalUniformIndexing = (value != 0);
558 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
Karl Schultz6addd812016-02-02 17:17:23 -0700559 Resources.limits.generalAttributeMatrixVectorIndexing =
560 (value != 0);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600561 else if (strcmp(token, "generalVaryingIndexing") == 0)
562 Resources.limits.generalVaryingIndexing = (value != 0);
563 else if (strcmp(token, "generalSamplerIndexing") == 0)
564 Resources.limits.generalSamplerIndexing = (value != 0);
565 else if (strcmp(token, "generalVariableIndexing") == 0)
566 Resources.limits.generalVariableIndexing = (value != 0);
567 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
568 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
569 else
Karl Schultz6addd812016-02-02 17:17:23 -0700570 printf("Warning: unrecognized limit (%s) in configuration file.\n",
571 token);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600572
573 token = strtok(0, delims);
574 }
575 if (configStrings)
576 FreeFileData(configStrings);
577}
578
Karl Schultz6addd812016-02-02 17:17:23 -0700579void VkTestFramework::SetMessageOptions(EShMessages &messages) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600580 if (m_compile_options & EOptionRelaxedErrors)
581 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
582 if (m_compile_options & EOptionIntermediate)
583 messages = (EShMessages)(messages | EShMsgAST);
584 if (m_compile_options & EOptionSuppressWarnings)
585 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
586}
587
588//
589// Malloc a string of sufficient size and read a string into it.
590//
Karl Schultz6addd812016-02-02 17:17:23 -0700591char **VkTestFramework::ReadFileData(const char *fileName) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600592 FILE *in;
Karl Schultz6addd812016-02-02 17:17:23 -0700593#if defined(_WIN32) && defined(__GNUC__)
594 in = fopen(fileName, "r");
595 int errorCode = in ? 0 : 1;
596#else
597 int errorCode = fopen_s(&in, fileName, "r");
598#endif
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600599
600 char *fdata;
Jeremy Hayes3b2a3a32016-06-21 11:05:08 -0600601 size_t count = 0;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600602 const int maxSourceStrings = 5;
Karl Schultz6addd812016-02-02 17:17:23 -0700603 char **return_data =
604 (char **)malloc(sizeof(char *) * (maxSourceStrings + 1));
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600605
606 if (errorCode) {
607 printf("Error: unable to open input file: %s\n", fileName);
608 return 0;
609 }
610
611 while (fgetc(in) != EOF)
612 count++;
613
614 fseek(in, 0, SEEK_SET);
615
Karl Schultz6addd812016-02-02 17:17:23 -0700616 if (!(fdata = (char *)malloc(count + 2))) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600617 printf("Error allocating memory\n");
618 return 0;
619 }
Karl Schultz6addd812016-02-02 17:17:23 -0700620 if (fread(fdata, 1, count, in) != count) {
621 printf("Error reading input file: %s\n", fileName);
622 return 0;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600623 }
624 fdata[count] = '\0';
625 fclose(in);
626 if (count == 0) {
Karl Schultz6addd812016-02-02 17:17:23 -0700627 return_data[0] = (char *)malloc(count + 2);
628 return_data[0][0] = '\0';
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600629 m_num_shader_strings = 0;
630 return return_data;
631 } else
632 m_num_shader_strings = 1;
633
Jeremy Hayes3b2a3a32016-06-21 11:05:08 -0600634 size_t len = (int)(ceil)((float)count / (float)m_num_shader_strings);
635 size_t ptr_len = 0, i = 0;
Karl Schultz6addd812016-02-02 17:17:23 -0700636 while (count > 0) {
637 return_data[i] = (char *)malloc(len + 2);
638 memcpy(return_data[i], fdata + ptr_len, len);
639 return_data[i][len] = '\0';
640 count -= (len);
641 ptr_len += (len);
642 if (count < len) {
643 if (count == 0) {
644 m_num_shader_strings = (i + 1);
645 break;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600646 }
Karl Schultz6addd812016-02-02 17:17:23 -0700647 len = count;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600648 }
649 ++i;
650 }
651 return return_data;
652}
653
Karl Schultz6addd812016-02-02 17:17:23 -0700654void VkTestFramework::FreeFileData(char **data) {
655 for (int i = 0; i < m_num_shader_strings; i++)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600656 free(data[i]);
657}
658
659//
660// Deduce the language from the filename. Files must end in one of the
661// following extensions:
662//
663// .vert = vertex
664// .tesc = tessellation control
665// .tese = tessellation evaluation
666// .geom = geometry
667// .frag = fragment
668// .comp = compute
669//
Karl Schultz6addd812016-02-02 17:17:23 -0700670EShLanguage VkTestFramework::FindLanguage(const std::string &name) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600671 size_t ext = name.rfind('.');
672 if (ext == std::string::npos) {
673 return EShLangVertex;
674 }
675
676 std::string suffix = name.substr(ext + 1, std::string::npos);
677 if (suffix == "vert")
678 return EShLangVertex;
679 else if (suffix == "tesc")
680 return EShLangTessControl;
681 else if (suffix == "tese")
682 return EShLangTessEvaluation;
683 else if (suffix == "geom")
684 return EShLangGeometry;
685 else if (suffix == "frag")
686 return EShLangFragment;
687 else if (suffix == "comp")
688 return EShLangCompute;
689
690 return EShLangVertex;
691}
692
693//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600694// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600695//
Karl Schultz6addd812016-02-02 17:17:23 -0700696EShLanguage
697VkTestFramework::FindLanguage(const VkShaderStageFlagBits shader_type) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600698 switch (shader_type) {
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600699 case VK_SHADER_STAGE_VERTEX_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600700 return EShLangVertex;
701
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600702 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600703 return EShLangTessControl;
704
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600705 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600706 return EShLangTessEvaluation;
707
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600708 case VK_SHADER_STAGE_GEOMETRY_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600709 return EShLangGeometry;
710
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600711 case VK_SHADER_STAGE_FRAGMENT_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600712 return EShLangFragment;
713
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600714 case VK_SHADER_STAGE_COMPUTE_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600715 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600716
Chia-I Wub4c2aa42014-12-15 23:50:11 +0800717 default:
718 return EShLangVertex;
719 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600720}
721
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600722//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600723// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600724// Return value of false means an error was encountered.
725//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600726bool VkTestFramework::GLSLtoSPV(const VkShaderStageFlagBits shader_type,
Karl Schultz6addd812016-02-02 17:17:23 -0700727 const char *pshader,
728 std::vector<unsigned int> &spirv) {
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -0600729 glslang::TProgram program;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600730 const char *shaderStrings[1];
731
732 // TODO: Do we want to load a special config file depending on the
733 // shader source? Optional name maybe?
734 // SetConfigFile(fileName);
735
736 ProcessConfigFile();
737
738 EShMessages messages = EShMsgDefault;
739 SetMessageOptions(messages);
Karl Schultz6addd812016-02-02 17:17:23 -0700740 messages =
741 static_cast<EShMessages>(messages | EShMsgSpvRules | EShMsgVulkanRules);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600742
743 EShLanguage stage = FindLanguage(shader_type);
Karl Schultz6addd812016-02-02 17:17:23 -0700744 glslang::TShader *shader = new glslang::TShader(stage);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600745
746 shaderStrings[0] = pshader;
747 shader->setStrings(shaderStrings, 1);
748
Karl Schultz6addd812016-02-02 17:17:23 -0700749 if (!shader->parse(&Resources,
750 (m_compile_options & EOptionDefaultDesktop) ? 110 : 100,
751 false, messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600752
Karl Schultz6addd812016-02-02 17:17:23 -0700753 if (!(m_compile_options & EOptionSuppressInfolog)) {
Cody Northrop195d6622014-11-03 12:54:37 -0700754 puts(shader->getInfoLog());
755 puts(shader->getInfoDebugLog());
756 }
757
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600758 return false; // something didn't work
759 }
760
761 program.addShader(shader);
762
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600763 //
764 // Program-level processing...
765 //
766
Karl Schultz6addd812016-02-02 17:17:23 -0700767 if (!program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600768
Karl Schultz6addd812016-02-02 17:17:23 -0700769 if (!(m_compile_options & EOptionSuppressInfolog)) {
Cody Northrop195d6622014-11-03 12:54:37 -0700770 puts(shader->getInfoLog());
771 puts(shader->getInfoDebugLog());
772 }
773
774 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600775 }
776
777 if (m_compile_options & EOptionDumpReflection) {
778 program.buildReflection();
779 program.dumpReflection();
780 }
781
Cody Northrop5a95b472015-06-03 13:01:54 -0600782 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
783
784 //
785 // Test the different modes of SPIR-V modification
786 //
787 if (this->m_canonicalize_spv) {
788 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
789 }
790
791 if (this->m_strip_spv) {
792 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
793 }
794
795 if (this->m_do_everything_spv) {
796 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
797 }
798
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -0600799 delete shader;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600800
801 return true;
802}