2 * Copyright (c) 2015-2016 The Khronos Group Inc.
3 * Copyright (c) 2015-2016 Valve Corporation
4 * Copyright (c) 2015-2016 LunarG, Inc.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * Author: Chia-I Wu <olvaffe@gmail.com>
19 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
20 * Author: Tony Barbour <tony@LunarG.com>
23 #include "vktestframework.h"
24 #include "vkrenderframework.h"
25 // TODO FIXME remove this once glslang doesn't define this
27 #include "SPIRV/GlslangToSpv.h"
28 #include "SPIRV/SPVRemapper.h"
32 #if defined(PATH_MAX) && !defined(MAX_PATH)
33 #define MAX_PATH PATH_MAX
37 #define ERR_EXIT(err_msg, err_class) \
39 MessageBox(NULL, err_msg, err_class, MB_OK); \
44 #define ERR_EXIT(err_msg, err_class) \
52 #define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \
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"); \
60 #define GET_DEVICE_PROC_ADDR(dev, entrypoint) \
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"); \
68 // Command-line options
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,
83 EOptionDefaultDesktop = 0x1000,
86 struct SwapchainBuffers {
96 int fopen_s(FILE **pFile, const char *filename, const char *mode) {
97 if (!pFile || !filename || !mode) {
101 FILE *f = fopen(filename, mode);
116 // Set up environment for GLSL compiler
117 // Must be done once per process
118 void TestEnvironment::SetUp() {
119 // Initialize GLSL to SPV compiler utility
120 glslang::InitializeProcess();
122 vk_testing::set_error_callback(test_error_callback);
125 void TestEnvironment::TearDown() { glslang::FinalizeProcess(); }
127 VkTestFramework::VkTestFramework() : m_compile_options(0), m_num_shader_strings(0) {}
129 VkTestFramework::~VkTestFramework() {}
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;
139 bool VkTestFramework::optionMatch(const char *option, char *optionLine) {
140 if (strncmp(option, optionLine, strlen(option)) == 0)
146 void VkTestFramework::InitArgs(int *argc, char *argv[]) {
149 for (i = 1, n = 1; i < *argc; i++) {
150 if (optionMatch("--no-SPV", argv[i]))
152 else if (optionMatch("--strip-SPV", argv[i]))
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 "
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 "
169 "\t\tSetting RENDERTEST_GOLDEN_DIR environment variable can "
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, "
178 printf("\t--canonicalize-SPV\n"
179 "\t\tRemap SPIR-V ids before submission to aid compression.\n");
182 printf("\nUnrecognized option: %s\n", argv[i]);
183 printf("\nUse --help or -h for option list.\n");
188 * Since the above "consume" inputs, update argv
189 * so that it contains the trimmed list of args for glutInit
197 VkFormat VkTestFramework::GetFormat(VkInstance instance, vk_testing::Device *device) {
198 VkFormatProperties format_props;
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;
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;
210 printf("Error - device does not support VK_FORMAT_B8G8R8A8_UNORM nor "
211 "VK_FORMAT_R8G8B8A8_UNORM - exiting\n");
215 void VkTestFramework::Finish() {}
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
222 static const char *DefaultConfig = "MaxLights 32\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"
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"
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"
306 "nonInductiveForLoops 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";
317 // *.conf => this is a config file that can set limits/resources
319 bool VkTestFramework::SetConfigFile(const std::string &name) {
323 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
332 // Parse either a .conf file provided by the user or the default string above.
334 void VkTestFramework::ProcessConfigFile() {
335 char **configStrings = 0;
337 if (ConfigFile.size() > 0) {
338 configStrings = ReadFileData(ConfigFile.c_str());
340 config = *configStrings;
342 printf("Error opening configuration file; will instead use the "
343 "default configuration\n");
348 config = (char *)alloca(strlen(DefaultConfig) + 1);
349 strcpy(config, DefaultConfig);
352 const char *delims = " \t\n\r";
353 const char *token = strtok(config, delims);
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 "
359 valueStr ? valueStr : "");
362 int value = atoi(valueStr);
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;
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);
550 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
552 token = strtok(0, delims);
555 FreeFileData(configStrings);
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);
568 // Malloc a string of sufficient size and read a string into it.
570 char **VkTestFramework::ReadFileData(const char *fileName) {
572 #if defined(_WIN32) && defined(__GNUC__)
573 in = fopen(fileName, "r");
574 int errorCode = in ? 0 : 1;
576 int errorCode = fopen_s(&in, fileName, "r");
581 const int maxSourceStrings = 5;
582 char **return_data = (char **)malloc(sizeof(char *) * (maxSourceStrings + 1));
585 printf("Error: unable to open input file: %s\n", fileName);
589 while (fgetc(in) != EOF)
592 fseek(in, 0, SEEK_SET);
594 if (!(fdata = (char *)malloc(count + 2))) {
595 printf("Error allocating memory\n");
598 if (fread(fdata, 1, count, in) != count) {
599 printf("Error reading input file: %s\n", fileName);
605 return_data[0] = (char *)malloc(count + 2);
606 return_data[0][0] = '\0';
607 m_num_shader_strings = 0;
610 m_num_shader_strings = 1;
612 size_t len = (int)(ceil)((float)count / (float)m_num_shader_strings);
613 size_t ptr_len = 0, i = 0;
615 return_data[i] = (char *)malloc(len + 2);
616 memcpy(return_data[i], fdata + ptr_len, len);
617 return_data[i][len] = '\0';
622 m_num_shader_strings = (i + 1);
632 void VkTestFramework::FreeFileData(char **data) {
633 for (int i = 0; i < m_num_shader_strings; i++)
638 // Deduce the language from the filename. Files must end in one of the
639 // following extensions:
642 // .tesc = tessellation control
643 // .tese = tessellation evaluation
648 EShLanguage VkTestFramework::FindLanguage(const std::string &name) {
649 size_t ext = name.rfind('.');
650 if (ext == std::string::npos) {
651 return EShLangVertex;
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;
668 return EShLangVertex;
672 // Convert VK shader type to compiler's
674 EShLanguage VkTestFramework::FindLanguage(const VkShaderStageFlagBits shader_type) {
675 switch (shader_type) {
676 case VK_SHADER_STAGE_VERTEX_BIT:
677 return EShLangVertex;
679 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
680 return EShLangTessControl;
682 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
683 return EShLangTessEvaluation;
685 case VK_SHADER_STAGE_GEOMETRY_BIT:
686 return EShLangGeometry;
688 case VK_SHADER_STAGE_FRAGMENT_BIT:
689 return EShLangFragment;
691 case VK_SHADER_STAGE_COMPUTE_BIT:
692 return EShLangCompute;
695 return EShLangVertex;
700 // Compile a given string containing GLSL into SPV for use by VK
701 // Return value of false means an error was encountered.
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];
707 // TODO: Do we want to load a special config file depending on the
708 // shader source? Optional name maybe?
709 // SetConfigFile(fileName);
713 EShMessages messages = EShMsgDefault;
714 SetMessageOptions(messages);
715 messages = static_cast<EShMessages>(messages | EShMsgSpvRules | EShMsgVulkanRules);
717 EShLanguage stage = FindLanguage(shader_type);
718 glslang::TShader *shader = new glslang::TShader(stage);
720 shaderStrings[0] = pshader;
721 shader->setStrings(shaderStrings, 1);
723 if (!shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) {
725 if (!(m_compile_options & EOptionSuppressInfolog)) {
726 puts(shader->getInfoLog());
727 puts(shader->getInfoDebugLog());
730 return false; // something didn't work
733 program.addShader(shader);
736 // Program-level processing...
739 if (!program.link(messages)) {
741 if (!(m_compile_options & EOptionSuppressInfolog)) {
742 puts(shader->getInfoLog());
743 puts(shader->getInfoDebugLog());
749 if (m_compile_options & EOptionDumpReflection) {
750 program.buildReflection();
751 program.dumpReflection();
754 glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
757 // Test the different modes of SPIR-V modification
759 if (this->m_canonicalize_spv) {
760 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP);
763 if (this->m_strip_spv) {
764 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP);
767 if (this->m_do_everything_spv) {
768 spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING);