blob: 322741d933e287dd3bd129387ecb9d02a47790b5 [file] [log] [blame]
Karl Schultz99e9d1d2016-02-02 17:17:23 -07001/*
2 * Copyright (c) 2015-2016 The Khronos Group Inc.
3 * Copyright (c) 2015-2016 Valve Corporation
4 * Copyright (c) 2015-2016 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and/or associated documentation files (the "Materials"), to
8 * deal in the Materials without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Materials, and to permit persons to whom the Materials are
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice(s) and this permission notice shall be included in
14 * all copies or substantial portions of the Materials.
15 *
Karl Schultz99e9d1d2016-02-02 17:17:23 -070016 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 *
20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
23 * USE OR OTHER DEALINGS IN THE MATERIALS.
24 *
25 * Author: Chia-I Wu <olvaffe@gmail.com>
26 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
27 * Author: Tony Barbour <tony@LunarG.com>
28 */
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -060029
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060030#include "vktestframework.h"
31#include "vkrenderframework.h"
Karl Schultz99e9d1d2016-02-02 17:17:23 -070032// TODO FIXME remove this once glslang doesn't define this
Jon Ashburn7dc96302015-12-04 17:03:59 -070033#undef BadValue
Cody Northropeb9130e2015-06-03 13:01:54 -060034#include "SPIRV/GlslangToSpv.h"
35#include "SPIRV/SPVRemapper.h"
Tony Barbour772c5ef2014-12-10 17:00:20 -070036#include <limits.h>
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -060037#include <math.h>
Jon Ashburn7dc96302015-12-04 17:03:59 -070038
Tony Barbour25e3b832015-05-20 16:53:31 -060039#if defined(PATH_MAX) && !defined(MAX_PATH)
40#define MAX_PATH PATH_MAX
41#endif
42
Tony Barbourb3744222015-07-23 10:36:18 -060043#ifdef _WIN32
Karl Schultz99e9d1d2016-02-02 17:17:23 -070044#define ERR_EXIT(err_msg, err_class) \
45 do { \
46 MessageBox(NULL, err_msg, err_class, MB_OK); \
47 exit(1); \
48 } while (0)
49#else // _WIN32
Tony Barbourb3744222015-07-23 10:36:18 -060050
Karl Schultz99e9d1d2016-02-02 17:17:23 -070051#define ERR_EXIT(err_msg, err_class) \
52 do { \
53 printf(err_msg); \
54 fflush(stdout); \
55 exit(1); \
56 } while (0)
Tony Barbourb3744222015-07-23 10:36:18 -060057#endif // _WIN32
58
Karl Schultz99e9d1d2016-02-02 17:17:23 -070059#define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \
60 { \
61 m_fp##entrypoint = \
62 (PFN_vk##entrypoint)vkGetInstanceProcAddr(inst, "vk" #entrypoint); \
63 if (m_fp##entrypoint == NULL) { \
64 ERR_EXIT("vkGetInstanceProcAddr failed to find vk" #entrypoint, \
65 "vkGetInstanceProcAddr Failure"); \
66 } \
67 }
Tony Barbourb3744222015-07-23 10:36:18 -060068
Karl Schultz99e9d1d2016-02-02 17:17:23 -070069#define GET_DEVICE_PROC_ADDR(dev, entrypoint) \
70 { \
71 m_fp##entrypoint = \
72 (PFN_vk##entrypoint)vkGetDeviceProcAddr(dev, "vk" #entrypoint); \
73 if (m_fp##entrypoint == NULL) { \
74 ERR_EXIT("vkGetDeviceProcAddr failed to find vk" #entrypoint, \
75 "vkGetDeviceProcAddr Failure"); \
76 } \
77 }
Tony Barbourb3744222015-07-23 10:36:18 -060078
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -060079// Command-line options
80enum TOptions {
Karl Schultz99e9d1d2016-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 Goeltzenleuchter94192032014-10-03 09:53:32 -060095};
96
Ian Elliott338dedb2015-08-21 15:09:33 -060097typedef struct _SwapchainBuffers {
Tony Barbourb3744222015-07-23 10:36:18 -060098 VkImage image;
Chia-I Wu1f851912015-10-27 18:04:07 +080099 VkCommandBuffer cmd;
Courtney Goeltzenleuchter1856d6f2015-09-01 17:30:39 -0600100 VkImageView view;
Ian Elliott338dedb2015-08-21 15:09:33 -0600101} SwapchainBuffers;
Tony Barbourb3744222015-07-23 10:36:18 -0600102
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600103#ifndef _WIN32
104
105#include <errno.h>
106
Karl Schultz99e9d1d2016-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 Goeltzenleuchter94192032014-10-03 09:53:32 -0600111
Karl Schultz99e9d1d2016-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 Goeltzenleuchter94192032014-10-03 09:53:32 -0600121
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700122 return 0;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600123}
124
125#endif
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600126
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600127// Set up environment for GLSL compiler
128// Must be done once per process
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700129void TestEnvironment::SetUp() {
Cody Northropacfb0492015-03-17 15:55:58 -0600130 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600131 glslang::InitializeProcess();
Chia-I Wu1c9869e2014-12-28 14:27:28 +0800132
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600133 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600134}
135
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700136void TestEnvironment::TearDown() { glslang::FinalizeProcess(); }
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600137
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700138VkTestFramework::VkTestFramework()
139 : m_compile_options(0), m_num_shader_strings(0) {}
Courtney Goeltzenleuchterf12c7762014-10-08 08:46:51 -0600140
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700141VkTestFramework::~VkTestFramework() {}
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600142
143// Define all the static elements
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700144bool VkTestFramework::m_use_glsl = false;
145bool VkTestFramework::m_canonicalize_spv = false;
146bool VkTestFramework::m_strip_spv = false;
Cody Northropeb9130e2015-06-03 13:01:54 -0600147bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour01999182015-04-09 12:58:51 -0600148int VkTestFramework::m_width = 0;
149int VkTestFramework::m_height = 0;
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600150
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700151bool VkTestFramework::optionMatch(const char *option, char *optionLine) {
Cody Northrop1cfbd172015-06-03 16:49:20 -0600152 if (strncmp(option, optionLine, strlen(option)) == 0)
153 return true;
154 else
155 return false;
156}
157
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700158void VkTestFramework::InitArgs(int *argc, char *argv[]) {
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600159 int i, n;
160
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700161 for (i = 1, n = 1; i < *argc; i++) {
Tony Barbour55e270b2016-02-02 14:43:55 -0700162 if (optionMatch("--no-SPV", argv[i]))
Cody Northrop1cfbd172015-06-03 16:49:20 -0600163 m_use_glsl = true;
164 else if (optionMatch("--strip-SPV", argv[i]))
Tony Barbour55e270b2016-02-02 14:43:55 -0700165 m_strip_spv = true;
Cody Northrop1cfbd172015-06-03 16:49:20 -0600166 else if (optionMatch("--canonicalize-SPV", argv[i]))
167 m_canonicalize_spv = true;
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700168 else if (optionMatch("--help", argv[i]) || optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchterb7f26e02014-12-02 13:13:10 -0700169 printf("\nOther options:\n");
170 printf("\t--show-images\n"
171 "\t\tDisplay test images in viewer after tests complete.\n");
172 printf("\t--save-images\n"
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700173 "\t\tSave tests images as ppm files in current working "
174 "directory.\n"
Courtney Goeltzenleuchterb7f26e02014-12-02 13:13:10 -0700175 "\t\tUsed to generate golden images for compare-images.\n");
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700176 printf(
177 "\t--compare-images\n"
178 "\t\tCompare test images to 'golden' image in golden folder.\n"
179 "\t\tAlso saves the generated test image in current working\n"
180 "\t\t\tdirectory but only if the image is different from the "
181 "golden\n"
182 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can "
183 "specify\n"
184 "\t\t\tdifferent directory for golden images\n"
185 "\t\tSignal test failure if different.\n");
186 printf(
187 "\t--no-SPV\n"
188 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop1cfbd172015-06-03 16:49:20 -0600189 printf("\t--strip-SPV\n"
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700190 "\t\tStrip SPIR-V debug information (line numbers, names, "
191 "etc).\n");
192 printf(
193 "\t--canonicalize-SPV\n"
194 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
Cody Northrop1cfbd172015-06-03 16:49:20 -0600195 exit(0);
196 } else {
197 printf("\nUnrecognized option: %s\n", argv[i]);
198 printf("\nUse --help or -h for option list.\n");
Tony Barbour772c5ef2014-12-10 17:00:20 -0700199 exit(0);
Courtney Goeltzenleuchterb7f26e02014-12-02 13:13:10 -0700200 }
201
Cody Northrop1cfbd172015-06-03 16:49:20 -0600202 /*
203 * Since the above "consume" inputs, update argv
204 * so that it contains the trimmed list of args for glutInit
205 */
206
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600207 argv[n] = argv[i];
208 n++;
209 }
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600210}
211
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700212VkFormat VkTestFramework::GetFormat(VkInstance instance,
213 vk_testing::Device *device) {
Tony Barbour474e9e42015-12-03 16:05:11 -0700214 VkFormatProperties format_props;
Tony Barbour55e270b2016-02-02 14:43:55 -0700215
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700216 vkGetPhysicalDeviceFormatProperties(
217 device->phy().handle(), VK_FORMAT_B8G8R8A8_UNORM, &format_props);
218 if (format_props.linearTilingFeatures &
219 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ||
220 format_props.optimalTilingFeatures &
221 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) {
Tony Barbour55e270b2016-02-02 14:43:55 -0700222 return VK_FORMAT_B8G8R8A8_UNORM;
Tony Barbour474e9e42015-12-03 16:05:11 -0700223 }
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700224 vkGetPhysicalDeviceFormatProperties(
225 device->phy().handle(), VK_FORMAT_R8G8B8A8_UNORM, &format_props);
226 if (format_props.linearTilingFeatures &
227 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ||
228 format_props.optimalTilingFeatures &
229 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) {
Tony Barbour55e270b2016-02-02 14:43:55 -0700230 return VK_FORMAT_R8G8B8A8_UNORM;
Tony Barbour474e9e42015-12-03 16:05:11 -0700231 }
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700232 printf("Error - device does not support VK_FORMAT_B8G8R8A8_UNORM nor "
233 "VK_FORMAT_R8G8B8A8_UNORM - exiting\n");
Tony Barbour55e270b2016-02-02 14:43:55 -0700234 exit(0);
Tony Barbour474e9e42015-12-03 16:05:11 -0700235}
236
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700237void VkTestFramework::Finish() {}
Courtney Goeltzenleuchterd0d7ccc2014-09-04 16:24:19 -0600238
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600239//
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600240// These are the default resources for TBuiltInResources, used for both
241// - parsing this string for the case where the user didn't supply one
242// - dumping out a template for user construction of a config file
243//
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700244static const char *DefaultConfig =
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600245 "MaxLights 32\n"
246 "MaxClipPlanes 6\n"
247 "MaxTextureUnits 32\n"
248 "MaxTextureCoords 32\n"
249 "MaxVertexAttribs 64\n"
250 "MaxVertexUniformComponents 4096\n"
251 "MaxVaryingFloats 64\n"
252 "MaxVertexTextureImageUnits 32\n"
253 "MaxCombinedTextureImageUnits 80\n"
254 "MaxTextureImageUnits 32\n"
255 "MaxFragmentUniformComponents 4096\n"
256 "MaxDrawBuffers 32\n"
257 "MaxVertexUniformVectors 128\n"
258 "MaxVaryingVectors 8\n"
259 "MaxFragmentUniformVectors 16\n"
260 "MaxVertexOutputVectors 16\n"
261 "MaxFragmentInputVectors 15\n"
262 "MinProgramTexelOffset -8\n"
263 "MaxProgramTexelOffset 7\n"
264 "MaxClipDistances 8\n"
265 "MaxComputeWorkGroupCountX 65535\n"
266 "MaxComputeWorkGroupCountY 65535\n"
267 "MaxComputeWorkGroupCountZ 65535\n"
268 "MaxComputeWorkGroupSizeX 1024\n"
269 "MaxComputeWorkGroupSizeY 1024\n"
270 "MaxComputeWorkGroupSizeZ 64\n"
271 "MaxComputeUniformComponents 1024\n"
272 "MaxComputeTextureImageUnits 16\n"
273 "MaxComputeImageUniforms 8\n"
274 "MaxComputeAtomicCounters 8\n"
275 "MaxComputeAtomicCounterBuffers 1\n"
276 "MaxVaryingComponents 60\n"
277 "MaxVertexOutputComponents 64\n"
278 "MaxGeometryInputComponents 64\n"
279 "MaxGeometryOutputComponents 128\n"
280 "MaxFragmentInputComponents 128\n"
281 "MaxImageUnits 8\n"
282 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
283 "MaxCombinedShaderOutputResources 8\n"
284 "MaxImageSamples 0\n"
285 "MaxVertexImageUniforms 0\n"
286 "MaxTessControlImageUniforms 0\n"
287 "MaxTessEvaluationImageUniforms 0\n"
288 "MaxGeometryImageUniforms 0\n"
289 "MaxFragmentImageUniforms 8\n"
290 "MaxCombinedImageUniforms 8\n"
291 "MaxGeometryTextureImageUnits 16\n"
292 "MaxGeometryOutputVertices 256\n"
293 "MaxGeometryTotalOutputComponents 1024\n"
294 "MaxGeometryUniformComponents 1024\n"
295 "MaxGeometryVaryingComponents 64\n"
296 "MaxTessControlInputComponents 128\n"
297 "MaxTessControlOutputComponents 128\n"
298 "MaxTessControlTextureImageUnits 16\n"
299 "MaxTessControlUniformComponents 1024\n"
300 "MaxTessControlTotalOutputComponents 4096\n"
301 "MaxTessEvaluationInputComponents 128\n"
302 "MaxTessEvaluationOutputComponents 128\n"
303 "MaxTessEvaluationTextureImageUnits 16\n"
304 "MaxTessEvaluationUniformComponents 1024\n"
305 "MaxTessPatchComponents 120\n"
306 "MaxPatchVertices 32\n"
307 "MaxTessGenLevel 64\n"
308 "MaxViewports 16\n"
309 "MaxVertexAtomicCounters 0\n"
310 "MaxTessControlAtomicCounters 0\n"
311 "MaxTessEvaluationAtomicCounters 0\n"
312 "MaxGeometryAtomicCounters 0\n"
313 "MaxFragmentAtomicCounters 8\n"
314 "MaxCombinedAtomicCounters 8\n"
315 "MaxAtomicCounterBindings 1\n"
316 "MaxVertexAtomicCounterBuffers 0\n"
317 "MaxTessControlAtomicCounterBuffers 0\n"
318 "MaxTessEvaluationAtomicCounterBuffers 0\n"
319 "MaxGeometryAtomicCounterBuffers 0\n"
320 "MaxFragmentAtomicCounterBuffers 1\n"
321 "MaxCombinedAtomicCounterBuffers 1\n"
322 "MaxAtomicCounterBufferSize 16384\n"
323 "MaxTransformFeedbackBuffers 4\n"
324 "MaxTransformFeedbackInterleavedComponents 64\n"
325 "MaxCullDistances 8\n"
326 "MaxCombinedClipAndCullDistances 8\n"
327 "MaxSamples 4\n"
328
329 "nonInductiveForLoops 1\n"
330 "whileLoops 1\n"
331 "doWhileLoops 1\n"
332 "generalUniformIndexing 1\n"
333 "generalAttributeMatrixVectorIndexing 1\n"
334 "generalVaryingIndexing 1\n"
335 "generalSamplerIndexing 1\n"
336 "generalVariableIndexing 1\n"
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700337 "generalConstantMatrixVectorIndexing 1\n";
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600338
339//
340// *.conf => this is a config file that can set limits/resources
341//
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700342bool VkTestFramework::SetConfigFile(const std::string &name) {
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600343 if (name.size() < 5)
344 return false;
345
346 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
347 ConfigFile = name;
348 return true;
349 }
350
351 return false;
352}
353
354//
355// Parse either a .conf file provided by the user or the default string above.
356//
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700357void VkTestFramework::ProcessConfigFile() {
358 char **configStrings = 0;
359 char *config = 0;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600360 if (ConfigFile.size() > 0) {
361 configStrings = ReadFileData(ConfigFile.c_str());
362 if (configStrings)
363 config = *configStrings;
364 else {
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700365 printf("Error opening configuration file; will instead use the "
366 "default configuration\n");
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600367 }
368 }
369
370 if (config == 0) {
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700371 config = (char *)alloca(strlen(DefaultConfig) + 1);
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600372 strcpy(config, DefaultConfig);
373 }
374
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700375 const char *delims = " \t\n\r";
376 const char *token = strtok(config, delims);
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600377 while (token) {
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700378 const char *valueStr = strtok(0, delims);
379 if (valueStr == 0 ||
380 !(valueStr[0] == '-' ||
381 (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
382 printf("Error: '%s' bad .conf file. Each name must be followed by "
383 "one number.\n",
384 valueStr ? valueStr : "");
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600385 return;
386 }
387 int value = atoi(valueStr);
388
389 if (strcmp(token, "MaxLights") == 0)
390 Resources.maxLights = value;
391 else if (strcmp(token, "MaxClipPlanes") == 0)
392 Resources.maxClipPlanes = value;
393 else if (strcmp(token, "MaxTextureUnits") == 0)
394 Resources.maxTextureUnits = value;
395 else if (strcmp(token, "MaxTextureCoords") == 0)
396 Resources.maxTextureCoords = value;
397 else if (strcmp(token, "MaxVertexAttribs") == 0)
398 Resources.maxVertexAttribs = value;
399 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
400 Resources.maxVertexUniformComponents = value;
401 else if (strcmp(token, "MaxVaryingFloats") == 0)
402 Resources.maxVaryingFloats = value;
403 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
404 Resources.maxVertexTextureImageUnits = value;
405 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
406 Resources.maxCombinedTextureImageUnits = value;
407 else if (strcmp(token, "MaxTextureImageUnits") == 0)
408 Resources.maxTextureImageUnits = value;
409 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
410 Resources.maxFragmentUniformComponents = value;
411 else if (strcmp(token, "MaxDrawBuffers") == 0)
412 Resources.maxDrawBuffers = value;
413 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
414 Resources.maxVertexUniformVectors = value;
415 else if (strcmp(token, "MaxVaryingVectors") == 0)
416 Resources.maxVaryingVectors = value;
417 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
418 Resources.maxFragmentUniformVectors = value;
419 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
420 Resources.maxVertexOutputVectors = value;
421 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
422 Resources.maxFragmentInputVectors = value;
423 else if (strcmp(token, "MinProgramTexelOffset") == 0)
424 Resources.minProgramTexelOffset = value;
425 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
426 Resources.maxProgramTexelOffset = value;
427 else if (strcmp(token, "MaxClipDistances") == 0)
428 Resources.maxClipDistances = value;
429 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
430 Resources.maxComputeWorkGroupCountX = value;
431 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
432 Resources.maxComputeWorkGroupCountY = value;
433 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
434 Resources.maxComputeWorkGroupCountZ = value;
435 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
436 Resources.maxComputeWorkGroupSizeX = value;
437 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
438 Resources.maxComputeWorkGroupSizeY = value;
439 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
440 Resources.maxComputeWorkGroupSizeZ = value;
441 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
442 Resources.maxComputeUniformComponents = value;
443 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
444 Resources.maxComputeTextureImageUnits = value;
445 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
446 Resources.maxComputeImageUniforms = value;
447 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
448 Resources.maxComputeAtomicCounters = value;
449 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
450 Resources.maxComputeAtomicCounterBuffers = value;
451 else if (strcmp(token, "MaxVaryingComponents") == 0)
452 Resources.maxVaryingComponents = value;
453 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
454 Resources.maxVertexOutputComponents = value;
455 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
456 Resources.maxGeometryInputComponents = value;
457 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
458 Resources.maxGeometryOutputComponents = value;
459 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
460 Resources.maxFragmentInputComponents = value;
461 else if (strcmp(token, "MaxImageUnits") == 0)
462 Resources.maxImageUnits = value;
463 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
464 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
465 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
466 Resources.maxCombinedShaderOutputResources = value;
467 else if (strcmp(token, "MaxImageSamples") == 0)
468 Resources.maxImageSamples = value;
469 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
470 Resources.maxVertexImageUniforms = value;
471 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
472 Resources.maxTessControlImageUniforms = value;
473 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
474 Resources.maxTessEvaluationImageUniforms = value;
475 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
476 Resources.maxGeometryImageUniforms = value;
477 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
478 Resources.maxFragmentImageUniforms = value;
479 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
480 Resources.maxCombinedImageUniforms = value;
481 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
482 Resources.maxGeometryTextureImageUnits = value;
483 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
484 Resources.maxGeometryOutputVertices = value;
485 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
486 Resources.maxGeometryTotalOutputComponents = value;
487 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
488 Resources.maxGeometryUniformComponents = value;
489 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
490 Resources.maxGeometryVaryingComponents = value;
491 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
492 Resources.maxTessControlInputComponents = value;
493 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
494 Resources.maxTessControlOutputComponents = value;
495 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
496 Resources.maxTessControlTextureImageUnits = value;
497 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
498 Resources.maxTessControlUniformComponents = value;
499 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
500 Resources.maxTessControlTotalOutputComponents = value;
501 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
502 Resources.maxTessEvaluationInputComponents = value;
503 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
504 Resources.maxTessEvaluationOutputComponents = value;
505 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
506 Resources.maxTessEvaluationTextureImageUnits = value;
507 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
508 Resources.maxTessEvaluationUniformComponents = value;
509 else if (strcmp(token, "MaxTessPatchComponents") == 0)
510 Resources.maxTessPatchComponents = value;
511 else if (strcmp(token, "MaxPatchVertices") == 0)
512 Resources.maxPatchVertices = value;
513 else if (strcmp(token, "MaxTessGenLevel") == 0)
514 Resources.maxTessGenLevel = value;
515 else if (strcmp(token, "MaxViewports") == 0)
516 Resources.maxViewports = value;
517 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
518 Resources.maxVertexAtomicCounters = value;
519 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
520 Resources.maxTessControlAtomicCounters = value;
521 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
522 Resources.maxTessEvaluationAtomicCounters = value;
523 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
524 Resources.maxGeometryAtomicCounters = value;
525 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
526 Resources.maxFragmentAtomicCounters = value;
527 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
528 Resources.maxCombinedAtomicCounters = value;
529 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
530 Resources.maxAtomicCounterBindings = value;
531 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
532 Resources.maxVertexAtomicCounterBuffers = value;
533 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
534 Resources.maxTessControlAtomicCounterBuffers = value;
535 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
536 Resources.maxTessEvaluationAtomicCounterBuffers = value;
537 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
538 Resources.maxGeometryAtomicCounterBuffers = value;
539 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
540 Resources.maxFragmentAtomicCounterBuffers = value;
541 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
542 Resources.maxCombinedAtomicCounterBuffers = value;
543 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
544 Resources.maxAtomicCounterBufferSize = value;
545 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
546 Resources.maxTransformFeedbackBuffers = value;
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700547 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") ==
548 0)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600549 Resources.maxTransformFeedbackInterleavedComponents = value;
550 else if (strcmp(token, "MaxCullDistances") == 0)
551 Resources.maxCullDistances = value;
552 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
553 Resources.maxCombinedClipAndCullDistances = value;
554 else if (strcmp(token, "MaxSamples") == 0)
555 Resources.maxSamples = value;
556
557 else if (strcmp(token, "nonInductiveForLoops") == 0)
558 Resources.limits.nonInductiveForLoops = (value != 0);
559 else if (strcmp(token, "whileLoops") == 0)
560 Resources.limits.whileLoops = (value != 0);
561 else if (strcmp(token, "doWhileLoops") == 0)
562 Resources.limits.doWhileLoops = (value != 0);
563 else if (strcmp(token, "generalUniformIndexing") == 0)
564 Resources.limits.generalUniformIndexing = (value != 0);
565 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700566 Resources.limits.generalAttributeMatrixVectorIndexing =
567 (value != 0);
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600568 else if (strcmp(token, "generalVaryingIndexing") == 0)
569 Resources.limits.generalVaryingIndexing = (value != 0);
570 else if (strcmp(token, "generalSamplerIndexing") == 0)
571 Resources.limits.generalSamplerIndexing = (value != 0);
572 else if (strcmp(token, "generalVariableIndexing") == 0)
573 Resources.limits.generalVariableIndexing = (value != 0);
574 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
575 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
576 else
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700577 printf("Warning: unrecognized limit (%s) in configuration file.\n",
578 token);
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600579
580 token = strtok(0, delims);
581 }
582 if (configStrings)
583 FreeFileData(configStrings);
584}
585
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700586void VkTestFramework::SetMessageOptions(EShMessages &messages) {
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600587 if (m_compile_options & EOptionRelaxedErrors)
588 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
589 if (m_compile_options & EOptionIntermediate)
590 messages = (EShMessages)(messages | EShMsgAST);
591 if (m_compile_options & EOptionSuppressWarnings)
592 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
593}
594
595//
596// Malloc a string of sufficient size and read a string into it.
597//
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700598char **VkTestFramework::ReadFileData(const char *fileName) {
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600599 FILE *in;
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700600#if defined(_WIN32) && defined(__GNUC__)
601 in = fopen(fileName, "r");
602 int errorCode = in ? 0 : 1;
603#else
604 int errorCode = fopen_s(&in, fileName, "r");
605#endif
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600606
607 char *fdata;
608 int count = 0;
609 const int maxSourceStrings = 5;
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700610 char **return_data =
611 (char **)malloc(sizeof(char *) * (maxSourceStrings + 1));
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600612
613 if (errorCode) {
614 printf("Error: unable to open input file: %s\n", fileName);
615 return 0;
616 }
617
618 while (fgetc(in) != EOF)
619 count++;
620
621 fseek(in, 0, SEEK_SET);
622
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700623 if (!(fdata = (char *)malloc(count + 2))) {
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600624 printf("Error allocating memory\n");
625 return 0;
626 }
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700627 if (fread(fdata, 1, count, in) != count) {
628 printf("Error reading input file: %s\n", fileName);
629 return 0;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600630 }
631 fdata[count] = '\0';
632 fclose(in);
633 if (count == 0) {
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700634 return_data[0] = (char *)malloc(count + 2);
635 return_data[0][0] = '\0';
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600636 m_num_shader_strings = 0;
637 return return_data;
638 } else
639 m_num_shader_strings = 1;
640
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700641 int len = (int)(ceil)((float)count / (float)m_num_shader_strings);
642 int ptr_len = 0, i = 0;
643 while (count > 0) {
644 return_data[i] = (char *)malloc(len + 2);
645 memcpy(return_data[i], fdata + ptr_len, len);
646 return_data[i][len] = '\0';
647 count -= (len);
648 ptr_len += (len);
649 if (count < len) {
650 if (count == 0) {
651 m_num_shader_strings = (i + 1);
652 break;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600653 }
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700654 len = count;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600655 }
656 ++i;
657 }
658 return return_data;
659}
660
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700661void VkTestFramework::FreeFileData(char **data) {
662 for (int i = 0; i < m_num_shader_strings; i++)
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600663 free(data[i]);
664}
665
666//
667// Deduce the language from the filename. Files must end in one of the
668// following extensions:
669//
670// .vert = vertex
671// .tesc = tessellation control
672// .tese = tessellation evaluation
673// .geom = geometry
674// .frag = fragment
675// .comp = compute
676//
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700677EShLanguage VkTestFramework::FindLanguage(const std::string &name) {
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600678 size_t ext = name.rfind('.');
679 if (ext == std::string::npos) {
680 return EShLangVertex;
681 }
682
683 std::string suffix = name.substr(ext + 1, std::string::npos);
684 if (suffix == "vert")
685 return EShLangVertex;
686 else if (suffix == "tesc")
687 return EShLangTessControl;
688 else if (suffix == "tese")
689 return EShLangTessEvaluation;
690 else if (suffix == "geom")
691 return EShLangGeometry;
692 else if (suffix == "frag")
693 return EShLangFragment;
694 else if (suffix == "comp")
695 return EShLangCompute;
696
697 return EShLangVertex;
698}
699
700//
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600701// Convert VK shader type to compiler's
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600702//
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700703EShLanguage
704VkTestFramework::FindLanguage(const VkShaderStageFlagBits shader_type) {
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600705 switch (shader_type) {
Courtney Goeltzenleuchter8e2f0972015-10-21 17:08:06 -0600706 case VK_SHADER_STAGE_VERTEX_BIT:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600707 return EShLangVertex;
708
Courtney Goeltzenleuchter8e2f0972015-10-21 17:08:06 -0600709 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600710 return EShLangTessControl;
711
Courtney Goeltzenleuchter8e2f0972015-10-21 17:08:06 -0600712 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600713 return EShLangTessEvaluation;
714
Courtney Goeltzenleuchter8e2f0972015-10-21 17:08:06 -0600715 case VK_SHADER_STAGE_GEOMETRY_BIT:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600716 return EShLangGeometry;
717
Courtney Goeltzenleuchter8e2f0972015-10-21 17:08:06 -0600718 case VK_SHADER_STAGE_FRAGMENT_BIT:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600719 return EShLangFragment;
720
Courtney Goeltzenleuchter8e2f0972015-10-21 17:08:06 -0600721 case VK_SHADER_STAGE_COMPUTE_BIT:
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600722 return EShLangCompute;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600723
Chia-I Wubbdeacc2014-12-15 23:50:11 +0800724 default:
725 return EShLangVertex;
726 }
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600727}
728
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600729//
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600730// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600731// Return value of false means an error was encountered.
732//
Courtney Goeltzenleuchter8e2f0972015-10-21 17:08:06 -0600733bool VkTestFramework::GLSLtoSPV(const VkShaderStageFlagBits shader_type,
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700734 const char *pshader,
735 std::vector<unsigned int> &spirv) {
Courtney Goeltzenleuchter358c76e2015-09-24 17:05:05 -0600736 glslang::TProgram program;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600737 const char *shaderStrings[1];
738
739 // TODO: Do we want to load a special config file depending on the
740 // shader source? Optional name maybe?
741 // SetConfigFile(fileName);
742
743 ProcessConfigFile();
744
745 EShMessages messages = EShMsgDefault;
746 SetMessageOptions(messages);
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700747 messages =
748 static_cast<EShMessages>(messages | EShMsgSpvRules | EShMsgVulkanRules);
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600749
750 EShLanguage stage = FindLanguage(shader_type);
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700751 glslang::TShader *shader = new glslang::TShader(stage);
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600752
753 shaderStrings[0] = pshader;
754 shader->setStrings(shaderStrings, 1);
755
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700756 if (!shader->parse(&Resources,
757 (m_compile_options & EOptionDefaultDesktop) ? 110 : 100,
758 false, messages)) {
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600759
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700760 if (!(m_compile_options & EOptionSuppressInfolog)) {
Cody Northropad306f02014-11-03 12:54:37 -0700761 puts(shader->getInfoLog());
762 puts(shader->getInfoDebugLog());
763 }
764
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600765 return false; // something didn't work
766 }
767
768 program.addShader(shader);
769
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600770 //
771 // Program-level processing...
772 //
773
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700774 if (!program.link(messages)) {
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600775
Karl Schultz99e9d1d2016-02-02 17:17:23 -0700776 if (!(m_compile_options & EOptionSuppressInfolog)) {
Cody Northropad306f02014-11-03 12:54:37 -0700777 puts(shader->getInfoLog());
778 puts(shader->getInfoDebugLog());
779 }
780
781 return false;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600782 }
783
784 if (m_compile_options & EOptionDumpReflection) {
785 program.buildReflection();
786 program.dumpReflection();
787 }
788
Cody Northropeb9130e2015-06-03 13:01:54 -0600789 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
790
791 //
792 // Test the different modes of SPIR-V modification
793 //
794 if (this->m_canonicalize_spv) {
795 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
796 }
797
798 if (this->m_strip_spv) {
799 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
800 }
801
802 if (this->m_do_everything_spv) {
803 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
804 }
805
Courtney Goeltzenleuchter358c76e2015-09-24 17:05:05 -0600806 delete shader;
Courtney Goeltzenleuchter94192032014-10-03 09:53:32 -0600807
808 return true;
809}