Externals: Add glslang from Vulkan SDK v1.0.21.1

This commit is contained in:
Stenzek
2016-06-26 15:06:20 +10:00
parent 49e57df2b6
commit 951fc44d86
135 changed files with 74837 additions and 0 deletions

View File

@ -0,0 +1,48 @@
add_library(glslang-default-resource-limits
${CMAKE_CURRENT_SOURCE_DIR}/ResourceLimits.cpp
)
set_property(TARGET glslang-default-resource-limits PROPERTY FOLDER glslang)
target_include_directories(glslang-default-resource-limits
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
PUBLIC ${PROJECT_SOURCE_DIR}
)
set(SOURCES StandAlone.cpp)
set(REMAPPER_SOURCES spirv-remap.cpp)
add_executable(glslangValidator ${SOURCES})
add_executable(spirv-remap ${REMAPPER_SOURCES})
set_property(TARGET glslangValidator PROPERTY FOLDER tools)
set_property(TARGET spirv-remap PROPERTY FOLDER tools)
glslang_set_link_args(glslangValidator)
glslang_set_link_args(spirv-remap)
set(LIBRARIES
glslang
OGLCompiler
OSDependent
HLSL
SPIRV
glslang-default-resource-limits)
if(WIN32)
set(LIBRARIES ${LIBRARIES} psapi)
elseif(UNIX)
if(NOT ANDROID)
set(LIBRARIES ${LIBRARIES} pthread)
endif()
endif(WIN32)
target_link_libraries(glslangValidator ${LIBRARIES})
target_link_libraries(spirv-remap ${LIBRARIES})
if(WIN32)
source_group("Source" FILES ${SOURCES})
endif(WIN32)
install(TARGETS glslangValidator
RUNTIME DESTINATION bin)
install(TARGETS spirv-remap
RUNTIME DESTINATION bin)

View File

