Add --no-link option
Adds the --no-link option which outputs the compiled shader binaries without linking them. This is a first step towards allowing users to create SPIR-v binary, non-executable libraries. When using the --no-link option, all functions are decorated with the Export linkage attribute.
This commit is contained in:
parent
a4aceb57de
commit
4c57db1595
24 changed files with 1671 additions and 1454 deletions
|
|
@ -73,40 +73,41 @@ extern "C" {
|
|||
}
|
||||
|
||||
// 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),
|
||||
EOptionAutoMapBindings = (1 << 19),
|
||||
EOptionFlattenUniformArrays = (1 << 20),
|
||||
EOptionNoStorageFormat = (1 << 21),
|
||||
EOptionKeepUncalled = (1 << 22),
|
||||
EOptionHlslOffsets = (1 << 23),
|
||||
EOptionHlslIoMapping = (1 << 24),
|
||||
EOptionAutoMapLocations = (1 << 25),
|
||||
EOptionDebug = (1 << 26),
|
||||
EOptionStdin = (1 << 27),
|
||||
EOptionOptimizeDisable = (1 << 28),
|
||||
EOptionOptimizeSize = (1 << 29),
|
||||
EOptionInvertY = (1 << 30),
|
||||
EOptionDumpBareVersion = (1 << 31),
|
||||
enum TOptions : uint64_t {
|
||||
EOptionNone = 0,
|
||||
EOptionIntermediate = (1ull << 0),
|
||||
EOptionSuppressInfolog = (1ull << 1),
|
||||
EOptionMemoryLeakMode = (1ull << 2),
|
||||
EOptionRelaxedErrors = (1ull << 3),
|
||||
EOptionGiveWarnings = (1ull << 4),
|
||||
EOptionLinkProgram = (1ull << 5),
|
||||
EOptionMultiThreaded = (1ull << 6),
|
||||
EOptionDumpConfig = (1ull << 7),
|
||||
EOptionDumpReflection = (1ull << 8),
|
||||
EOptionSuppressWarnings = (1ull << 9),
|
||||
EOptionDumpVersions = (1ull << 10),
|
||||
EOptionSpv = (1ull << 11),
|
||||
EOptionHumanReadableSpv = (1ull << 12),
|
||||
EOptionVulkanRules = (1ull << 13),
|
||||
EOptionDefaultDesktop = (1ull << 14),
|
||||
EOptionOutputPreprocessed = (1ull << 15),
|
||||
EOptionOutputHexadecimal = (1ull << 16),
|
||||
EOptionReadHlsl = (1ull << 17),
|
||||
EOptionCascadingErrors = (1ull << 18),
|
||||
EOptionAutoMapBindings = (1ull << 19),
|
||||
EOptionFlattenUniformArrays = (1ull << 20),
|
||||
EOptionNoStorageFormat = (1ull << 21),
|
||||
EOptionKeepUncalled = (1ull << 22),
|
||||
EOptionHlslOffsets = (1ull << 23),
|
||||
EOptionHlslIoMapping = (1ull << 24),
|
||||
EOptionAutoMapLocations = (1ull << 25),
|
||||
EOptionDebug = (1ull << 26),
|
||||
EOptionStdin = (1ull << 27),
|
||||
EOptionOptimizeDisable = (1ull << 28),
|
||||
EOptionOptimizeSize = (1ull << 29),
|
||||
EOptionInvertY = (1ull << 30),
|
||||
EOptionDumpBareVersion = (1ull << 31),
|
||||
EOptionCompileOnly = (1ull << 32),
|
||||
};
|
||||
bool targetHlslFunctionality1 = false;
|
||||
bool SpvToolsDisassembler = false;
|
||||
|
|
@ -166,7 +167,7 @@ void ProcessConfigFile()
|
|||
}
|
||||
|
||||
int ReflectOptions = EShReflectionDefault;
|
||||
int Options = 0;
|
||||
std::underlying_type_t<TOptions> Options = EOptionNone;
|
||||
const char* ExecutableName = nullptr;
|
||||
const char* binaryFileName = nullptr;
|
||||
const char* depencyFileName = nullptr;
|
||||
|
|
@ -889,6 +890,8 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
|
|||
bumpArg();
|
||||
} else if (lowerword == "version") {
|
||||
Options |= EOptionDumpVersions;
|
||||
} else if (lowerword == "no-link") {
|
||||
Options |= EOptionCompileOnly;
|
||||
} else if (lowerword == "help") {
|
||||
usage();
|
||||
break;
|
||||
|
|
@ -1310,6 +1313,7 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
|
|||
//
|
||||
|
||||
glslang::TProgram& program = *new glslang::TProgram;
|
||||
const bool compileOnly = (Options & EOptionCompileOnly) != 0;
|
||||
for (auto it = compUnits.cbegin(); it != compUnits.cend(); ++it) {
|
||||
const auto &compUnit = *it;
|
||||
for (int i = 0; i < compUnit.count; i++) {
|
||||
|
|
@ -1326,6 +1330,9 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
|
|||
shader->setSourceEntryPoint(sourceEntryPointName);
|
||||
}
|
||||
|
||||
if (compileOnly)
|
||||
shader->setCompileOnly();
|
||||
|
||||
shader->setOverrideVersion(GlslVersion);
|
||||
|
||||
std::string intrinsicString = getIntrinsic(compUnit.text, compUnit.count);
|
||||
|
|
@ -1445,7 +1452,8 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
|
|||
if (! shader->parse(GetResources(), defaultVersion, false, messages, includer))
|
||||
CompileFailed = true;
|
||||
|
||||
program.addShader(shader);
|
||||
if (!compileOnly)
|
||||
program.addShader(shader);
|
||||
|
||||
if (! (Options & EOptionSuppressInfolog) &&
|
||||
! (Options & EOptionMemoryLeakMode)) {
|
||||
|
|
@ -1460,27 +1468,28 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
|
|||
// Program-level processing...
|
||||
//
|
||||
|
||||
// Link
|
||||
if (! (Options & EOptionOutputPreprocessed) && ! program.link(messages))
|
||||
LinkFailed = true;
|
||||
|
||||
// Map IO
|
||||
if (Options & EOptionSpv) {
|
||||
if (!program.mapIO())
|
||||
if (!compileOnly) {
|
||||
// Link
|
||||
if (!(Options & EOptionOutputPreprocessed) && !program.link(messages))
|
||||
LinkFailed = true;
|
||||
}
|
||||
|
||||
// Report
|
||||
if (! (Options & EOptionSuppressInfolog) &&
|
||||
! (Options & EOptionMemoryLeakMode)) {
|
||||
PutsIfNonEmpty(program.getInfoLog());
|
||||
PutsIfNonEmpty(program.getInfoDebugLog());
|
||||
}
|
||||
// Map IO
|
||||
if (Options & EOptionSpv) {
|
||||
if (!program.mapIO())
|
||||
LinkFailed = true;
|
||||
}
|
||||
|
||||
// Reflect
|
||||
if (Options & EOptionDumpReflection) {
|
||||
program.buildReflection(ReflectOptions);
|
||||
program.dumpReflection();
|
||||
// Report
|
||||
if (!(Options & EOptionSuppressInfolog) && !(Options & EOptionMemoryLeakMode)) {
|
||||
PutsIfNonEmpty(program.getInfoLog());
|
||||
PutsIfNonEmpty(program.getInfoDebugLog());
|
||||
}
|
||||
|
||||
// Reflect
|
||||
if (Options & EOptionDumpReflection) {
|
||||
program.buildReflection(ReflectOptions);
|
||||
program.dumpReflection();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> outputFiles;
|
||||
|
|
@ -1490,44 +1499,58 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
|
|||
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;
|
||||
spv::SpvBuildLogger logger;
|
||||
glslang::SpvOptions spvOptions;
|
||||
if (Options & EOptionDebug) {
|
||||
spvOptions.generateDebugInfo = true;
|
||||
if (emitNonSemanticShaderDebugInfo) {
|
||||
spvOptions.emitNonSemanticShaderDebugInfo = true;
|
||||
if (emitNonSemanticShaderDebugSource) {
|
||||
spvOptions.emitNonSemanticShaderDebugSource = true;
|
||||
}
|
||||
}
|
||||
} else if (stripDebugInfo)
|
||||
spvOptions.stripDebugInfo = true;
|
||||
spvOptions.disableOptimizer = (Options & EOptionOptimizeDisable) != 0;
|
||||
spvOptions.optimizeSize = (Options & EOptionOptimizeSize) != 0;
|
||||
spvOptions.disassemble = SpvToolsDisassembler;
|
||||
spvOptions.validate = SpvToolsValidate;
|
||||
glslang::GlslangToSpv(*program.getIntermediate((EShLanguage)stage), spirv, &logger, &spvOptions);
|
||||
|
||||
// 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) {
|
||||
if (!glslang::OutputSpvHex(spirv, GetBinaryName((EShLanguage)stage), variableName))
|
||||
exit(EFailUsage);
|
||||
} else {
|
||||
if (!glslang::OutputSpvBin(spirv, GetBinaryName((EShLanguage)stage)))
|
||||
exit(EFailUsage);
|
||||
}
|
||||
|
||||
outputFiles.push_back(GetBinaryName((EShLanguage)stage));
|
||||
if (!SpvToolsDisassembler && (Options & EOptionHumanReadableSpv))
|
||||
spv::Disassemble(std::cout, spirv);
|
||||
std::vector<glslang::TIntermediate*> intermediates;
|
||||
if (!compileOnly) {
|
||||
for (int stage = 0; stage < EShLangCount; ++stage) {
|
||||
if (auto* i = program.getIntermediate((EShLanguage)stage)) {
|
||||
intermediates.emplace_back(i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const auto* shader : shaders) {
|
||||
if (auto* i = shader->getIntermediate()) {
|
||||
intermediates.emplace_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto* intermediate : intermediates) {
|
||||
std::vector<unsigned int> spirv;
|
||||
spv::SpvBuildLogger logger;
|
||||
glslang::SpvOptions spvOptions;
|
||||
if (Options & EOptionDebug) {
|
||||
spvOptions.generateDebugInfo = true;
|
||||
if (emitNonSemanticShaderDebugInfo) {
|
||||
spvOptions.emitNonSemanticShaderDebugInfo = true;
|
||||
if (emitNonSemanticShaderDebugSource) {
|
||||
spvOptions.emitNonSemanticShaderDebugSource = true;
|
||||
}
|
||||
}
|
||||
} else if (stripDebugInfo)
|
||||
spvOptions.stripDebugInfo = true;
|
||||
spvOptions.disableOptimizer = (Options & EOptionOptimizeDisable) != 0;
|
||||
spvOptions.optimizeSize = (Options & EOptionOptimizeSize) != 0;
|
||||
spvOptions.disassemble = SpvToolsDisassembler;
|
||||
spvOptions.validate = SpvToolsValidate;
|
||||
spvOptions.compileOnly = compileOnly;
|
||||
glslang::GlslangToSpv(*intermediate, spirv, &logger, &spvOptions);
|
||||
|
||||
// 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());
|
||||
const auto filename = GetBinaryName(intermediate->getStage());
|
||||
if (Options & EOptionOutputHexadecimal) {
|
||||
if (!glslang::OutputSpvHex(spirv, filename, variableName))
|
||||
exit(EFailUsage);
|
||||
} else {
|
||||
if (!glslang::OutputSpvBin(spirv, filename))
|
||||
exit(EFailUsage);
|
||||
}
|
||||
|
||||
outputFiles.push_back(filename);
|
||||
if (!SpvToolsDisassembler && (Options & EOptionHumanReadableSpv))
|
||||
spv::Disassemble(std::cout, spirv);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2075,7 +2098,10 @@ void usage()
|
|||
" --variable-name <name>\n"
|
||||
" --vn <name> creates a C header file that contains a\n"
|
||||
" uint32_t array named <name>\n"
|
||||
" initialized with the shader binary code\n");
|
||||
" initialized with the shader binary code\n"
|
||||
" --no-link Only compile shader; do not link (GLSL-only)\n"
|
||||
" NOTE: this option will set the export linkage\n"
|
||||
" attribute on all functions\n");
|
||||
|
||||
exit(EFailUsage);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue