1 /*
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 * 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
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * 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.
17 *
18 * Author: Chia-I Wu <olvaffe@gmail.com>
19 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
20 * Author: Tony Barbour <tony@LunarG.com>
21 */
22
23 #include "vktestframework.h"
24 #include "vkrenderframework.h"
25 // TODO FIXME remove this once glslang doesn't define this
26 #undef BadValue
27 #include "SPIRV/GlslangToSpv.h"
28 #include "SPIRV/SPVRemapper.h"
29 #include <limits.h>
30 #include <math.h>
31
32 #if defined(PATH_MAX) && !defined(MAX_PATH)
33 #define MAX_PATH PATH_MAX
34 #endif
35
36 #ifdef _WIN32
37 #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
43
44 #define ERR_EXIT(err_msg, err_class) \
45 do { \
46 printf(err_msg); \
47 fflush(stdout); \
48 exit(1); \
49 } while (0)
50 #endif // _WIN32
51
52 #define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \
53 { \
54 m_fp##entrypoint = (PFN_vk##entrypoint)vkGetInstanceProcAddr(inst, "vk" #entrypoint); \
55 if (m_fp##entrypoint == NULL) { \
56 ERR_EXIT("vkGetInstanceProcAddr failed to find vk" #entrypoint, "vkGetInstanceProcAddr Failure"); \
57 } \
58 }
59
60 #define GET_DEVICE_PROC_ADDR(dev, entrypoint) \
61 { \
62 m_fp##entrypoint = (PFN_vk##entrypoint)vkGetDeviceProcAddr(dev, "vk" #entrypoint); \
63 if (m_fp##entrypoint == NULL) { \
64 ERR_EXIT("vkGetDeviceProcAddr failed to find vk" #entrypoint, "vkGetDeviceProcAddr Failure"); \
65 } \
66 }
67
68 // Command-line options
69 enum TOptions {
70 EOptionNone = 0x000,
71 EOptionIntermediate = 0x001,
72 EOptionSuppressInfolog = 0x002,
73 EOptionMemoryLeakMode = 0x004,
74 EOptionRelaxedErrors = 0x008,
75 EOptionGiveWarnings = 0x010,
76 EOptionLinkProgram = 0x020,
77 EOptionMultiThreaded = 0x040,
78 EOptionDumpConfig = 0x080,
79 EOptionDumpReflection = 0x100,
80 EOptionSuppressWarnings = 0x200,
81 EOptionDumpVersions = 0x400,
82 EOptionSpv = 0x800,
83 EOptionDefaultDesktop = 0x1000,
84 };
85
86 struct SwapchainBuffers {
87 VkImage image;
88 VkCommandBuffer cmd;
89 VkImageView view;
90 };
91
92 #ifndef _WIN32
93
94 #include <errno.h>
95
fopen_s(FILE ** pFile,const char * filename,const char * mode)96 int fopen_s(FILE **pFile, const char *filename, const char *mode) {
97 if (!pFile || !filename || !mode) {
98 return EINVAL;
99 }
100
101 FILE *f = fopen(filename, mode);
102 if (!f) {
103 if (errno != 0) {
104 return errno;
105 } else {
106 return ENOENT;
107 }
108 }
109 *pFile = f;
110
111 return 0;
112 }
113
114 #endif
115
116 // Set up environment for GLSL compiler
117 // Must be done once per process
SetUp()118 void TestEnvironment::SetUp() {
119 // Initialize GLSL to SPV compiler utility
120 glslang::InitializeProcess();
121
122 vk_testing::set_error_callback(test_error_callback);
123 }
124
TearDown()125 void TestEnvironment::TearDown() { glslang::FinalizeProcess(); }
126
VkTestFramework()127 VkTestFramework::VkTestFramework() : m_compile_options(0), m_num_shader_strings(0) {}
128
~VkTestFramework()129 VkTestFramework::~VkTestFramework() {}
130
131 // Define all the static elements
132 bool VkTestFramework::m_use_glsl = false;
133 bool VkTestFramework::m_canonicalize_spv = false;
134 bool VkTestFramework::m_strip_spv = false;
135 bool VkTestFramework::m_do_everything_spv = false;
136 int VkTestFramework::m_width = 0;
137 int VkTestFramework::m_height = 0;
138
optionMatch(const char * option,char * optionLine)139 bool VkTestFramework::optionMatch(const char *option, char *optionLine) {
140 if (strncmp(option, optionLine, strlen(option)) == 0)
141 return true;
142 else
143 return false;
144 }
145
InitArgs(int * argc,char * argv[])146 void VkTestFramework::InitArgs(int *argc, char *argv[]) {
147 int i, n;
148
149 for (i = 1, n = 1; i < *argc; i++) {
150 if (optionMatch("--no-SPV", argv[i]))
151 m_use_glsl = true;
152 else if (optionMatch("--strip-SPV", argv[i]))
153 m_strip_spv = true;
154 else if (optionMatch("--canonicalize-SPV", argv[i]))
155 m_canonicalize_spv = true;
156 else if (optionMatch("--help", argv[i]) || optionMatch("-h", argv[i])) {
157 printf("\nOther options:\n");
158 printf("\t--show-images\n"
159 "\t\tDisplay test images in viewer after tests complete.\n");
160 printf("\t--save-images\n"
161 "\t\tSave tests images as ppm files in current working "
162 "directory.\n"
163 "\t\tUsed to generate golden images for compare-images.\n");
164 printf("\t--compare-images\n"
165 "\t\tCompare test images to 'golden' image in golden folder.\n"
166 "\t\tAlso saves the generated test image in current working\n"
167 "\t\t\tdirectory but only if the image is different from the "
168 "golden\n"
169 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can "
170 "specify\n"
171 "\t\t\tdifferent directory for golden images\n"
172 "\t\tSignal test failure if different.\n");
173 printf("\t--no-SPV\n"
174 "\t\tUse built-in GLSL compiler rather than SPV code path.\n");
175 printf("\t--strip-SPV\n"
176 "\t\tStrip SPIR-V debug information (line numbers, names, "
177 "etc).\n");
178 printf("\t--canonicalize-SPV\n"
179 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
180 exit(0);
181 } else {
182 printf("\nUnrecognized option: %s\n", argv[i]);
183 printf("\nUse --help or -h for option list.\n");
184 exit(0);
185 }
186
187 /*
188 * Since the above "consume" inputs, update argv
189 * so that it contains the trimmed list of args for glutInit
190 */
191
192 argv[n] = argv[i];
193 n++;
194 }
195 }
196
GetFormat(VkInstance instance,vk_testing::Device * device)197 VkFormat VkTestFramework::GetFormat(VkInstance instance, vk_testing::Device *device) {
198 VkFormatProperties format_props;
199
200 vkGetPhysicalDeviceFormatProperties(device->phy().handle(), VK_FORMAT_B8G8R8A8_UNORM, &format_props);
201 if (format_props.linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ||
202 format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) {
203 return VK_FORMAT_B8G8R8A8_UNORM;
204 }
205 vkGetPhysicalDeviceFormatProperties(device->phy().handle(), VK_FORMAT_R8G8B8A8_UNORM, &format_props);
206 if (format_props.linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ||
207 format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) {
208 return VK_FORMAT_R8G8B8A8_UNORM;
209 }
210 printf("Error - device does not support VK_FORMAT_B8G8R8A8_UNORM nor "
211 "VK_FORMAT_R8G8B8A8_UNORM - exiting\n");
212 exit(1);
213 }
214
Finish()215 void VkTestFramework::Finish() {}
216
217 //
218 // These are the default resources for TBuiltInResources, used for both
219 // - parsing this string for the case where the user didn't supply one
220 // - dumping out a template for user construction of a config file
221 //
222 static const char *DefaultConfig = "MaxLights 32\n"
223 "MaxClipPlanes 6\n"
224 "MaxTextureUnits 32\n"
225 "MaxTextureCoords 32\n"
226 "MaxVertexAttribs 64\n"
227 "MaxVertexUniformComponents 4096\n"
228 "MaxVaryingFloats 64\n"
229 "MaxVertexTextureImageUnits 32\n"
230 "MaxCombinedTextureImageUnits 80\n"
231 "MaxTextureImageUnits 32\n"
232 "MaxFragmentUniformComponents 4096\n"
233 "MaxDrawBuffers 32\n"
234 "MaxVertexUniformVectors 128\n"
235 "MaxVaryingVectors 8\n"
236 "MaxFragmentUniformVectors 16\n"
237 "MaxVertexOutputVectors 16\n"
238 "MaxFragmentInputVectors 15\n"
239 "MinProgramTexelOffset -8\n"
240 "MaxProgramTexelOffset 7\n"
241 "MaxClipDistances 8\n"
242 "MaxComputeWorkGroupCountX 65535\n"
243 "MaxComputeWorkGroupCountY 65535\n"
244 "MaxComputeWorkGroupCountZ 65535\n"
245 "MaxComputeWorkGroupSizeX 1024\n"
246 "MaxComputeWorkGroupSizeY 1024\n"
247 "MaxComputeWorkGroupSizeZ 64\n"
248 "MaxComputeUniformComponents 1024\n"
249 "MaxComputeTextureImageUnits 16\n"
250 "MaxComputeImageUniforms 8\n"
251 "MaxComputeAtomicCounters 8\n"
252 "MaxComputeAtomicCounterBuffers 1\n"
253 "MaxVaryingComponents 60\n"
254 "MaxVertexOutputComponents 64\n"
255 "MaxGeometryInputComponents 64\n"
256 "MaxGeometryOutputComponents 128\n"
257 "MaxFragmentInputComponents 128\n"
258 "MaxImageUnits 8\n"
259 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
260 "MaxCombinedShaderOutputResources 8\n"
261 "MaxImageSamples 0\n"
262 "MaxVertexImageUniforms 0\n"
263 "MaxTessControlImageUniforms 0\n"
264 "MaxTessEvaluationImageUniforms 0\n"
265 "MaxGeometryImageUniforms 0\n"
266 "MaxFragmentImageUniforms 8\n"
267 "MaxCombinedImageUniforms 8\n"
268 "MaxGeometryTextureImageUnits 16\n"
269 "MaxGeometryOutputVertices 256\n"
270 "MaxGeometryTotalOutputComponents 1024\n"
271 "MaxGeometryUniformComponents 1024\n"
272 "MaxGeometryVaryingComponents 64\n"
273 "MaxTessControlInputComponents 128\n"
274 "MaxTessControlOutputComponents 128\n"
275 "MaxTessControlTextureImageUnits 16\n"
276 "MaxTessControlUniformComponents 1024\n"
277 "MaxTessControlTotalOutputComponents 4096\n"
278 "MaxTessEvaluationInputComponents 128\n"
279 "MaxTessEvaluationOutputComponents 128\n"
280 "MaxTessEvaluationTextureImageUnits 16\n"
281 "MaxTessEvaluationUniformComponents 1024\n"
282 "MaxTessPatchComponents 120\n"
283 "MaxPatchVertices 32\n"
284 "MaxTessGenLevel 64\n"
285 "MaxViewports 16\n"
286 "MaxVertexAtomicCounters 0\n"
287 "MaxTessControlAtomicCounters 0\n"
288 "MaxTessEvaluationAtomicCounters 0\n"
289 "MaxGeometryAtomicCounters 0\n"
290 "MaxFragmentAtomicCounters 8\n"
291 "MaxCombinedAtomicCounters 8\n"
292 "MaxAtomicCounterBindings 1\n"
293 "MaxVertexAtomicCounterBuffers 0\n"
294 "MaxTessControlAtomicCounterBuffers 0\n"
295 "MaxTessEvaluationAtomicCounterBuffers 0\n"
296 "MaxGeometryAtomicCounterBuffers 0\n"
297 "MaxFragmentAtomicCounterBuffers 1\n"
298 "MaxCombinedAtomicCounterBuffers 1\n"
299 "MaxAtomicCounterBufferSize 16384\n"
300 "MaxTransformFeedbackBuffers 4\n"
301 "MaxTransformFeedbackInterleavedComponents 64\n"
302 "MaxCullDistances 8\n"
303 "MaxCombinedClipAndCullDistances 8\n"
304 "MaxSamples 4\n"
305
306 "nonInductiveForLoops 1\n"
307 "whileLoops 1\n"
308 "doWhileLoops 1\n"
309 "generalUniformIndexing 1\n"
310 "generalAttributeMatrixVectorIndexing 1\n"
311 "generalVaryingIndexing 1\n"
312 "generalSamplerIndexing 1\n"
313 "generalVariableIndexing 1\n"
314 "generalConstantMatrixVectorIndexing 1\n";
315
316 //
317 // *.conf => this is a config file that can set limits/resources
318 //
SetConfigFile(const std::string & name)319 bool VkTestFramework::SetConfigFile(const std::string &name) {
320 if (name.size() < 5)
321 return false;
322
323 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
324 ConfigFile = name;
325 return true;
326 }
327
328 return false;
329 }
330
331 //
332 // Parse either a .conf file provided by the user or the default string above.
333 //
ProcessConfigFile()334 void VkTestFramework::ProcessConfigFile() {
335 char **configStrings = 0;
336 char *config = 0;
337 if (ConfigFile.size() > 0) {
338 configStrings = ReadFileData(ConfigFile.c_str());
339 if (configStrings)
340 config = *configStrings;
341 else {
342 printf("Error opening configuration file; will instead use the "
343 "default configuration\n");
344 }
345 }
346
347 if (config == 0) {
348 config = (char *)alloca(strlen(DefaultConfig) + 1);
349 strcpy(config, DefaultConfig);
350 }
351
352 const char *delims = " \t\n\r";
353 const char *token = strtok(config, delims);
354 while (token) {
355 const char *valueStr = strtok(0, delims);
356 if (valueStr == 0 || !(valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
357 printf("Error: '%s' bad .conf file. Each name must be followed by "
358 "one number.\n",
359 valueStr ? valueStr : "");
360 return;
361 }
362 int value = atoi(valueStr);
363
364 if (strcmp(token, "MaxLights") == 0)
365 Resources.maxLights = value;
366 else if (strcmp(token, "MaxClipPlanes") == 0)
367 Resources.maxClipPlanes = value;
368 else if (strcmp(token, "MaxTextureUnits") == 0)
369 Resources.maxTextureUnits = value;
370 else if (strcmp(token, "MaxTextureCoords") == 0)
371 Resources.maxTextureCoords = value;
372 else if (strcmp(token, "MaxVertexAttribs") == 0)
373 Resources.maxVertexAttribs = value;
374 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
375 Resources.maxVertexUniformComponents = value;
376 else if (strcmp(token, "MaxVaryingFloats") == 0)
377 Resources.maxVaryingFloats = value;
378 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
379 Resources.maxVertexTextureImageUnits = value;
380 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
381 Resources.maxCombinedTextureImageUnits = value;
382 else if (strcmp(token, "MaxTextureImageUnits") == 0)
383 Resources.maxTextureImageUnits = value;
384 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
385 Resources.maxFragmentUniformComponents = value;
386 else if (strcmp(token, "MaxDrawBuffers") == 0)
387 Resources.maxDrawBuffers = value;
388 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
389 Resources.maxVertexUniformVectors = value;
390 else if (strcmp(token, "MaxVaryingVectors") == 0)
391 Resources.maxVaryingVectors = value;
392 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
393 Resources.maxFragmentUniformVectors = value;
394 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
395 Resources.maxVertexOutputVectors = value;
396 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
397 Resources.maxFragmentInputVectors = value;
398 else if (strcmp(token, "MinProgramTexelOffset") == 0)
399 Resources.minProgramTexelOffset = value;
400 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
401 Resources.maxProgramTexelOffset = value;
402 else if (strcmp(token, "MaxClipDistances") == 0)
403 Resources.maxClipDistances = value;
404 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
405 Resources.maxComputeWorkGroupCountX = value;
406 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
407 Resources.maxComputeWorkGroupCountY = value;
408 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
409 Resources.maxComputeWorkGroupCountZ = value;
410 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
411 Resources.maxComputeWorkGroupSizeX = value;
412 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
413 Resources.maxComputeWorkGroupSizeY = value;
414 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
415 Resources.maxComputeWorkGroupSizeZ = value;
416 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
417 Resources.maxComputeUniformComponents = value;
418 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
419 Resources.maxComputeTextureImageUnits = value;
420 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
421 Resources.maxComputeImageUniforms = value;
422 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
423 Resources.maxComputeAtomicCounters = value;
424 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
425 Resources.maxComputeAtomicCounterBuffers = value;
426 else if (strcmp(token, "MaxVaryingComponents") == 0)
427 Resources.maxVaryingComponents = value;
428 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
429 Resources.maxVertexOutputComponents = value;
430 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
431 Resources.maxGeometryInputComponents = value;
432 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
433 Resources.maxGeometryOutputComponents = value;
434 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
435 Resources.maxFragmentInputComponents = value;
436 else if (strcmp(token, "MaxImageUnits") == 0)
437 Resources.maxImageUnits = value;
438 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
439 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
440 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
441 Resources.maxCombinedShaderOutputResources = value;
442 else if (strcmp(token, "MaxImageSamples") == 0)
443 Resources.maxImageSamples = value;
444 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
445 Resources.maxVertexImageUniforms = value;
446 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
447 Resources.maxTessControlImageUniforms = value;
448 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
449 Resources.maxTessEvaluationImageUniforms = value;
450 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
451 Resources.maxGeometryImageUniforms = value;
452 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
453 Resources.maxFragmentImageUniforms = value;
454 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
455 Resources.maxCombinedImageUniforms = value;
456 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
457 Resources.maxGeometryTextureImageUnits = value;
458 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
459 Resources.maxGeometryOutputVertices = value;
460 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
461 Resources.maxGeometryTotalOutputComponents = value;
462 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
463 Resources.maxGeometryUniformComponents = value;
464 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
465 Resources.maxGeometryVaryingComponents = value;
466 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
467 Resources.maxTessControlInputComponents = value;
468 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
469 Resources.maxTessControlOutputComponents = value;
470 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
471 Resources.maxTessControlTextureImageUnits = value;
472 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
473 Resources.maxTessControlUniformComponents = value;
474 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
475 Resources.maxTessControlTotalOutputComponents = value;
476 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
477 Resources.maxTessEvaluationInputComponents = value;
478 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
479 Resources.maxTessEvaluationOutputComponents = value;
480 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
481 Resources.maxTessEvaluationTextureImageUnits = value;
482 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
483 Resources.maxTessEvaluationUniformComponents = value;
484 else if (strcmp(token, "MaxTessPatchComponents") == 0)
485 Resources.maxTessPatchComponents = value;
486 else if (strcmp(token, "MaxPatchVertices") == 0)
487 Resources.maxPatchVertices = value;
488 else if (strcmp(token, "MaxTessGenLevel") == 0)
489 Resources.maxTessGenLevel = value;
490 else if (strcmp(token, "MaxViewports") == 0)
491 Resources.maxViewports = value;
492 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
493 Resources.maxVertexAtomicCounters = value;
494 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
495 Resources.maxTessControlAtomicCounters = value;
496 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
497 Resources.maxTessEvaluationAtomicCounters = value;
498 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
499 Resources.maxGeometryAtomicCounters = value;
500 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
501 Resources.maxFragmentAtomicCounters = value;
502 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
503 Resources.maxCombinedAtomicCounters = value;
504 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
505 Resources.maxAtomicCounterBindings = value;
506 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
507 Resources.maxVertexAtomicCounterBuffers = value;
508 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
509 Resources.maxTessControlAtomicCounterBuffers = value;
510 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
511 Resources.maxTessEvaluationAtomicCounterBuffers = value;
512 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
513 Resources.maxGeometryAtomicCounterBuffers = value;
514 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
515 Resources.maxFragmentAtomicCounterBuffers = value;
516 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
517 Resources.maxCombinedAtomicCounterBuffers = value;
518 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
519 Resources.maxAtomicCounterBufferSize = value;
520 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
521 Resources.maxTransformFeedbackBuffers = value;
522 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
523 Resources.maxTransformFeedbackInterleavedComponents = value;
524 else if (strcmp(token, "MaxCullDistances") == 0)
525 Resources.maxCullDistances = value;
526 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
527 Resources.maxCombinedClipAndCullDistances = value;
528 else if (strcmp(token, "MaxSamples") == 0)
529 Resources.maxSamples = value;
530
531 else if (strcmp(token, "nonInductiveForLoops") == 0)
532 Resources.limits.nonInductiveForLoops = (value != 0);
533 else if (strcmp(token, "whileLoops") == 0)
534 Resources.limits.whileLoops = (value != 0);
535 else if (strcmp(token, "doWhileLoops") == 0)
536 Resources.limits.doWhileLoops = (value != 0);
537 else if (strcmp(token, "generalUniformIndexing") == 0)
538 Resources.limits.generalUniformIndexing = (value != 0);
539 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
540 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
541 else if (strcmp(token, "generalVaryingIndexing") == 0)
542 Resources.limits.generalVaryingIndexing = (value != 0);
543 else if (strcmp(token, "generalSamplerIndexing") == 0)
544 Resources.limits.generalSamplerIndexing = (value != 0);
545 else if (strcmp(token, "generalVariableIndexing") == 0)
546 Resources.limits.generalVariableIndexing = (value != 0);
547 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
548 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
549 else
550 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
551
552 token = strtok(0, delims);
553 }
554 if (configStrings)
555 FreeFileData(configStrings);
556 }
557
SetMessageOptions(EShMessages & messages)558 void VkTestFramework::SetMessageOptions(EShMessages &messages) {
559 if (m_compile_options & EOptionRelaxedErrors)
560 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
561 if (m_compile_options & EOptionIntermediate)
562 messages = (EShMessages)(messages | EShMsgAST);
563 if (m_compile_options & EOptionSuppressWarnings)
564 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
565 }
566
567 //
568 // Malloc a string of sufficient size and read a string into it.
569 //
ReadFileData(const char * fileName)570 char **VkTestFramework::ReadFileData(const char *fileName) {
571 FILE *in;
572 #if defined(_WIN32) && defined(__GNUC__)
573 in = fopen(fileName, "r");
574 int errorCode = in ? 0 : 1;
575 #else
576 int errorCode = fopen_s(&in, fileName, "r");
577 #endif
578
579 char *fdata;
580 size_t count = 0;
581 const int maxSourceStrings = 5;
582 char **return_data = (char **)malloc(sizeof(char *) * (maxSourceStrings + 1));
583
584 if (errorCode) {
585 printf("Error: unable to open input file: %s\n", fileName);
586 return 0;
587 }
588
589 while (fgetc(in) != EOF)
590 count++;
591
592 fseek(in, 0, SEEK_SET);
593
594 if (!(fdata = (char *)malloc(count + 2))) {
595 printf("Error allocating memory\n");
596 return 0;
597 }
598 if (fread(fdata, 1, count, in) != count) {
599 printf("Error reading input file: %s\n", fileName);
600 return 0;
601 }
602 fdata[count] = '\0';
603 fclose(in);
604 if (count == 0) {
605 return_data[0] = (char *)malloc(count + 2);
606 return_data[0][0] = '\0';
607 m_num_shader_strings = 0;
608 return return_data;
609 } else
610 m_num_shader_strings = 1;
611
612 size_t len = (int)(ceil)((float)count / (float)m_num_shader_strings);
613 size_t ptr_len = 0, i = 0;
614 while (count > 0) {
615 return_data[i] = (char *)malloc(len + 2);
616 memcpy(return_data[i], fdata + ptr_len, len);
617 return_data[i][len] = '\0';
618 count -= (len);
619 ptr_len += (len);
620 if (count < len) {
621 if (count == 0) {
622 m_num_shader_strings = (i + 1);
623 break;
624 }
625 len = count;
626 }
627 ++i;
628 }
629 return return_data;
630 }
631
FreeFileData(char ** data)632 void VkTestFramework::FreeFileData(char **data) {
633 for (int i = 0; i < m_num_shader_strings; i++)
634 free(data[i]);
635 }
636
637 //
638 // Deduce the language from the filename. Files must end in one of the
639 // following extensions:
640 //
641 // .vert = vertex
642 // .tesc = tessellation control
643 // .tese = tessellation evaluation
644 // .geom = geometry
645 // .frag = fragment
646 // .comp = compute
647 //
FindLanguage(const std::string & name)648 EShLanguage VkTestFramework::FindLanguage(const std::string &name) {
649 size_t ext = name.rfind('.');
650 if (ext == std::string::npos) {
651 return EShLangVertex;
652 }
653
654 std::string suffix = name.substr(ext + 1, std::string::npos);
655 if (suffix == "vert")
656 return EShLangVertex;
657 else if (suffix == "tesc")
658 return EShLangTessControl;
659 else if (suffix == "tese")
660 return EShLangTessEvaluation;
661 else if (suffix == "geom")
662 return EShLangGeometry;
663 else if (suffix == "frag")
664 return EShLangFragment;
665 else if (suffix == "comp")
666 return EShLangCompute;
667
668 return EShLangVertex;
669 }
670
671 //
672 // Convert VK shader type to compiler's
673 //
FindLanguage(const VkShaderStageFlagBits shader_type)674 EShLanguage VkTestFramework::FindLanguage(const VkShaderStageFlagBits shader_type) {
675 switch (shader_type) {
676 case VK_SHADER_STAGE_VERTEX_BIT:
677 return EShLangVertex;
678
679 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
680 return EShLangTessControl;
681
682 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
683 return EShLangTessEvaluation;
684
685 case VK_SHADER_STAGE_GEOMETRY_BIT:
686 return EShLangGeometry;
687
688 case VK_SHADER_STAGE_FRAGMENT_BIT:
689 return EShLangFragment;
690
691 case VK_SHADER_STAGE_COMPUTE_BIT:
692 return EShLangCompute;
693
694 default:
695 return EShLangVertex;
696 }
697 }
698
699 //
700 // Compile a given string containing GLSL into SPV for use by VK
701 // Return value of false means an error was encountered.
702 //
GLSLtoSPV(const VkShaderStageFlagBits shader_type,const char * pshader,std::vector<unsigned int> & spirv)703 bool VkTestFramework::GLSLtoSPV(const VkShaderStageFlagBits shader_type, const char *pshader, std::vector<unsigned int> &spirv) {
704 glslang::TProgram program;
705 const char *shaderStrings[1];
706
707 // TODO: Do we want to load a special config file depending on the
708 // shader source? Optional name maybe?
709 // SetConfigFile(fileName);
710
711 ProcessConfigFile();
712
713 EShMessages messages = EShMsgDefault;
714 SetMessageOptions(messages);
715 messages = static_cast<EShMessages>(messages | EShMsgSpvRules | EShMsgVulkanRules);
716
717 EShLanguage stage = FindLanguage(shader_type);
718 glslang::TShader *shader = new glslang::TShader(stage);
719
720 shaderStrings[0] = pshader;
721 shader->setStrings(shaderStrings, 1);
722
723 if (!shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
724
725 if (!(m_compile_options & EOptionSuppressInfolog)) {
726 puts(shader->getInfoLog());
727 puts(shader->getInfoDebugLog());
728 }
729
730 return false; // something didn't work
731 }
732
733 program.addShader(shader);
734
735 //
736 // Program-level processing...
737 //
738
739 if (!program.link(messages)) {
740
741 if (!(m_compile_options & EOptionSuppressInfolog)) {
742 puts(shader->getInfoLog());
743 puts(shader->getInfoDebugLog());
744 }
745
746 return false;
747 }
748
749 if (m_compile_options & EOptionDumpReflection) {
750 program.buildReflection();
751 program.dumpReflection();
752 }
753
754 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
755
756 //
757 // Test the different modes of SPIR-V modification
758 //
759 if (this->m_canonicalize_spv) {
760 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
761 }
762
763 if (this->m_strip_spv) {
764 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
765 }
766
767 if (this->m_do_everything_spv) {
768 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);
769 }
770
771 delete shader;
772
773 return true;
774 }
775