@ -0,0 +1,445 @@
//
// Copyright (C) 2016 Google, Inc.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <cstdlib>
#include <cstring>
#include <sstream>
#include "ResourceLimits.h"
namespace glslang {
const TBuiltInResource DefaultTBuiltInResource = {
/* .MaxLights = */ 32,
/* .MaxClipPlanes = */ 6,
/* .MaxTextureUnits = */ 32,
/* .MaxTextureCoords = */ 32,
/* .MaxVertexAttribs = */ 64,
/* .MaxVertexUniformComponents = */ 4096,
/* .MaxVaryingFloats = */ 64,
/* .MaxVertexTextureImageUnits = */ 32,
/* .MaxCombinedTextureImageUnits = */ 80,
/* .MaxTextureImageUnits = */ 32,
/* .MaxFragmentUniformComponents = */ 4096,
/* .MaxDrawBuffers = */ 32,
/* .MaxVertexUniformVectors = */ 128,
/* .MaxVaryingVectors = */ 8,
/* .MaxFragmentUniformVectors = */ 16,
/* .MaxVertexOutputVectors = */ 16,
/* .MaxFragmentInputVectors = */ 15,
/* .MinProgramTexelOffset = */ -8,
/* .MaxProgramTexelOffset = */ 7,
/* .MaxClipDistances = */ 8,
/* .MaxComputeWorkGroupCountX = */ 65535,
/* .MaxComputeWorkGroupCountY = */ 65535,
/* .MaxComputeWorkGroupCountZ = */ 65535,
/* .MaxComputeWorkGroupSizeX = */ 1024,
/* .MaxComputeWorkGroupSizeY = */ 1024,
/* .MaxComputeWorkGroupSizeZ = */ 64,
/* .MaxComputeUniformComponents = */ 1024,
/* .MaxComputeTextureImageUnits = */ 16,
/* .MaxComputeImageUniforms = */ 8,
/* .MaxComputeAtomicCounters = */ 8,
/* .MaxComputeAtomicCounterBuffers = */ 1,
/* .MaxVaryingComponents = */ 60,
/* .MaxVertexOutputComponents = */ 64,
/* .MaxGeometryInputComponents = */ 64,
/* .MaxGeometryOutputComponents = */ 128,
/* .MaxFragmentInputComponents = */ 128,
/* .MaxImageUnits = */ 8,
/* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8,
/* .MaxCombinedShaderOutputResources = */ 8,
/* .MaxImageSamples = */ 0,
/* .MaxVertexImageUniforms = */ 0,
/* .MaxTessControlImageUniforms = */ 0,
/* .MaxTessEvaluationImageUniforms = */ 0,
/* .MaxGeometryImageUniforms = */ 0,
/* .MaxFragmentImageUniforms = */ 8,
/* .MaxCombinedImageUniforms = */ 8,
/* .MaxGeometryTextureImageUnits = */ 16,
/* .MaxGeometryOutputVertices = */ 256,
/* .MaxGeometryTotalOutputComponents = */ 1024,
/* .MaxGeometryUniformComponents = */ 1024,
/* .MaxGeometryVaryingComponents = */ 64,
/* .MaxTessControlInputComponents = */ 128,
/* .MaxTessControlOutputComponents = */ 128,
/* .MaxTessControlTextureImageUnits = */ 16,
/* .MaxTessControlUniformComponents = */ 1024,
/* .MaxTessControlTotalOutputComponents = */ 4096,
/* .MaxTessEvaluationInputComponents = */ 128,
/* .MaxTessEvaluationOutputComponents = */ 128,
/* .MaxTessEvaluationTextureImageUnits = */ 16,
/* .MaxTessEvaluationUniformComponents = */ 1024,
/* .MaxTessPatchComponents = */ 120,
/* .MaxPatchVertices = */ 32,
/* .MaxTessGenLevel = */ 64,
/* .MaxViewports = */ 16,
/* .MaxVertexAtomicCounters = */ 0,
/* .MaxTessControlAtomicCounters = */ 0,
/* .MaxTessEvaluationAtomicCounters = */ 0,
/* .MaxGeometryAtomicCounters = */ 0,
/* .MaxFragmentAtomicCounters = */ 8,
/* .MaxCombinedAtomicCounters = */ 8,
/* .MaxAtomicCounterBindings = */ 1,
/* .MaxVertexAtomicCounterBuffers = */ 0,
/* .MaxTessControlAtomicCounterBuffers = */ 0,
/* .MaxTessEvaluationAtomicCounterBuffers = */ 0,
/* .MaxGeometryAtomicCounterBuffers = */ 0,
/* .MaxFragmentAtomicCounterBuffers = */ 1,
/* .MaxCombinedAtomicCounterBuffers = */ 1,
/* .MaxAtomicCounterBufferSize = */ 16384,
/* .MaxTransformFeedbackBuffers = */ 4,
/* .MaxTransformFeedbackInterleavedComponents = */ 64,
/* .MaxCullDistances = */ 8,
/* .MaxCombinedClipAndCullDistances = */ 8,
/* .MaxSamples = */ 4,
/* .limits = */ {
/* .nonInductiveForLoops = */ 1,
/* .whileLoops = */ 1,
/* .doWhileLoops = */ 1,
/* .generalUniformIndexing = */ 1,
/* .generalAttributeMatrixVectorIndexing = */ 1,
/* .generalVaryingIndexing = */ 1,
/* .generalSamplerIndexing = */ 1,
/* .generalVariableIndexing = */ 1,
/* .generalConstantMatrixVectorIndexing = */ 1,
}};
std::string GetDefaultTBuiltInResourceString()
{
std::ostringstream ostream;
ostream << "MaxLights " << DefaultTBuiltInResource.maxLights << "\n"
<< "MaxClipPlanes " << DefaultTBuiltInResource.maxClipPlanes << "\n"
<< "MaxTextureUnits " << DefaultTBuiltInResource.maxTextureUnits << "\n"
<< "MaxTextureCoords " << DefaultTBuiltInResource.maxTextureCoords << "\n"
<< "MaxVertexAttribs " << DefaultTBuiltInResource.maxVertexAttribs << "\n"
<< "MaxVertexUniformComponents " << DefaultTBuiltInResource.maxVertexUniformComponents << "\n"
<< "MaxVaryingFloats " << DefaultTBuiltInResource.maxVaryingFloats << "\n"
<< "MaxVertexTextureImageUnits " << DefaultTBuiltInResource.maxVertexTextureImageUnits << "\n"
<< "MaxCombinedTextureImageUnits " << DefaultTBuiltInResource.maxCombinedTextureImageUnits << "\n"
<< "MaxTextureImageUnits " << DefaultTBuiltInResource.maxTextureImageUnits << "\n"
<< "MaxFragmentUniformComponents " << DefaultTBuiltInResource.maxFragmentUniformComponents << "\n"
<< "MaxDrawBuffers " << DefaultTBuiltInResource.maxDrawBuffers << "\n"
<< "MaxVertexUniformVectors " << DefaultTBuiltInResource.maxVertexUniformVectors << "\n"
<< "MaxVaryingVectors " << DefaultTBuiltInResource.maxVaryingVectors << "\n"
<< "MaxFragmentUniformVectors " << DefaultTBuiltInResource.maxFragmentUniformVectors << "\n"
<< "MaxVertexOutputVectors " << DefaultTBuiltInResource.maxVertexOutputVectors << "\n"
<< "MaxFragmentInputVectors " << DefaultTBuiltInResource.maxFragmentInputVectors << "\n"
<< "MinProgramTexelOffset " << DefaultTBuiltInResource.minProgramTexelOffset << "\n"
<< "MaxProgramTexelOffset " << DefaultTBuiltInResource.maxProgramTexelOffset << "\n"
<< "MaxClipDistances " << DefaultTBuiltInResource.maxClipDistances << "\n"
<< "MaxComputeWorkGroupCountX " << DefaultTBuiltInResource.maxComputeWorkGroupCountX << "\n"
<< "MaxComputeWorkGroupCountY " << DefaultTBuiltInResource.maxComputeWorkGroupCountY << "\n"
<< "MaxComputeWorkGroupCountZ " << DefaultTBuiltInResource.maxComputeWorkGroupCountZ << "\n"
<< "MaxComputeWorkGroupSizeX " << DefaultTBuiltInResource.maxComputeWorkGroupSizeX << "\n"
<< "MaxComputeWorkGroupSizeY " << DefaultTBuiltInResource.maxComputeWorkGroupSizeY << "\n"
<< "MaxComputeWorkGroupSizeZ " << DefaultTBuiltInResource.maxComputeWorkGroupSizeZ << "\n"
<< "MaxComputeUniformComponents " << DefaultTBuiltInResource.maxComputeUniformComponents << "\n"
<< "MaxComputeTextureImageUnits " << DefaultTBuiltInResource.maxComputeTextureImageUnits << "\n"
<< "MaxComputeImageUniforms " << DefaultTBuiltInResource.maxComputeImageUniforms << "\n"
<< "MaxComputeAtomicCounters " << DefaultTBuiltInResource.maxComputeAtomicCounters << "\n"
<< "MaxComputeAtomicCounterBuffers " << DefaultTBuiltInResource.maxComputeAtomicCounterBuffers << "\n"
<< "MaxVaryingComponents " << DefaultTBuiltInResource.maxVaryingComponents << "\n"
<< "MaxVertexOutputComponents " << DefaultTBuiltInResource.maxVertexOutputComponents << "\n"
<< "MaxGeometryInputComponents " << DefaultTBuiltInResource.maxGeometryInputComponents << "\n"
<< "MaxGeometryOutputComponents " << DefaultTBuiltInResource.maxGeometryOutputComponents << "\n"
<< "MaxFragmentInputComponents " << DefaultTBuiltInResource.maxFragmentInputComponents << "\n"
<< "MaxImageUnits " << DefaultTBuiltInResource.maxImageUnits << "\n"
<< "MaxCombinedImageUnitsAndFragmentOutputs " << DefaultTBuiltInResource.maxCombinedImageUnitsAndFragmentOutputs << "\n"
<< "MaxCombinedShaderOutputResources " << DefaultTBuiltInResource.maxCombinedShaderOutputResources << "\n"
<< "MaxImageSamples " << DefaultTBuiltInResource.maxImageSamples << "\n"
<< "MaxVertexImageUniforms " << DefaultTBuiltInResource.maxVertexImageUniforms << "\n"
<< "MaxTessControlImageUniforms " << DefaultTBuiltInResource.maxTessControlImageUniforms << "\n"
<< "MaxTessEvaluationImageUniforms " << DefaultTBuiltInResource.maxTessEvaluationImageUniforms << "\n"
<< "MaxGeometryImageUniforms " << DefaultTBuiltInResource.maxGeometryImageUniforms << "\n"
<< "MaxFragmentImageUniforms " << DefaultTBuiltInResource.maxFragmentImageUniforms << "\n"
<< "MaxCombinedImageUniforms " << DefaultTBuiltInResource.maxCombinedImageUniforms << "\n"
<< "MaxGeometryTextureImageUnits " << DefaultTBuiltInResource.maxGeometryTextureImageUnits << "\n"
<< "MaxGeometryOutputVertices " << DefaultTBuiltInResource.maxGeometryOutputVertices << "\n"
<< "MaxGeometryTotalOutputComponents " << DefaultTBuiltInResource.maxGeometryTotalOutputComponents << "\n"
<< "MaxGeometryUniformComponents " << DefaultTBuiltInResource.maxGeometryUniformComponents << "\n"
<< "MaxGeometryVaryingComponents " << DefaultTBuiltInResource.maxGeometryVaryingComponents << "\n"
<< "MaxTessControlInputComponents " << DefaultTBuiltInResource.maxTessControlInputComponents << "\n"
<< "MaxTessControlOutputComponents " << DefaultTBuiltInResource.maxTessControlOutputComponents << "\n"
<< "MaxTessControlTextureImageUnits " << DefaultTBuiltInResource.maxTessControlTextureImageUnits << "\n"
<< "MaxTessControlUniformComponents " << DefaultTBuiltInResource.maxTessControlUniformComponents << "\n"
<< "MaxTessControlTotalOutputComponents " << DefaultTBuiltInResource.maxTessControlTotalOutputComponents << "\n"
<< "MaxTessEvaluationInputComponents " << DefaultTBuiltInResource.maxTessEvaluationInputComponents << "\n"
<< "MaxTessEvaluationOutputComponents " << DefaultTBuiltInResource.maxTessEvaluationOutputComponents << "\n"
<< "MaxTessEvaluationTextureImageUnits " << DefaultTBuiltInResource.maxTessEvaluationTextureImageUnits << "\n"
<< "MaxTessEvaluationUniformComponents " << DefaultTBuiltInResource.maxTessEvaluationUniformComponents << "\n"
<< "MaxTessPatchComponents " << DefaultTBuiltInResource.maxTessPatchComponents << "\n"
<< "MaxPatchVertices " << DefaultTBuiltInResource.maxPatchVertices << "\n"
<< "MaxTessGenLevel " << DefaultTBuiltInResource.maxTessGenLevel << "\n"
<< "MaxViewports " << DefaultTBuiltInResource.maxViewports << "\n"
<< "MaxVertexAtomicCounters " << DefaultTBuiltInResource.maxVertexAtomicCounters << "\n"
<< "MaxTessControlAtomicCounters " << DefaultTBuiltInResource.maxTessControlAtomicCounters << "\n"
<< "MaxTessEvaluationAtomicCounters " << DefaultTBuiltInResource.maxTessEvaluationAtomicCounters << "\n"
<< "MaxGeometryAtomicCounters " << DefaultTBuiltInResource.maxGeometryAtomicCounters << "\n"
<< "MaxFragmentAtomicCounters " << DefaultTBuiltInResource.maxFragmentAtomicCounters << "\n"
<< "MaxCombinedAtomicCounters " << DefaultTBuiltInResource.maxCombinedAtomicCounters << "\n"
<< "MaxAtomicCounterBindings " << DefaultTBuiltInResource.maxAtomicCounterBindings << "\n"
<< "MaxVertexAtomicCounterBuffers " << DefaultTBuiltInResource.maxVertexAtomicCounterBuffers << "\n"
<< "MaxTessControlAtomicCounterBuffers " << DefaultTBuiltInResource.maxTessControlAtomicCounterBuffers << "\n"
<< "MaxTessEvaluationAtomicCounterBuffers " << DefaultTBuiltInResource.maxTessEvaluationAtomicCounterBuffers << "\n"
<< "MaxGeometryAtomicCounterBuffers " << DefaultTBuiltInResource.maxGeometryAtomicCounterBuffers << "\n"
<< "MaxFragmentAtomicCounterBuffers " << DefaultTBuiltInResource.maxFragmentAtomicCounterBuffers << "\n"
<< "MaxCombinedAtomicCounterBuffers " << DefaultTBuiltInResource.maxCombinedAtomicCounterBuffers << "\n"
<< "MaxAtomicCounterBufferSize " << DefaultTBuiltInResource.maxAtomicCounterBufferSize << "\n"
<< "MaxTransformFeedbackBuffers " << DefaultTBuiltInResource.maxTransformFeedbackBuffers << "\n"
<< "MaxTransformFeedbackInterleavedComponents " << DefaultTBuiltInResource.maxTransformFeedbackInterleavedComponents << "\n"
<< "MaxCullDistances " << DefaultTBuiltInResource.maxCullDistances << "\n"
<< "MaxCombinedClipAndCullDistances " << DefaultTBuiltInResource.maxCombinedClipAndCullDistances << "\n"
<< "MaxSamples " << DefaultTBuiltInResource.maxSamples << "\n"
<< "nonInductiveForLoops " << DefaultTBuiltInResource.limits.nonInductiveForLoops << "\n"
<< "whileLoops " << DefaultTBuiltInResource.limits.whileLoops << "\n"
<< "doWhileLoops " << DefaultTBuiltInResource.limits.doWhileLoops << "\n"
<< "generalUniformIndexing " << DefaultTBuiltInResource.limits.generalUniformIndexing << "\n"
<< "generalAttributeMatrixVectorIndexing " << DefaultTBuiltInResource.limits.generalAttributeMatrixVectorIndexing << "\n"
<< "generalVaryingIndexing " << DefaultTBuiltInResource.limits.generalVaryingIndexing << "\n"
<< "generalSamplerIndexing " << DefaultTBuiltInResource.limits.generalSamplerIndexing << "\n"
<< "generalVariableIndexing " << DefaultTBuiltInResource.limits.generalVariableIndexing << "\n"
<< "generalConstantMatrixVectorIndexing " << DefaultTBuiltInResource.limits.generalConstantMatrixVectorIndexing << "\n"
;
return ostream.str();
}
void DecodeResourceLimits(TBuiltInResource* resources, char* config)
{
const char* delims = " \t\n\r";
const char* token = strtok(config, delims);
while (token) {
const char* valueStr = strtok(0, delims);
if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
return;
}
int value = atoi(valueStr);
if (strcmp(token, "MaxLights") == 0)
resources->maxLights = value;
else if (strcmp(token, "MaxClipPlanes") == 0)
resources->maxClipPlanes = value;
else if (strcmp(token, "MaxTextureUnits") == 0)
resources->maxTextureUnits = value;
else if (strcmp(token, "MaxTextureCoords") == 0)
resources->maxTextureCoords = value;
else if (strcmp(token, "MaxVertexAttribs") == 0)
resources->maxVertexAttribs = value;
else if (strcmp(token, "MaxVertexUniformComponents") == 0)
resources->maxVertexUniformComponents = value;
else if (strcmp(token, "MaxVaryingFloats") == 0)
resources->maxVaryingFloats = value;
else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
resources->maxVertexTextureImageUnits = value;
else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
resources->maxCombinedTextureImageUnits = value;
else if (strcmp(token, "MaxTextureImageUnits") == 0)
resources->maxTextureImageUnits = value;
else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
resources->maxFragmentUniformComponents = value;
else if (strcmp(token, "MaxDrawBuffers") == 0)
resources->maxDrawBuffers = value;
else if (strcmp(token, "MaxVertexUniformVectors") == 0)
resources->maxVertexUniformVectors = value;
else if (strcmp(token, "MaxVaryingVectors") == 0)
resources->maxVaryingVectors = value;
else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
resources->maxFragmentUniformVectors = value;
else if (strcmp(token, "MaxVertexOutputVectors") == 0)
resources->maxVertexOutputVectors = value;
else if (strcmp(token, "MaxFragmentInputVectors") == 0)
resources->maxFragmentInputVectors = value;
else if (strcmp(token, "MinProgramTexelOffset") == 0)
resources->minProgramTexelOffset = value;
else if (strcmp(token, "MaxProgramTexelOffset") == 0)
resources->maxProgramTexelOffset = value;
else if (strcmp(token, "MaxClipDistances") == 0)
resources->maxClipDistances = value;
else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
resources->maxComputeWorkGroupCountX = value;
else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
resources->maxComputeWorkGroupCountY = value;
else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
resources->maxComputeWorkGroupCountZ = value;
else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
resources->maxComputeWorkGroupSizeX = value;
else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
resources->maxComputeWorkGroupSizeY = value;
else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
resources->maxComputeWorkGroupSizeZ = value;
else if (strcmp(token, "MaxComputeUniformComponents") == 0)
resources->maxComputeUniformComponents = value;
else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
resources->maxComputeTextureImageUnits = value;
else if (strcmp(token, "MaxComputeImageUniforms") == 0)
resources->maxComputeImageUniforms = value;
else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
resources->maxComputeAtomicCounters = value;
else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
resources->maxComputeAtomicCounterBuffers = value;
else if (strcmp(token, "MaxVaryingComponents") == 0)
resources->maxVaryingComponents = value;
else if (strcmp(token, "MaxVertexOutputComponents") == 0)
resources->maxVertexOutputComponents = value;
else if (strcmp(token, "MaxGeometryInputComponents") == 0)
resources->maxGeometryInputComponents = value;
else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
resources->maxGeometryOutputComponents = value;
else if (strcmp(token, "MaxFragmentInputComponents") == 0)
resources->maxFragmentInputComponents = value;
else if (strcmp(token, "MaxImageUnits") == 0)
resources->maxImageUnits = value;
else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
resources->maxCombinedImageUnitsAndFragmentOutputs = value;
else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
resources->maxCombinedShaderOutputResources = value;
else if (strcmp(token, "MaxImageSamples") == 0)
resources->maxImageSamples = value;
else if (strcmp(token, "MaxVertexImageUniforms") == 0)
resources->maxVertexImageUniforms = value;
else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
resources->maxTessControlImageUniforms = value;
else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
resources->maxTessEvaluationImageUniforms = value;
else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
resources->maxGeometryImageUniforms = value;
else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
resources->maxFragmentImageUniforms = value;
else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
resources->maxCombinedImageUniforms = value;
else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
resources->maxGeometryTextureImageUnits = value;
else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
resources->maxGeometryOutputVertices = value;
else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
resources->maxGeometryTotalOutputComponents = value;
else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
resources->maxGeometryUniformComponents = value;
else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
resources->maxGeometryVaryingComponents = value;
else if (strcmp(token, "MaxTessControlInputComponents") == 0)
resources->maxTessControlInputComponents = value;
else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
resources->maxTessControlOutputComponents = value;
else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
resources->maxTessControlTextureImageUnits = value;
else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
resources->maxTessControlUniformComponents = value;
else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
resources->maxTessControlTotalOutputComponents = value;
else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
resources->maxTessEvaluationInputComponents = value;
else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
resources->maxTessEvaluationOutputComponents = value;
else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
resources->maxTessEvaluationTextureImageUnits = value;
else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
resources->maxTessEvaluationUniformComponents = value;
else if (strcmp(token, "MaxTessPatchComponents") == 0)
resources->maxTessPatchComponents = value;
else if (strcmp(token, "MaxPatchVertices") == 0)
resources->maxPatchVertices = value;
else if (strcmp(token, "MaxTessGenLevel") == 0)
resources->maxTessGenLevel = value;
else if (strcmp(token, "MaxViewports") == 0)
resources->maxViewports = value;
else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
resources->maxVertexAtomicCounters = value;
else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
resources->maxTessControlAtomicCounters = value;
else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
resources->maxTessEvaluationAtomicCounters = value;
else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
resources->maxGeometryAtomicCounters = value;
else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
resources->maxFragmentAtomicCounters = value;
else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
resources->maxCombinedAtomicCounters = value;
else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
resources->maxAtomicCounterBindings = value;
else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
resources->maxVertexAtomicCounterBuffers = value;
else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
resources->maxTessControlAtomicCounterBuffers = value;
else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
resources->maxTessEvaluationAtomicCounterBuffers = value;
else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
resources->maxGeometryAtomicCounterBuffers = value;
else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
resources->maxFragmentAtomicCounterBuffers = value;
else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
resources->maxCombinedAtomicCounterBuffers = value;
else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
resources->maxAtomicCounterBufferSize = value;
else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
resources->maxTransformFeedbackBuffers = value;
else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
resources->maxTransformFeedbackInterleavedComponents = value;
else if (strcmp(token, "MaxCullDistances") == 0)
resources->maxCullDistances = value;
else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
resources->maxCombinedClipAndCullDistances = value;
else if (strcmp(token, "MaxSamples") == 0)
resources->maxSamples = value;
else if (strcmp(token, "nonInductiveForLoops") == 0)
resources->limits.nonInductiveForLoops = (value != 0);
else if (strcmp(token, "whileLoops") == 0)
resources->limits.whileLoops = (value != 0);
else if (strcmp(token, "doWhileLoops") == 0)
resources->limits.doWhileLoops = (value != 0);
else if (strcmp(token, "generalUniformIndexing") == 0)
resources->limits.generalUniformIndexing = (value != 0);
else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
resources->limits.generalAttributeMatrixVectorIndexing = (value != 0);
else if (strcmp(token, "generalVaryingIndexing") == 0)
resources->limits.generalVaryingIndexing = (value != 0);
else if (strcmp(token, "generalSamplerIndexing") == 0)
resources->limits.generalSamplerIndexing = (value != 0);
else if (strcmp(token, "generalVariableIndexing") == 0)
resources->limits.generalVariableIndexing = (value != 0);
else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
resources->limits.generalConstantMatrixVectorIndexing = (value != 0);
else
printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
token = strtok(0, delims);
}
}
} // end namespace glslang

