blob: 1b2e83f764310b9cffdb5571b36d8dff4f786237 [file] [log] [blame]
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06001//
Courtney Goeltzenleuchterfcbe16f2015-10-29 13:50:34 -06002// Copyright (C) 2015 Valve Corporation
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -06003//
4// Permission is hereby granted, free of charge, to any person obtaining a
5// copy of this software and associated documentation files (the "Software"),
6// to deal in the Software without restriction, including without limitation
7// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8// and/or sell copies of the Software, and to permit persons to whom the
9// Software is furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included
12// in all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060021//
22// Author: Chia-I Wu <olv@lunarg.com>
23// Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
24// Author: Tony Barbour <tony@LunarG.com>
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -060025
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060026#include "vktestframework.h"
27#include "vkrenderframework.h"
Jon Ashburn94207e92015-12-04 17:03:59 -070028//TODO FIXME remove this once glslang doesn't define this
29#undef BadValue
Cody Northrop5a95b472015-06-03 13:01:54 -060030#include "SPIRV/GlslangToSpv.h"
31#include "SPIRV/SPVRemapper.h"
Tony Barbour4ab45422014-12-10 17:00:20 -070032#include <limits.h>
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060033#include <math.h>
Jon Ashburn94207e92015-12-04 17:03:59 -070034
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060035
Tony Barbour3d69c9e2015-05-20 16:53:31 -060036#if defined(PATH_MAX) && !defined(MAX_PATH)
37#define MAX_PATH PATH_MAX
38#endif
39
Tony Barbour6a3faf02015-07-23 10:36:18 -060040#ifdef _WIN32
41#define ERR_EXIT(err_msg, err_class) \
42 do { \
43 MessageBox(NULL, err_msg, err_class, MB_OK); \
44 exit(1); \
45 } while (0)
46#else // _WIN32
47
48#define ERR_EXIT(err_msg, err_class) \
49 do { \
50 printf(err_msg); \
51 fflush(stdout); \
52 exit(1); \
53 } while (0)
54#endif // _WIN32
55
56#define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \
57{ \
58 m_fp##entrypoint = (PFN_vk##entrypoint) vkGetInstanceProcAddr(inst, "vk"#entrypoint); \
59 if (m_fp##entrypoint == NULL) { \
60 ERR_EXIT("vkGetInstanceProcAddr failed to find vk"#entrypoint, \
61 "vkGetInstanceProcAddr Failure"); \
62 } \
63}
64
65#define GET_DEVICE_PROC_ADDR(dev, entrypoint) \
66{ \
67 m_fp##entrypoint = (PFN_vk##entrypoint) vkGetDeviceProcAddr(dev, "vk"#entrypoint); \
68 if (m_fp##entrypoint == NULL) { \
69 ERR_EXIT("vkGetDeviceProcAddr failed to find vk"#entrypoint, \
70 "vkGetDeviceProcAddr Failure"); \
71 } \
72}
73
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060074// Command-line options
75enum TOptions {
76 EOptionNone = 0x000,
77 EOptionIntermediate = 0x001,
78 EOptionSuppressInfolog = 0x002,
79 EOptionMemoryLeakMode = 0x004,
80 EOptionRelaxedErrors = 0x008,
81 EOptionGiveWarnings = 0x010,
82 EOptionLinkProgram = 0x020,
83 EOptionMultiThreaded = 0x040,
84 EOptionDumpConfig = 0x080,
85 EOptionDumpReflection = 0x100,
86 EOptionSuppressWarnings = 0x200,
87 EOptionDumpVersions = 0x400,
Cody Northrop3bfd27c2015-03-17 15:55:58 -060088 EOptionSpv = 0x800,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060089 EOptionDefaultDesktop = 0x1000,
90};
91
Ian Elliott7e40db92015-08-21 15:09:33 -060092typedef struct _SwapchainBuffers {
Tony Barbour6a3faf02015-07-23 10:36:18 -060093 VkImage image;
Chia-I Wu3432a0c2015-10-27 18:04:07 +080094 VkCommandBuffer cmd;
Courtney Goeltzenleuchter5861a1b2015-09-01 17:30:39 -060095 VkImageView view;
Ian Elliott7e40db92015-08-21 15:09:33 -060096} SwapchainBuffers;
Tony Barbour6a3faf02015-07-23 10:36:18 -060097
Chia-I Wuf8693382015-04-16 22:02:10 +080098
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -060099#ifndef _WIN32
100
101#include <errno.h>
102
103int fopen_s(
104 FILE** pFile,
105 const char* filename,
106 const char* mode
107)
108{
109 if (!pFile || !filename || !mode) {
110 return EINVAL;
111 }
112
113 FILE* f = fopen(filename, mode);
114 if (! f) {
115 if (errno != 0) {
116 return errno;
117 } else {
118 return ENOENT;
119 }
120 }
121 *pFile = f;
122
123 return 0;
124}
125
126#endif
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600127
Tony Barbour3d69c9e2015-05-20 16:53:31 -0600128
129
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600130// Set up environment for GLSL compiler
131// Must be done once per process
132void TestEnvironment::SetUp()
133{
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600134 // Initialize GLSL to SPV compiler utility
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600135 glslang::InitializeProcess();
Chia-I Wub76e0fa2014-12-28 14:27:28 +0800136
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600137 vk_testing::set_error_callback(test_error_callback);
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600138}
139
140void TestEnvironment::TearDown()
141{
142 glslang::FinalizeProcess();
143}
144
Tony Barbour6918cd52015-04-09 12:58:51 -0600145VkTestFramework::VkTestFramework() :
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600146 m_compile_options( 0 ),
147 m_num_shader_strings( 0 )
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600148{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600149
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600150}
151
Tony Barbour6918cd52015-04-09 12:58:51 -0600152VkTestFramework::~VkTestFramework()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600153{
Courtney Goeltzenleuchtera0f74c52014-10-08 08:46:51 -0600154
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600155}
156
157// Define all the static elements
Cody Northropa3673cf2015-06-09 13:00:45 -0600158bool VkTestFramework::m_use_glsl = false;
159bool VkTestFramework::m_canonicalize_spv = false;
160bool VkTestFramework::m_strip_spv = false;
Cody Northrop5a95b472015-06-03 13:01:54 -0600161bool VkTestFramework::m_do_everything_spv = false;
Tony Barbour6918cd52015-04-09 12:58:51 -0600162int VkTestFramework::m_width = 0;
163int VkTestFramework::m_height = 0;
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600164
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600165bool VkTestFramework::optionMatch(const char* option, char* optionLine)
166{
167 if (strncmp(option, optionLine, strlen(option)) == 0)
168 return true;
169 else
170 return false;
171}
172
Tony Barbour6918cd52015-04-09 12:58:51 -0600173void VkTestFramework::InitArgs(int *argc, char *argv[])
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600174{
175 int i, n;
176
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600177 for (i=1, n=1; i< *argc; i++) {
Tony Barbour7b60e492016-02-02 14:43:55 -0700178 if (optionMatch("--no-SPV", argv[i]))
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600179 m_use_glsl = true;
180 else if (optionMatch("--strip-SPV", argv[i]))
Tony Barbour7b60e492016-02-02 14:43:55 -0700181 m_strip_spv = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600182 else if (optionMatch("--canonicalize-SPV", argv[i]))
183 m_canonicalize_spv = true;
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600184 else if (optionMatch("--help", argv[i]) ||
185 optionMatch("-h", argv[i])) {
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700186 printf("\nOther options:\n");
187 printf("\t--show-images\n"
188 "\t\tDisplay test images in viewer after tests complete.\n");
189 printf("\t--save-images\n"
190 "\t\tSave tests images as ppm files in current working directory.\n"
191 "\t\tUsed to generate golden images for compare-images.\n");
192 printf("\t--compare-images\n"
193 "\t\tCompare test images to 'golden' image in golden folder.\n"
Tony Barboura98d3932014-12-11 09:52:49 -0700194 "\t\tAlso saves the generated test image in current working\n"
195 "\t\t\tdirectory but only if the image is different from the golden\n"
196 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can specify\n"
197 "\t\t\tdifferent directory for golden images\n"
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700198 "\t\tSignal test failure if different.\n");
Cody Northrop3bfd27c2015-03-17 15:55:58 -0600199 printf("\t--no-SPV\n"
200 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600201 printf("\t--strip-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600202 "\t\tStrip SPIR-V debug information (line numbers, names, etc).\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600203 printf("\t--canonicalize-SPV\n"
Cody Northropa9bad9c2015-07-13 12:48:41 -0600204 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600205 exit(0);
206 } else {
207 printf("\nUnrecognized option: %s\n", argv[i]);
208 printf("\nUse --help or -h for option list.\n");
Tony Barbour4ab45422014-12-10 17:00:20 -0700209 exit(0);
Courtney Goeltzenleuchter31144b72014-12-02 13:13:10 -0700210 }
211
Cody Northrop50a2a4b2015-06-03 16:49:20 -0600212 /*
213 * Since the above "consume" inputs, update argv
214 * so that it contains the trimmed list of args for glutInit
215 */
216
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600217 argv[n] = argv[i];
218 n++;
219 }
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600220}
221
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700222VkFormat VkTestFramework::GetFormat(VkInstance instance, vk_testing::Device *device)
223{
224 VkFormatProperties format_props;
Tony Barbour7b60e492016-02-02 14:43:55 -0700225
226 vkGetPhysicalDeviceFormatProperties(device->phy().handle(), VK_FORMAT_B8G8R8A8_UNORM, &format_props);
227 if (format_props.linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ||
228 format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700229 {
Tony Barbour7b60e492016-02-02 14:43:55 -0700230 return VK_FORMAT_B8G8R8A8_UNORM;
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700231 }
Tony Barbour7b60e492016-02-02 14:43:55 -0700232 vkGetPhysicalDeviceFormatProperties(device->phy().handle(), VK_FORMAT_R8G8B8A8_UNORM, &format_props);
233 if (format_props.linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ||
234 format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700235 {
Tony Barbour7b60e492016-02-02 14:43:55 -0700236 return VK_FORMAT_R8G8B8A8_UNORM;
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700237 }
Tony Barbour7b60e492016-02-02 14:43:55 -0700238 printf("Error - device does not support VK_FORMAT_B8G8R8A8_UNORM nor VK_FORMAT_R8G8B8A8_UNORM - exiting\n");
239 exit(0);
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700240}
241
Tony Barbour2d6d54e2015-12-03 16:05:11 -0700242
Tony Barbour6918cd52015-04-09 12:58:51 -0600243void VkTestFramework::Finish()
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600244{
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600245
Courtney Goeltzenleuchter30e9dc42014-09-04 16:24:19 -0600246}
247
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600248//
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600249// These are the default resources for TBuiltInResources, used for both
250// - parsing this string for the case where the user didn't supply one
251// - dumping out a template for user construction of a config file
252//
253static const char* DefaultConfig =
254 "MaxLights 32\n"
255 "MaxClipPlanes 6\n"
256 "MaxTextureUnits 32\n"
257 "MaxTextureCoords 32\n"
258 "MaxVertexAttribs 64\n"
259 "MaxVertexUniformComponents 4096\n"
260 "MaxVaryingFloats 64\n"
261 "MaxVertexTextureImageUnits 32\n"
262 "MaxCombinedTextureImageUnits 80\n"
263 "MaxTextureImageUnits 32\n"
264 "MaxFragmentUniformComponents 4096\n"
265 "MaxDrawBuffers 32\n"
266 "MaxVertexUniformVectors 128\n"
267 "MaxVaryingVectors 8\n"
268 "MaxFragmentUniformVectors 16\n"
269 "MaxVertexOutputVectors 16\n"
270 "MaxFragmentInputVectors 15\n"
271 "MinProgramTexelOffset -8\n"
272 "MaxProgramTexelOffset 7\n"
273 "MaxClipDistances 8\n"
274 "MaxComputeWorkGroupCountX 65535\n"
275 "MaxComputeWorkGroupCountY 65535\n"
276 "MaxComputeWorkGroupCountZ 65535\n"
277 "MaxComputeWorkGroupSizeX 1024\n"
278 "MaxComputeWorkGroupSizeY 1024\n"
279 "MaxComputeWorkGroupSizeZ 64\n"
280 "MaxComputeUniformComponents 1024\n"
281 "MaxComputeTextureImageUnits 16\n"
282 "MaxComputeImageUniforms 8\n"
283 "MaxComputeAtomicCounters 8\n"
284 "MaxComputeAtomicCounterBuffers 1\n"
285 "MaxVaryingComponents 60\n"
286 "MaxVertexOutputComponents 64\n"
287 "MaxGeometryInputComponents 64\n"
288 "MaxGeometryOutputComponents 128\n"
289 "MaxFragmentInputComponents 128\n"
290 "MaxImageUnits 8\n"
291 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
292 "MaxCombinedShaderOutputResources 8\n"
293 "MaxImageSamples 0\n"
294 "MaxVertexImageUniforms 0\n"
295 "MaxTessControlImageUniforms 0\n"
296 "MaxTessEvaluationImageUniforms 0\n"
297 "MaxGeometryImageUniforms 0\n"
298 "MaxFragmentImageUniforms 8\n"
299 "MaxCombinedImageUniforms 8\n"
300 "MaxGeometryTextureImageUnits 16\n"
301 "MaxGeometryOutputVertices 256\n"
302 "MaxGeometryTotalOutputComponents 1024\n"
303 "MaxGeometryUniformComponents 1024\n"
304 "MaxGeometryVaryingComponents 64\n"
305 "MaxTessControlInputComponents 128\n"
306 "MaxTessControlOutputComponents 128\n"
307 "MaxTessControlTextureImageUnits 16\n"
308 "MaxTessControlUniformComponents 1024\n"
309 "MaxTessControlTotalOutputComponents 4096\n"
310 "MaxTessEvaluationInputComponents 128\n"
311 "MaxTessEvaluationOutputComponents 128\n"
312 "MaxTessEvaluationTextureImageUnits 16\n"
313 "MaxTessEvaluationUniformComponents 1024\n"
314 "MaxTessPatchComponents 120\n"
315 "MaxPatchVertices 32\n"
316 "MaxTessGenLevel 64\n"
317 "MaxViewports 16\n"
318 "MaxVertexAtomicCounters 0\n"
319 "MaxTessControlAtomicCounters 0\n"
320 "MaxTessEvaluationAtomicCounters 0\n"
321 "MaxGeometryAtomicCounters 0\n"
322 "MaxFragmentAtomicCounters 8\n"
323 "MaxCombinedAtomicCounters 8\n"
324 "MaxAtomicCounterBindings 1\n"
325 "MaxVertexAtomicCounterBuffers 0\n"
326 "MaxTessControlAtomicCounterBuffers 0\n"
327 "MaxTessEvaluationAtomicCounterBuffers 0\n"
328 "MaxGeometryAtomicCounterBuffers 0\n"
329 "MaxFragmentAtomicCounterBuffers 1\n"
330 "MaxCombinedAtomicCounterBuffers 1\n"
331 "MaxAtomicCounterBufferSize 16384\n"
332 "MaxTransformFeedbackBuffers 4\n"
333 "MaxTransformFeedbackInterleavedComponents 64\n"
334 "MaxCullDistances 8\n"
335 "MaxCombinedClipAndCullDistances 8\n"
336 "MaxSamples 4\n"
337
338 "nonInductiveForLoops 1\n"
339 "whileLoops 1\n"
340 "doWhileLoops 1\n"
341 "generalUniformIndexing 1\n"
342 "generalAttributeMatrixVectorIndexing 1\n"
343 "generalVaryingIndexing 1\n"
344 "generalSamplerIndexing 1\n"
345 "generalVariableIndexing 1\n"
346 "generalConstantMatrixVectorIndexing 1\n"
347 ;
348
349//
350// *.conf => this is a config file that can set limits/resources
351//
Tony Barbour6918cd52015-04-09 12:58:51 -0600352bool VkTestFramework::SetConfigFile(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600353{
354 if (name.size() < 5)
355 return false;
356
357 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
358 ConfigFile = name;
359 return true;
360 }
361
362 return false;
363}
364
365//
366// Parse either a .conf file provided by the user or the default string above.
367//
Tony Barbour6918cd52015-04-09 12:58:51 -0600368void VkTestFramework::ProcessConfigFile()
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600369{
370 char** configStrings = 0;
371 char* config = 0;
372 if (ConfigFile.size() > 0) {
373 configStrings = ReadFileData(ConfigFile.c_str());
374 if (configStrings)
375 config = *configStrings;
376 else {
377 printf("Error opening configuration file; will instead use the default configuration\n");
378 }
379 }
380
381 if (config == 0) {
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -0600382 config = (char *) alloca(strlen(DefaultConfig) + 1);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600383 strcpy(config, DefaultConfig);
384 }
385
386 const char* delims = " \t\n\r";
387 const char* token = strtok(config, delims);
388 while (token) {
389 const char* valueStr = strtok(0, delims);
390 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
391 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
392 return;
393 }
394 int value = atoi(valueStr);
395
396 if (strcmp(token, "MaxLights") == 0)
397 Resources.maxLights = value;
398 else if (strcmp(token, "MaxClipPlanes") == 0)
399 Resources.maxClipPlanes = value;
400 else if (strcmp(token, "MaxTextureUnits") == 0)
401 Resources.maxTextureUnits = value;
402 else if (strcmp(token, "MaxTextureCoords") == 0)
403 Resources.maxTextureCoords = value;
404 else if (strcmp(token, "MaxVertexAttribs") == 0)
405 Resources.maxVertexAttribs = value;
406 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
407 Resources.maxVertexUniformComponents = value;
408 else if (strcmp(token, "MaxVaryingFloats") == 0)
409 Resources.maxVaryingFloats = value;
410 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
411 Resources.maxVertexTextureImageUnits = value;
412 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
413 Resources.maxCombinedTextureImageUnits = value;
414 else if (strcmp(token, "MaxTextureImageUnits") == 0)
415 Resources.maxTextureImageUnits = value;
416 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
417 Resources.maxFragmentUniformComponents = value;
418 else if (strcmp(token, "MaxDrawBuffers") == 0)
419 Resources.maxDrawBuffers = value;
420 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
421 Resources.maxVertexUniformVectors = value;
422 else if (strcmp(token, "MaxVaryingVectors") == 0)
423 Resources.maxVaryingVectors = value;
424 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
425 Resources.maxFragmentUniformVectors = value;
426 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
427 Resources.maxVertexOutputVectors = value;
428 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
429 Resources.maxFragmentInputVectors = value;
430 else if (strcmp(token, "MinProgramTexelOffset") == 0)
431 Resources.minProgramTexelOffset = value;
432 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
433 Resources.maxProgramTexelOffset = value;
434 else if (strcmp(token, "MaxClipDistances") == 0)
435 Resources.maxClipDistances = value;
436 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
437 Resources.maxComputeWorkGroupCountX = value;
438 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
439 Resources.maxComputeWorkGroupCountY = value;
440 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
441 Resources.maxComputeWorkGroupCountZ = value;
442 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
443 Resources.maxComputeWorkGroupSizeX = value;
444 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
445 Resources.maxComputeWorkGroupSizeY = value;
446 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
447 Resources.maxComputeWorkGroupSizeZ = value;
448 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
449 Resources.maxComputeUniformComponents = value;
450 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
451 Resources.maxComputeTextureImageUnits = value;
452 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
453 Resources.maxComputeImageUniforms = value;
454 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
455 Resources.maxComputeAtomicCounters = value;
456 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
457 Resources.maxComputeAtomicCounterBuffers = value;
458 else if (strcmp(token, "MaxVaryingComponents") == 0)
459 Resources.maxVaryingComponents = value;
460 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
461 Resources.maxVertexOutputComponents = value;
462 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
463 Resources.maxGeometryInputComponents = value;
464 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
465 Resources.maxGeometryOutputComponents = value;
466 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
467 Resources.maxFragmentInputComponents = value;
468 else if (strcmp(token, "MaxImageUnits") == 0)
469 Resources.maxImageUnits = value;
470 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
471 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
472 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
473 Resources.maxCombinedShaderOutputResources = value;
474 else if (strcmp(token, "MaxImageSamples") == 0)
475 Resources.maxImageSamples = value;
476 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
477 Resources.maxVertexImageUniforms = value;
478 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
479 Resources.maxTessControlImageUniforms = value;
480 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
481 Resources.maxTessEvaluationImageUniforms = value;
482 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
483 Resources.maxGeometryImageUniforms = value;
484 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
485 Resources.maxFragmentImageUniforms = value;
486 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
487 Resources.maxCombinedImageUniforms = value;
488 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
489 Resources.maxGeometryTextureImageUnits = value;
490 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
491 Resources.maxGeometryOutputVertices = value;
492 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
493 Resources.maxGeometryTotalOutputComponents = value;
494 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
495 Resources.maxGeometryUniformComponents = value;
496 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
497 Resources.maxGeometryVaryingComponents = value;
498 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
499 Resources.maxTessControlInputComponents = value;
500 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
501 Resources.maxTessControlOutputComponents = value;
502 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
503 Resources.maxTessControlTextureImageUnits = value;
504 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
505 Resources.maxTessControlUniformComponents = value;
506 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
507 Resources.maxTessControlTotalOutputComponents = value;
508 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
509 Resources.maxTessEvaluationInputComponents = value;
510 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
511 Resources.maxTessEvaluationOutputComponents = value;
512 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
513 Resources.maxTessEvaluationTextureImageUnits = value;
514 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
515 Resources.maxTessEvaluationUniformComponents = value;
516 else if (strcmp(token, "MaxTessPatchComponents") == 0)
517 Resources.maxTessPatchComponents = value;
518 else if (strcmp(token, "MaxPatchVertices") == 0)
519 Resources.maxPatchVertices = value;
520 else if (strcmp(token, "MaxTessGenLevel") == 0)
521 Resources.maxTessGenLevel = value;
522 else if (strcmp(token, "MaxViewports") == 0)
523 Resources.maxViewports = value;
524 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
525 Resources.maxVertexAtomicCounters = value;
526 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
527 Resources.maxTessControlAtomicCounters = value;
528 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
529 Resources.maxTessEvaluationAtomicCounters = value;
530 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
531 Resources.maxGeometryAtomicCounters = value;
532 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
533 Resources.maxFragmentAtomicCounters = value;
534 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
535 Resources.maxCombinedAtomicCounters = value;
536 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
537 Resources.maxAtomicCounterBindings = value;
538 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
539 Resources.maxVertexAtomicCounterBuffers = value;
540 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
541 Resources.maxTessControlAtomicCounterBuffers = value;
542 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
543 Resources.maxTessEvaluationAtomicCounterBuffers = value;
544 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
545 Resources.maxGeometryAtomicCounterBuffers = value;
546 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
547 Resources.maxFragmentAtomicCounterBuffers = value;
548 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
549 Resources.maxCombinedAtomicCounterBuffers = value;
550 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
551 Resources.maxAtomicCounterBufferSize = value;
552 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
553 Resources.maxTransformFeedbackBuffers = value;
554 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
555 Resources.maxTransformFeedbackInterleavedComponents = value;
556 else if (strcmp(token, "MaxCullDistances") == 0)
557 Resources.maxCullDistances = value;
558 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
559 Resources.maxCombinedClipAndCullDistances = value;
560 else if (strcmp(token, "MaxSamples") == 0)
561 Resources.maxSamples = value;
562
563 else if (strcmp(token, "nonInductiveForLoops") == 0)
564 Resources.limits.nonInductiveForLoops = (value != 0);
565 else if (strcmp(token, "whileLoops") == 0)
566 Resources.limits.whileLoops = (value != 0);
567 else if (strcmp(token, "doWhileLoops") == 0)
568 Resources.limits.doWhileLoops = (value != 0);
569 else if (strcmp(token, "generalUniformIndexing") == 0)
570 Resources.limits.generalUniformIndexing = (value != 0);
571 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
572 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
573 else if (strcmp(token, "generalVaryingIndexing") == 0)
574 Resources.limits.generalVaryingIndexing = (value != 0);
575 else if (strcmp(token, "generalSamplerIndexing") == 0)
576 Resources.limits.generalSamplerIndexing = (value != 0);
577 else if (strcmp(token, "generalVariableIndexing") == 0)
578 Resources.limits.generalVariableIndexing = (value != 0);
579 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
580 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
581 else
582 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
583
584 token = strtok(0, delims);
585 }
586 if (configStrings)
587 FreeFileData(configStrings);
588}
589
Tony Barbour6918cd52015-04-09 12:58:51 -0600590void VkTestFramework::SetMessageOptions(EShMessages& messages)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600591{
592 if (m_compile_options & EOptionRelaxedErrors)
593 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
594 if (m_compile_options & EOptionIntermediate)
595 messages = (EShMessages)(messages | EShMsgAST);
596 if (m_compile_options & EOptionSuppressWarnings)
597 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
598}
599
600//
601// Malloc a string of sufficient size and read a string into it.
602//
Tony Barbour6918cd52015-04-09 12:58:51 -0600603char** VkTestFramework::ReadFileData(const char* fileName)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600604{
605 FILE *in;
606 #if defined(_WIN32) && defined(__GNUC__)
607 in = fopen(fileName, "r");
608 int errorCode = in ? 0 : 1;
609 #else
610 int errorCode = fopen_s(&in, fileName, "r");
611 #endif
612
613 char *fdata;
614 int count = 0;
615 const int maxSourceStrings = 5;
616 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
617
618 if (errorCode) {
619 printf("Error: unable to open input file: %s\n", fileName);
620 return 0;
621 }
622
623 while (fgetc(in) != EOF)
624 count++;
625
626 fseek(in, 0, SEEK_SET);
627
628 if (!(fdata = (char*)malloc(count+2))) {
629 printf("Error allocating memory\n");
630 return 0;
631 }
632 if (fread(fdata,1,count, in)!=count) {
633 printf("Error reading input file: %s\n", fileName);
634 return 0;
635 }
636 fdata[count] = '\0';
637 fclose(in);
638 if (count == 0) {
639 return_data[0]=(char*)malloc(count+2);
640 return_data[0][0]='\0';
641 m_num_shader_strings = 0;
642 return return_data;
643 } else
644 m_num_shader_strings = 1;
645
646 int len = (int)(ceil)((float)count/(float)m_num_shader_strings);
647 int ptr_len=0,i=0;
648 while(count>0){
649 return_data[i]=(char*)malloc(len+2);
650 memcpy(return_data[i],fdata+ptr_len,len);
651 return_data[i][len]='\0';
652 count-=(len);
653 ptr_len+=(len);
654 if(count<len){
655 if(count==0){
656 m_num_shader_strings=(i+1);
657 break;
658 }
659 len = count;
660 }
661 ++i;
662 }
663 return return_data;
664}
665
Tony Barbour6918cd52015-04-09 12:58:51 -0600666void VkTestFramework::FreeFileData(char** data)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600667{
668 for(int i=0;i<m_num_shader_strings;i++)
669 free(data[i]);
670}
671
672//
673// Deduce the language from the filename. Files must end in one of the
674// following extensions:
675//
676// .vert = vertex
677// .tesc = tessellation control
678// .tese = tessellation evaluation
679// .geom = geometry
680// .frag = fragment
681// .comp = compute
682//
Tony Barbour6918cd52015-04-09 12:58:51 -0600683EShLanguage VkTestFramework::FindLanguage(const std::string& name)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600684{
685 size_t ext = name.rfind('.');
686 if (ext == std::string::npos) {
687 return EShLangVertex;
688 }
689
690 std::string suffix = name.substr(ext + 1, std::string::npos);
691 if (suffix == "vert")
692 return EShLangVertex;
693 else if (suffix == "tesc")
694 return EShLangTessControl;
695 else if (suffix == "tese")
696 return EShLangTessEvaluation;
697 else if (suffix == "geom")
698 return EShLangGeometry;
699 else if (suffix == "frag")
700 return EShLangFragment;
701 else if (suffix == "comp")
702 return EShLangCompute;
703
704 return EShLangVertex;
705}
706
707//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600708// Convert VK shader type to compiler's
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600709//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600710EShLanguage VkTestFramework::FindLanguage(const VkShaderStageFlagBits shader_type)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600711{
712 switch (shader_type) {
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600713 case VK_SHADER_STAGE_VERTEX_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600714 return EShLangVertex;
715
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600716 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600717 return EShLangTessControl;
718
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600719 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600720 return EShLangTessEvaluation;
721
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600722 case VK_SHADER_STAGE_GEOMETRY_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600723 return EShLangGeometry;
724
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600725 case VK_SHADER_STAGE_FRAGMENT_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600726 return EShLangFragment;
727
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600728 case VK_SHADER_STAGE_COMPUTE_BIT:
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600729 return EShLangCompute;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600730
Chia-I Wub4c2aa42014-12-15 23:50:11 +0800731 default:
732 return EShLangVertex;
733 }
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600734}
735
736
737//
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600738// Compile a given string containing GLSL into SPV for use by VK
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600739// Return value of false means an error was encountered.
740//
Courtney Goeltzenleuchterd2635502015-10-21 17:08:06 -0600741bool VkTestFramework::GLSLtoSPV(const VkShaderStageFlagBits shader_type,
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600742 const char *pshader,
Cody Northrop5a95b472015-06-03 13:01:54 -0600743 std::vector<unsigned int> &spirv)
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600744{
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -0600745 glslang::TProgram program;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600746 const char *shaderStrings[1];
747
748 // TODO: Do we want to load a special config file depending on the
749 // shader source? Optional name maybe?
750 // SetConfigFile(fileName);
751
752 ProcessConfigFile();
753
754 EShMessages messages = EShMsgDefault;
755 SetMessageOptions(messages);
GregF7ed37422016-01-21 10:00:36 -0700756 messages = static_cast<EShMessages>(messages | EShMsgSpvRules | EShMsgVulkanRules);
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600757
758 EShLanguage stage = FindLanguage(shader_type);
759 glslang::TShader* shader = new glslang::TShader(stage);
760
761 shaderStrings[0] = pshader;
762 shader->setStrings(shaderStrings, 1);
763
764 if (! shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
765
Cody Northrop195d6622014-11-03 12:54:37 -0700766 if (! (m_compile_options & EOptionSuppressInfolog)) {
767 puts(shader->getInfoLog());
768 puts(shader->getInfoDebugLog());
769 }
770
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600771 return false; // something didn't work
772 }
773
774 program.addShader(shader);
775
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600776
777 //
778 // Program-level processing...
779 //
780
Cody Northrop195d6622014-11-03 12:54:37 -0700781 if (! program.link(messages)) {
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600782
Cody Northrop195d6622014-11-03 12:54:37 -0700783 if (! (m_compile_options & EOptionSuppressInfolog)) {
784 puts(shader->getInfoLog());
785 puts(shader->getInfoDebugLog());
786 }
787
788 return false;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600789 }
790
791 if (m_compile_options & EOptionDumpReflection) {
792 program.buildReflection();
793 program.dumpReflection();
794 }
795
Cody Northrop5a95b472015-06-03 13:01:54 -0600796 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
797
798 //
799 // Test the different modes of SPIR-V modification
800 //
801 if (this->m_canonicalize_spv) {
802 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
803 }
804
805 if (this->m_strip_spv) {
806 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
807 }
808
809 if (this->m_do_everything_spv) {
810 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
811 }
812
Courtney Goeltzenleuchterc7def922015-09-24 17:05:05 -0600813 delete shader;
Courtney Goeltzenleuchter9818f782014-10-03 09:53:32 -0600814
815 return true;
816}