View File

@ -0,0 +1,57 @@
//
// Copyright (C) 2016 Google, Inc.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#ifndef _STAND_ALONE_RESOURCE_LIMITS_INCLUDED_
#define _STAND_ALONE_RESOURCE_LIMITS_INCLUDED_
#include <string>
#include "glslang/Include/ResourceLimits.h"
namespace glslang {
// These are the default resources for TBuiltInResources, used for both
// - parsing this string for the case where the user didn't supply one,
// - dumping out a template for user construction of a config file.
extern const TBuiltInResource DefaultTBuiltInResource;
// Returns the DefaultTBuiltInResource as a human-readable string.
std::string GetDefaultTBuiltInResourceString();
// Decodes the resource limits from |config| to |resources|.
void DecodeResourceLimits(TBuiltInResource* resources, char* config);
} // end namespace glslang
#endif // _STAND_ALONE_RESOURCE_LIMITS_INCLUDED_

View File

@ -0,0 +1,914 @@
//
//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
//Copyright (C) 2013 LunarG, Inc.
//
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions
//are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//POSSIBILITY OF SUCH DAMAGE.
//
// this only applies to the standalone wrapper, not the front end in general
#define _CRT_SECURE_NO_WARNINGS
#include "ResourceLimits.h"
#include "Worklist.h"
#include "./../glslang/Include/ShHandle.h"
#include "./../glslang/Include/revision.h"
#include "./../glslang/Public/ShaderLang.h"
#include "../SPIRV/GlslangToSpv.h"
#include "../SPIRV/GLSL.std.450.h"
#include "../SPIRV/doc.h"
#include "../SPIRV/disassemble.h"
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "../glslang/OSDependent/osinclude.h"
extern "C" {
SH_IMPORT_EXPORT void ShOutputHtml();
}
// Command-line options
enum TOptions {
EOptionNone = 0,
EOptionIntermediate = (1 << 0),
EOptionSuppressInfolog = (1 << 1),
EOptionMemoryLeakMode = (1 << 2),
EOptionRelaxedErrors = (1 << 3),
EOptionGiveWarnings = (1 << 4),
EOptionLinkProgram = (1 << 5),
EOptionMultiThreaded = (1 << 6),
EOptionDumpConfig = (1 << 7),
EOptionDumpReflection = (1 << 8),
EOptionSuppressWarnings = (1 << 9),
EOptionDumpVersions = (1 << 10),
EOptionSpv = (1 << 11),
EOptionHumanReadableSpv = (1 << 12),
EOptionVulkanRules = (1 << 13),
EOptionDefaultDesktop = (1 << 14),
EOptionOutputPreprocessed = (1 << 15),
EOptionOutputHexadecimal = (1 << 16),
EOptionReadHlsl = (1 << 17),
EOptionCascadingErrors = (1 << 18),
};
//
// Return codes from main/exit().
//
enum TFailCode {
ESuccess = 0,
EFailUsage,
EFailCompile,
EFailLink,
EFailCompilerCreate,
EFailThreadCreate,
EFailLinkerCreate
};
//
// Forward declarations.
//
EShLanguage FindLanguage(const std::string& name);
void CompileFile(const char* fileName, ShHandle);
void usage();
void FreeFileData(char** data);
char** ReadFileData(const char* fileName);
void InfoLogMsg(const char* msg, const char* name, const int num);
// Globally track if any compile or link failure.
bool CompileFailed = false;
bool LinkFailed = false;
// Use to test breaking up a single shader file into multiple strings.
// Set in ReadFileData().
int NumShaderStrings;
TBuiltInResource Resources;
std::string ConfigFile;
//
// Parse either a .conf file provided by the user or the default from glslang::DefaultTBuiltInResource
//
void ProcessConfigFile()
{
char** configStrings = 0;
char* config = 0;
if (ConfigFile.size() > 0) {
configStrings = ReadFileData(ConfigFile.c_str());
if (configStrings)
config = *configStrings;
else {
printf("Error opening configuration file; will instead use the default configuration\n");
usage();
}
}
if (config == 0) {
Resources = glslang::DefaultTBuiltInResource;
return;
}
glslang::DecodeResourceLimits(&Resources, config);
if (configStrings)
FreeFileData(configStrings);
else
delete[] config;
}
// thread-safe list of shaders to asynchronously grab and compile
glslang::TWorklist Worklist;
// array of unique places to leave the shader names and infologs for the asynchronous compiles
glslang::TWorkItem** Work = 0;
int NumWorkItems = 0;
int Options = 0;
const char* ExecutableName = nullptr;
const char* binaryFileName = nullptr;
const char* entryPointName = nullptr;
//
// Create the default name for saving a binary if -o is not provided.
//
const char* GetBinaryName(EShLanguage stage)
{
const char* name;
if (binaryFileName == nullptr) {
switch (stage) {
case EShLangVertex: name = "vert.spv"; break;
case EShLangTessControl: name = "tesc.spv"; break;
case EShLangTessEvaluation: name = "tese.spv"; break;
case EShLangGeometry: name = "geom.spv"; break;
case EShLangFragment: name = "frag.spv"; break;
case EShLangCompute: name = "comp.spv"; break;
default: name = "unknown"; break;
}
} else
name = binaryFileName;
return name;
}
//
// *.conf => this is a config file that can set limits/resources
//
bool SetConfigFile(const std::string& name)
{
if (name.size() < 5)
return false;
if (name.compare(name.size() - 5, 5, ".conf") == 0) {
ConfigFile = name;
return true;
}
return false;
}
//
// Give error and exit with failure code.
//
void Error(const char* message)
{
printf("%s: Error %s (use -h for usage)\n", ExecutableName, message);
exit(EFailUsage);
}
//
// Do all command-line argument parsing. This includes building up the work-items
// to be processed later, and saving all the command-line options.
//
// Does not return (it exits) if command-line is fatally flawed.
//
void ProcessArguments(int argc, char* argv[])
{
ExecutableName = argv[0];
NumWorkItems = argc; // will include some empties where the '-' options were, but it doesn't matter, they'll be 0
Work = new glslang::TWorkItem*[NumWorkItems];
for (int w = 0; w < NumWorkItems; ++w)
Work[w] = 0;
argc--;
argv++;
for (; argc >= 1; argc--, argv++) {
if (argv[0][0] == '-') {
switch (argv[0][1]) {
case 'H':
Options |= EOptionHumanReadableSpv;
if ((Options & EOptionSpv) == 0) {
// default to Vulkan
Options |= EOptionSpv;
Options |= EOptionVulkanRules;
Options |= EOptionLinkProgram;
}
break;
case 'V':
Options |= EOptionSpv;
Options |= EOptionVulkanRules;
Options |= EOptionLinkProgram;
break;
case 'G':
Options |= EOptionSpv;
Options |= EOptionLinkProgram;
// undo a -H default to Vulkan
Options &= ~EOptionVulkanRules;
break;
case 'E':
Options |= EOptionOutputPreprocessed;
break;
case 'c':
Options |= EOptionDumpConfig;
break;
case 'C':
Options |= EOptionCascadingErrors;
break;
case 'd':
Options |= EOptionDefaultDesktop;
break;
case 'D':
Options |= EOptionReadHlsl;
break;
case 'e':
// HLSL todo: entry point handle needs much more sophistication.
// This is okay for one compilation unit with one entry point.
entryPointName = argv[1];
if (argc > 0) {
argc--;
argv++;
} else
Error("no <entry-point> provided for -e");
break;
case 'h':
usage();
break;
case 'i':
Options |= EOptionIntermediate;
break;
case 'l':
Options |= EOptionLinkProgram;
break;
case 'm':
Options |= EOptionMemoryLeakMode;
break;
case 'o':
binaryFileName = argv[1];
if (argc > 0) {
argc--;
argv++;
} else
Error("no <file> provided for -o");
break;
case 'q':
Options |= EOptionDumpReflection;
break;
case 'r':
Options |= EOptionRelaxedErrors;
break;
case 's':
Options |= EOptionSuppressInfolog;
break;
case 't':
#ifdef _WIN32
Options |= EOptionMultiThreaded;
#endif
break;
case 'v':
Options |= EOptionDumpVersions;
break;
case 'w':
Options |= EOptionSuppressWarnings;
break;
case 'x':
Options |= EOptionOutputHexadecimal;
break;
default:
usage();
break;
}
} else {
std::string name(argv[0]);
if (! SetConfigFile(name)) {
Work[argc] = new glslang::TWorkItem(name);
Worklist.add(Work[argc]);
}
}
}
// Make sure that -E is not specified alongside linking (which includes SPV generation)
if ((Options & EOptionOutputPreprocessed) && (Options & EOptionLinkProgram))
Error("can't use -E when linking is selected");
// -o or -x makes no sense if there is no target binary
if (binaryFileName && (Options & EOptionSpv) == 0)
Error("no binary generation requested (e.g., -V)");
}
//
// Translate the meaningful subset of command-line options to parser-behavior options.
//
void SetMessageOptions(EShMessages& messages)
{
if (Options & EOptionRelaxedErrors)
messages = (EShMessages)(messages | EShMsgRelaxedErrors);
if (Options & EOptionIntermediate)
messages = (EShMessages)(messages | EShMsgAST);
if (Options & EOptionSuppressWarnings)
messages = (EShMessages)(messages | EShMsgSuppressWarnings);
if (Options & EOptionSpv)
messages = (EShMessages)(messages | EShMsgSpvRules);
if (Options & EOptionVulkanRules)
messages = (EShMessages)(messages | EShMsgVulkanRules);
if (Options & EOptionOutputPreprocessed)
messages = (EShMessages)(messages | EShMsgOnlyPreprocessor);
if (Options & EOptionReadHlsl)
messages = (EShMessages)(messages | EShMsgReadHlsl);
if (Options & EOptionCascadingErrors)
messages = (EShMessages)(messages | EShMsgCascadingErrors);
}
//
// Thread entry point, for non-linking asynchronous mode.
//
// Return 0 for failure, 1 for success.
//
unsigned int CompileShaders(void*)
{
glslang::TWorkItem* workItem;
while (Worklist.remove(workItem)) {
ShHandle compiler = ShConstructCompiler(FindLanguage(workItem->name), Options);
if (compiler == 0)
return 0;
CompileFile(workItem->name.c_str(), compiler);
if (! (Options & EOptionSuppressInfolog))
workItem->results = ShGetInfoLog(compiler);
ShDestruct(compiler);
}
return 0;
}
// Outputs the given string, but only if it is non-null and non-empty.
// This prevents erroneous newlines from appearing.
void PutsIfNonEmpty(const char* str)
{
if (str && str[0]) {
puts(str);
}
}
// Outputs the given string to stderr, but only if it is non-null and non-empty.
// This prevents erroneous newlines from appearing.
void StderrIfNonEmpty(const char* str)
{
if (str && str[0]) {
fprintf(stderr, "%s\n", str);
}
}
// Simple bundling of what makes a compilation unit for ease in passing around,
// and separation of handling file IO versus API (programmatic) compilation.
struct ShaderCompUnit {
EShLanguage stage;
std::string fileName;
char** text; // memory owned/managed externally
};
//
// For linking mode: Will independently parse each compilation unit, but then put them
// in the same program and link them together, making at most one linked module per
// pipeline stage.
//
// Uses the new C++ interface instead of the old handle-based interface.
//
void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
{
// keep track of what to free
std::list<glslang::TShader*> shaders;
EShMessages messages = EShMsgDefault;
SetMessageOptions(messages);
//
// Per-shader processing...
//
glslang::TProgram& program = *new glslang::TProgram;
for (auto it = compUnits.cbegin(); it != compUnits.cend(); ++it) {
const auto &compUnit = *it;
glslang::TShader* shader = new glslang::TShader(compUnit.stage);
shader->setStrings(compUnit.text, 1);
if (entryPointName) // HLSL todo: this needs to be tracked per compUnits
shader->setEntryPoint(entryPointName);
shaders.push_back(shader);
const int defaultVersion = Options & EOptionDefaultDesktop? 110: 100;
if (Options & EOptionOutputPreprocessed) {
std::string str;
glslang::TShader::ForbidInclude includer;
if (shader->preprocess(&Resources, defaultVersion, ENoProfile, false, false,
messages, &str, includer)) {
PutsIfNonEmpty(str.c_str());
} else {
CompileFailed = true;
}
StderrIfNonEmpty(shader->getInfoLog());
StderrIfNonEmpty(shader->getInfoDebugLog());
continue;
}
if (! shader->parse(&Resources, defaultVersion, false, messages))
CompileFailed = true;
program.addShader(shader);
if (! (Options & EOptionSuppressInfolog) &&
! (Options & EOptionMemoryLeakMode)) {
PutsIfNonEmpty(compUnit.fileName.c_str());
PutsIfNonEmpty(shader->getInfoLog());
PutsIfNonEmpty(shader->getInfoDebugLog());
}
}
//
// Program-level processing...
//
// Link
if (! (Options & EOptionOutputPreprocessed) && ! program.link(messages))
LinkFailed = true;
// Report
if (! (Options & EOptionSuppressInfolog) &&
! (Options & EOptionMemoryLeakMode)) {
PutsIfNonEmpty(program.getInfoLog());
PutsIfNonEmpty(program.getInfoDebugLog());
}
// Reflect
if (Options & EOptionDumpReflection) {
program.buildReflection();
program.dumpReflection();
}
// Dump SPIR-V
if (Options & EOptionSpv) {
if (CompileFailed || LinkFailed)
printf("SPIR-V is not generated for failed compile or link\n");
else {
for (int stage = 0; stage < EShLangCount; ++stage) {
if (program.getIntermediate((EShLanguage)stage)) {
std::vector<unsigned int> spirv;
std::string warningsErrors;
spv::SpvBuildLogger logger;
glslang::GlslangToSpv(*program.getIntermediate((EShLanguage)stage), spirv, &logger);
// Dump the spv to a file or stdout, etc., but only if not doing
// memory/perf testing, as it's not internal to programmatic use.
if (! (Options & EOptionMemoryLeakMode)) {
printf("%s", logger.getAllMessages().c_str());
if (Options & EOptionOutputHexadecimal) {
glslang::OutputSpvHex(spirv, GetBinaryName((EShLanguage)stage));
} else {
glslang::OutputSpvBin(spirv, GetBinaryName((EShLanguage)stage));
}
if (Options & EOptionHumanReadableSpv) {
spv::Disassemble(std::cout, spirv);
}
}
}
}
}
}
// Free everything up, program has to go before the shaders
// because it might have merged stuff from the shaders, and
// the stuff from the shaders has to have its destructors called
// before the pools holding the memory in the shaders is freed.
delete &program;
while (shaders.size() > 0) {
delete shaders.back();
shaders.pop_back();
}
}
//
// Do file IO part of compile and link, handing off the pure
// API/programmatic mode to CompileAndLinkShaderUnits(), which can
// be put in a loop for testing memory footprint and performance.
//
// This is just for linking mode: meaning all the shaders will be put into the
// the same program linked together.
//
// This means there are a limited number of work items (not multi-threading mode)
// and that the point is testing at the linking level. Hence, to enable
// performance and memory testing, the actual compile/link can be put in
// a loop, independent of processing the work items and file IO.
//
void CompileAndLinkShaderFiles()
{
std::vector<ShaderCompUnit> compUnits;
// Transfer all the work items from to a simple list of
// of compilation units. (We don't care about the thread
// work-item distribution properties in this path, which
// is okay due to the limited number of shaders, know since
// they are all getting linked together.)
glslang::TWorkItem* workItem;
while (Worklist.remove(workItem)) {
ShaderCompUnit compUnit = {
FindLanguage(workItem->name),
workItem->name,
ReadFileData(workItem->name.c_str())
};
if (! compUnit.text) {
usage();
return;
}
compUnits.push_back(compUnit);
}
// Actual call to programmatic processing of compile and link,
// in a loop for testing memory and performance. This part contains
// all the perf/memory that a programmatic consumer will care about.
for (int i = 0; i < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++i) {
for (int j = 0; j < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++j)
CompileAndLinkShaderUnits(compUnits);
if (Options & EOptionMemoryLeakMode)
glslang::OS_DumpMemoryCounters();
}
for (auto it = compUnits.begin(); it != compUnits.end(); ++it)
FreeFileData(it->text);
}
int C_DECL main(int argc, char* argv[])
{
ProcessArguments(argc, argv);
if (Options & EOptionDumpConfig) {
printf("%s", glslang::GetDefaultTBuiltInResourceString().c_str());
if (Worklist.empty())
return ESuccess;
}
if (Options & EOptionDumpVersions) {
printf("Glslang Version: %s %s\n", GLSLANG_REVISION, GLSLANG_DATE);
printf("ESSL Version: %s\n", glslang::GetEsslVersionString());
printf("GLSL Version: %s\n", glslang::GetGlslVersionString());
std::string spirvVersion;
glslang::GetSpirvVersion(spirvVersion);
printf("SPIR-V Version %s\n", spirvVersion.c_str());
printf("GLSL.std.450 Version %d, Revision %d\n", GLSLstd450Version, GLSLstd450Revision);
printf("Khronos Tool ID %d\n", glslang::GetKhronosToolId());
if (Worklist.empty())
return ESuccess;
}
if (Worklist.empty()) {
usage();
}
ProcessConfigFile();
//
// Two modes:
// 1) linking all arguments together, single-threaded, new C++ interface
// 2) independent arguments, can be tackled by multiple asynchronous threads, for testing thread safety, using the old handle interface
//
if (Options & EOptionLinkProgram ||
Options & EOptionOutputPreprocessed) {
glslang::InitializeProcess();
CompileAndLinkShaderFiles();
glslang::FinalizeProcess();
for (int w = 0; w < NumWorkItems; ++w) {
if (Work[w]) {
delete Work[w];
}
}
} else {
ShInitialize();
bool printShaderNames = Worklist.size() > 1;
if (Options & EOptionMultiThreaded) {
const int NumThreads = 16;
void* threads[NumThreads];
for (int t = 0; t < NumThreads; ++t) {
threads[t] = glslang::OS_CreateThread(&CompileShaders);
if (! threads[t]) {
printf("Failed to create thread\n");
return EFailThreadCreate;
}
}
glslang::OS_WaitForAllThreads(threads, NumThreads);
} else
CompileShaders(0);
// Print out all the resulting infologs
for (int w = 0; w < NumWorkItems; ++w) {
if (Work[w]) {
if (printShaderNames || Work[w]->results.size() > 0)
PutsIfNonEmpty(Work[w]->name.c_str());
PutsIfNonEmpty(Work[w]->results.c_str());
delete Work[w];
}
}
ShFinalize();
}
delete[] Work;
if (CompileFailed)
return EFailCompile;
if (LinkFailed)
return EFailLink;
return 0;
}
//
// Deduce the language from the filename. Files must end in one of the
// following extensions:
//
// .vert = vertex
// .tesc = tessellation control
// .tese = tessellation evaluation
// .geom = geometry
// .frag = fragment
// .comp = compute
//
EShLanguage FindLanguage(const std::string& name)
{
size_t ext = name.rfind('.');
if (ext == std::string::npos) {
usage();
return EShLangVertex;
}
std::string suffix = name.substr(ext + 1, std::string::npos);
if (suffix == "vert")
return EShLangVertex;
else if (suffix == "tesc")
return EShLangTessControl;
else if (suffix == "tese")
return EShLangTessEvaluation;
else if (suffix == "geom")
return EShLangGeometry;
else if (suffix == "frag")
return EShLangFragment;
else if (suffix == "comp")
return EShLangCompute;
usage();
return EShLangVertex;
}
//
// Read a file's data into a string, and compile it using the old interface ShCompile,
// for non-linkable results.
//
void CompileFile(const char* fileName, ShHandle compiler)
{
int ret = 0;
char** shaderStrings = ReadFileData(fileName);
if (! shaderStrings) {
usage();
}
int* lengths = new int[NumShaderStrings];
// move to length-based strings, rather than null-terminated strings
for (int s = 0; s < NumShaderStrings; ++s)
lengths[s] = (int)strlen(shaderStrings[s]);
if (! shaderStrings) {
CompileFailed = true;
return;
}
EShMessages messages = EShMsgDefault;
SetMessageOptions(messages);
for (int i = 0; i < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++i) {
for (int j = 0; j < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++j) {
//ret = ShCompile(compiler, shaderStrings, NumShaderStrings, lengths, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages);
ret = ShCompile(compiler, shaderStrings, NumShaderStrings, nullptr, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages);
//const char* multi[12] = { "# ve", "rsion", " 300 e", "s", "\n#err",
// "or should be l", "ine 1", "string 5\n", "float glo", "bal",
// ";\n#error should be line 2\n void main() {", "global = 2.3;}" };
//const char* multi[7] = { "/", "/", "\\", "\n", "\n", "#", "version 300 es" };
//ret = ShCompile(compiler, multi, 7, nullptr, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages);
}
if (Options & EOptionMemoryLeakMode)
glslang::OS_DumpMemoryCounters();
}
delete [] lengths;
FreeFileData(shaderStrings);
if (ret == 0)
CompileFailed = true;
}
//
// print usage to stdout
//
void usage()
{
printf("Usage: glslangValidator [option]... [file]...\n"
"\n"
"Where: each 'file' ends in .<stage>, where <stage> is one of\n"
" .conf to provide an optional config file that replaces the default configuration\n"
" (see -c option below for generating a template)\n"
" .vert for a vertex shader\n"
" .tesc for a tessellation control shader\n"
" .tese for a tessellation evaluation shader\n"
" .geom for a geometry shader\n"
" .frag for a fragment shader\n"
" .comp for a compute shader\n"
"\n"
"Compilation warnings and errors will be printed to stdout.\n"
"\n"
"To get other information, use one of the following options:\n"
"Each option must be specified separately.\n"
" -V create SPIR-V binary, under Vulkan semantics; turns on -l;\n"
" default file name is <stage>.spv (-o overrides this)\n"
" -G create SPIR-V binary, under OpenGL semantics; turns on -l;\n"
" default file name is <stage>.spv (-o overrides this)\n"
" -H print human readable form of SPIR-V; turns on -V\n"
" -E print pre-processed GLSL; cannot be used with -l;\n"
" errors will appear on stderr.\n"
" -c configuration dump;\n"
" creates the default configuration file (redirect to a .conf file)\n"
" -C cascading errors; risks crashes from accumulation of error recoveries\n"
" -d default to desktop (#version 110) when there is no shader #version\n"
" (default is ES version 100)\n"
" -D input is HLSL\n"
" -e specify entry-point name\n"
" -h print this usage message\n"
" -i intermediate tree (glslang AST) is printed out\n"
" -l link all input files together to form a single module\n"
" -m memory leak mode\n"
" -o <file> save binary to <file>, requires a binary option (e.g., -V)\n"
" -q dump reflection query database\n"
" -r relaxed semantic error-checking mode\n"
" -s silent mode\n"
" -t multi-threaded mode\n"
" -v print version strings\n"
" -w suppress warnings (except as required by #extension : warn)\n"
" -x save 32-bit hexadecimal numbers as text, requires a binary option (e.g., -V)\n"
);
exit(EFailUsage);
}
#if !defined _MSC_VER && !defined MINGW_HAS_SECURE_API
#include <errno.h>
int fopen_s(
FILE** pFile,
const char* filename,
const char* mode
)
{
if (!pFile || !filename || !mode) {
return EINVAL;
}
FILE* f = fopen(filename, mode);
if (! f) {
if (errno != 0) {
return errno;
} else {
return ENOENT;
}
}
*pFile = f;
return 0;
}
#endif
//
// Malloc a string of sufficient size and read a string into it.
//
char** ReadFileData(const char* fileName)
{
FILE *in = nullptr;
int errorCode = fopen_s(&in, fileName, "r");
int count = 0;
const int maxSourceStrings = 5; // for testing splitting shader/tokens across multiple strings
char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1)); // freed in FreeFileData()
if (errorCode || in == nullptr)
Error("unable to open input file");
while (fgetc(in) != EOF)
count++;
fseek(in, 0, SEEK_SET);
char *fdata = (char*)malloc(count+2); // freed before return of this function
if (! fdata)
Error("can't allocate memory");
if ((int)fread(fdata, 1, count, in) != count) {
free(fdata);
Error("can't read input file");
}
fdata[count] = '\0';
fclose(in);
if (count == 0) {
// recover from empty file
return_data[0] = (char*)malloc(count+2); // freed in FreeFileData()
return_data[0][0]='\0';
NumShaderStrings = 0;
free(fdata);
return return_data;
} else
NumShaderStrings = 1; // Set to larger than 1 for testing multiple strings
// compute how to split up the file into multiple strings, for testing multiple strings
int len = (int)(ceil)((float)count/(float)NumShaderStrings);
int ptr_len = 0;
int i = 0;
while (count > 0) {
return_data[i] = (char*)malloc(len + 2); // freed in FreeFileData()
memcpy(return_data[i], fdata + ptr_len, len);
return_data[i][len] = '\0';
count -= len;
ptr_len += len;
if (count < len) {
if (count == 0) {
NumShaderStrings = i + 1;
break;
}
len = count;
}
++i;
}
free(fdata);
return return_data;
}
void FreeFileData(char** data)
{
for(int i = 0; i < NumShaderStrings; i++)
free(data[i]);
free(data);
}
void InfoLogMsg(const char* msg, const char* name, const int num)
{
if (num >= 0 )
printf("#### %s %s %d INFO LOG ####\n", msg, name, num);
else
printf("#### %s %s INFO LOG ####\n", msg, name);
}

98
Externals/glslang/StandAlone/Worklist.h vendored Normal file
View File

@ -0,0 +1,98 @@
//
//Copyright (C) 2013 LunarG, Inc.
//
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions
//are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//POSSIBILITY OF SUCH DAMAGE.
//
#ifndef WORKLIST_H_INCLUDED
#define WORKLIST_H_INCLUDED
#include "../glslang/OSDependent/osinclude.h"
#include <string>
#include <list>
namespace glslang {
class TWorkItem {
public:
TWorkItem() { }
explicit TWorkItem(const std::string& s) :
name(s) { }
std::string name;
std::string results;
std::string resultsIndex;
};
class TWorklist {
public:
TWorklist() { }
virtual ~TWorklist() { }
void add(TWorkItem* item)
{
GetGlobalLock();
worklist.push_back(item);
ReleaseGlobalLock();
}
bool remove(TWorkItem*& item)
{
GetGlobalLock();
if (worklist.empty())
return false;
item = worklist.front();
worklist.pop_front();
ReleaseGlobalLock();
return true;
}
int size()
{
return (int)worklist.size();
}
bool empty()
{
return worklist.empty();
}
protected:
std::list<TWorkItem*> worklist;
};
} // end namespace glslang
#endif // WORKLIST_H_INCLUDED

View File

@ -0,0 +1,344 @@
//
//Copyright (C) 2015 LunarG, Inc.
//
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions
//are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//POSSIBILITY OF SUCH DAMAGE.
//
#include <iostream>
#include <fstream>
#include <cstring>
#include <stdexcept>
#include "../SPIRV/SPVRemapper.h"
namespace {
typedef unsigned int SpvWord;
// Poor man's basename: given a complete path, return file portion.
// E.g:
// Linux: /foo/bar/test -> test
// Win: c:\foo\bar\test -> test
// It's not very efficient, but that doesn't matter for our minimal-duty use.
// Using boost::filesystem would be better in many ways, but want to avoid that dependency.
// OS dependent path separator (avoiding boost::filesystem dependency)
#if defined(_WIN32)
char path_sep_char() { return '\\'; }
#else
char path_sep_char() { return '/'; }
#endif
std::string basename(const std::string filename)
{
const size_t sepLoc = filename.find_last_of(path_sep_char());
return (sepLoc == filename.npos) ? filename : filename.substr(sepLoc+1);
}
void errHandler(const std::string& str) {
std::cout << str << std::endl;
exit(5);
}
void logHandler(const std::string& str) {
std::cout << str << std::endl;
}
// Read word stream from disk
void read(std::vector<SpvWord>& spv, const std::string& inFilename, int verbosity)
{
std::ifstream fp;
if (verbosity > 0)
logHandler(std::string(" reading: ") + inFilename);
spv.clear();
fp.open(inFilename, std::fstream::in | std::fstream::binary);
if (fp.fail())
errHandler("error opening file for read: ");
// Reserve space (for efficiency, not for correctness)
fp.seekg(0, fp.end);
spv.reserve(size_t(fp.tellg()) / sizeof(SpvWord));
fp.seekg(0, fp.beg);
while (!fp.eof()) {
SpvWord inWord;
fp.read((char *)&inWord, sizeof(inWord));
if (!fp.eof()) {
spv.push_back(inWord);
if (fp.fail())
errHandler(std::string("error reading file: ") + inFilename);
}
}
}
void write(std::vector<SpvWord>& spv, const std::string& outFile, int verbosity)
{
if (outFile.empty())
errHandler("missing output filename.");
std::ofstream fp;
if (verbosity > 0)
logHandler(std::string(" writing: ") + outFile);
fp.open(outFile, std::fstream::out | std::fstream::binary);
if (fp.fail())
errHandler(std::string("error opening file for write: ") + outFile);
for (auto it = spv.cbegin(); it != spv.cend(); ++it) {
SpvWord word = *it;
fp.write((char *)&word, sizeof(word));
if (fp.fail())
errHandler(std::string("error writing file: ") + outFile);
}
// file is closed by destructor
}
// Print helpful usage message to stdout, and exit
void usage(const char* const name, const char* const msg = 0)
{
if (msg)
std::cout << msg << std::endl << std::endl;
std::cout << "Usage: " << std::endl;
std::cout << " " << basename(name)
<< " [-v[v[...]] | --verbose [int]]"
<< " [--map (all|types|names|funcs)]"
<< " [--dce (all|types|funcs)]"
<< " [--opt (all|loadstore)]"
<< " [--strip-all | --strip all | -s]"
<< " [--do-everything]"
<< " --input | -i file1 [file2...] --output|-o DESTDIR"
<< std::endl;
std::cout << " " << basename(name) << " [--version | -V]" << std::endl;
std::cout << " " << basename(name) << " [--help | -?]" << std::endl;
exit(5);
}
// grind through each SPIR in turn
void execute(const std::vector<std::string>& inputFile, const std::string& outputDir,
int opts, int verbosity)
{
for (auto it = inputFile.cbegin(); it != inputFile.cend(); ++it) {
const std::string &filename = *it;
std::vector<SpvWord> spv;
read(spv, filename, verbosity);
spv::spirvbin_t(verbosity).remap(spv, opts);
const std::string outfile = outputDir + path_sep_char() + basename(filename);
write(spv, outfile, verbosity);
}
if (verbosity > 0)
std::cout << "Done: " << inputFile.size() << " file(s) processed" << std::endl;
}
// Parse command line options
void parseCmdLine(int argc, char** argv, std::vector<std::string>& inputFile,
std::string& outputDir,
int& options,
int& verbosity)
{
if (argc < 2)
usage(argv[0]);
verbosity = 0;
options = spv::spirvbin_t::NONE;
// Parse command line.
// boost::program_options would be quite a bit nicer, but we don't want to
// introduce a dependency on boost.
for (int a=1; a<argc; ) {
const std::string arg = argv[a];
if (arg == "--output" || arg == "-o") {
// Output directory
if (++a >= argc)
usage(argv[0], "--output requires an argument");
if (!outputDir.empty())
usage(argv[0], "--output can be provided only once");
outputDir = argv[a++];
// Remove trailing directory separator characters
while (!outputDir.empty() && outputDir.back() == path_sep_char())
outputDir.pop_back();
}
else if (arg == "-vv") { verbosity = 2; ++a; } // verbosity shortcuts
else if (arg == "-vvv") { verbosity = 3; ++a; } // ...
else if (arg == "-vvvv") { verbosity = 4; ++a; } // ...
else if (arg == "-vvvvv") { verbosity = 5; ++a; } // ...
else if (arg == "--verbose" || arg == "-v") {
++a;
verbosity = 1;
if (a < argc) {
char* end_ptr = 0;
int verb = ::strtol(argv[a], &end_ptr, 10);
// If we have not read to the end of the string or
// the string contained no elements, then we do not want to
// store the value.
if (*end_ptr == '\0' && end_ptr != argv[a]) {
verbosity = verb;
++a;
}
}
}
else if (arg == "--version" || arg == "-V") {
std::cout << basename(argv[0]) << " version 0.97 " << __DATE__ << " " << __TIME__ << std::endl;
exit(0);
} else if (arg == "--input" || arg == "-i") {
// Collect input files
for (++a; a < argc && argv[a][0] != '-'; ++a)
inputFile.push_back(argv[a]);
} else if (arg == "--do-everything") {
++a;
options = options | spv::spirvbin_t::DO_EVERYTHING;
} else if (arg == "--strip-all" || arg == "-s") {
++a;
options = options | spv::spirvbin_t::STRIP;
} else if (arg == "--strip") {
++a;
if (strncmp(argv[a], "all", 3) == 0) {
options = options | spv::spirvbin_t::STRIP;
++a;
}
} else if (arg == "--dce") {
// Parse comma (or colon, etc) separated list of things to dce
++a;
for (const char* c = argv[a]; *c; ++c) {
if (strncmp(c, "all", 3) == 0) {
options = (options | spv::spirvbin_t::DCE_ALL);
c += 3;
} else if (strncmp(c, "*", 1) == 0) {
options = (options | spv::spirvbin_t::DCE_ALL);
c += 1;
} else if (strncmp(c, "funcs", 5) == 0) {
options = (options | spv::spirvbin_t::DCE_FUNCS);
c += 5;
} else if (strncmp(c, "types", 5) == 0) {
options = (options | spv::spirvbin_t::DCE_TYPES);
c += 5;
}
}
++a;
} else if (arg == "--map") {
// Parse comma (or colon, etc) separated list of things to map
++a;
for (const char* c = argv[a]; *c; ++c) {
if (strncmp(c, "all", 3) == 0) {
options = (options | spv::spirvbin_t::MAP_ALL);
c += 3;
} else if (strncmp(c, "*", 1) == 0) {
options = (options | spv::spirvbin_t::MAP_ALL);
c += 1;
} else if (strncmp(c, "types", 5) == 0) {
options = (options | spv::spirvbin_t::MAP_TYPES);
c += 5;
} else if (strncmp(c, "names", 5) == 0) {
options = (options | spv::spirvbin_t::MAP_NAMES);
c += 5;
} else if (strncmp(c, "funcs", 5) == 0) {
options = (options | spv::spirvbin_t::MAP_FUNCS);
c += 5;
}
}
++a;
} else if (arg == "--opt") {
++a;
for (const char* c = argv[a]; *c; ++c) {
if (strncmp(c, "all", 3) == 0) {
options = (options | spv::spirvbin_t::OPT_ALL);
c += 3;
} else if (strncmp(c, "*", 1) == 0) {
options = (options | spv::spirvbin_t::OPT_ALL);
c += 1;
} else if (strncmp(c, "loadstore", 9) == 0) {
options = (options | spv::spirvbin_t::OPT_LOADSTORE);
c += 9;
}
}
++a;
} else if (arg == "--help" || arg == "-?") {
usage(argv[0]);
} else {
usage(argv[0], "Unknown command line option");
}
}
}
} // namespace
int main(int argc, char** argv)
{
std::vector<std::string> inputFile;
std::string outputDir;
int opts;
int verbosity;
#ifdef use_cpp11
// handle errors by exiting
spv::spirvbin_t::registerErrorHandler(errHandler);
// Log messages to std::cout
spv::spirvbin_t::registerLogHandler(logHandler);
#endif
if (argc < 2)
usage(argv[0]);
parseCmdLine(argc, argv, inputFile, outputDir, opts, verbosity);
if (outputDir.empty())
usage(argv[0], "Output directory required");
std::string errmsg;
// Main operations: read, remap, and write.
execute(inputFile, outputDir, opts, verbosity);
// If we get here, everything went OK! Nothing more to be done.
}