// If from HLSL, run spirv-opt to "legalize" the SPIR-V for Vulkan
// eg. forward and remove memory writes of opaque types.
bool prelegalization = intermediate.getSource() == EShSourceHlsl;
- if ((intermediate.getSource() == EShSourceHlsl || options->optimizeSize) && !options->disableOptimizer) {
- SpirvToolsLegalize(intermediate, spirv, logger, options);
+ if ((prelegalization || options->optimizeSize) && !options->disableOptimizer) {
+ SpirvToolsTransform(intermediate, spirv, logger, options);
prelegalization = false;
}
+ else if (options->stripDebugInfo) {
+ // Strip debug info even if optimization is disabled.
+ SpirvToolsStripDebugInfo(intermediate, spirv, logger);
+ }
if (options->validate)
SpirvToolsValidate(intermediate, spirv, logger, prelegalization);
return spv_target_env::SPV_ENV_UNIVERSAL_1_0;
}
+// Callback passed to spvtools::Optimizer::SetMessageConsumer
+void OptimizerMesssageConsumer(spv_message_level_t level, const char *source,
+ const spv_position_t &position, const char *message)
+{
+ auto &out = std::cerr;
+ switch (level)
+ {
+ case SPV_MSG_FATAL:
+ case SPV_MSG_INTERNAL_ERROR:
+ case SPV_MSG_ERROR:
+ out << "error: ";
+ break;
+ case SPV_MSG_WARNING:
+ out << "warning: ";
+ break;
+ case SPV_MSG_INFO:
+ case SPV_MSG_DEBUG:
+ out << "info: ";
+ break;
+ default:
+ break;
+ }
+ if (source)
+ {
+ out << source << ":";
+ }
+ out << position.line << ":" << position.column << ":" << position.index << ":";
+ if (message)
+ {
+ out << " " << message;
+ }
+ out << std::endl;
+}
// Use the SPIRV-Tools disassembler to print SPIR-V.
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv)
spvContextDestroy(context);
}
-// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of
-// legalizing HLSL SPIR-V.
-void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
- spv::SpvBuildLogger* logger, const SpvOptions* options)
+// Apply the SPIRV-Tools optimizer to generated SPIR-V. HLSL SPIR-V is legalized in the process.
+void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
+ spv::SpvBuildLogger* logger, const SpvOptions* options)
{
spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2;
spvtools::Optimizer optimizer(target_env);
- optimizer.SetMessageConsumer(
- [](spv_message_level_t level, const char *source, const spv_position_t &position, const char *message) {
- auto &out = std::cerr;
- switch (level)
- {
- case SPV_MSG_FATAL:
- case SPV_MSG_INTERNAL_ERROR:
- case SPV_MSG_ERROR:
- out << "error: ";
- break;
- case SPV_MSG_WARNING:
- out << "warning: ";
- break;
- case SPV_MSG_INFO:
- case SPV_MSG_DEBUG:
- out << "info: ";
- break;
- default:
- break;
- }
- if (source)
- {
- out << source << ":";
- }
- out << position.line << ":" << position.column << ":" << position.index << ":";
- if (message)
- {
- out << " " << message;
- }
- out << std::endl;
- });
+ optimizer.SetMessageConsumer(OptimizerMesssageConsumer);
// If debug (specifically source line info) is being generated, propagate
// line information into all SPIR-V instructions. This avoids loss of
if (options->generateDebugInfo) {
optimizer.RegisterPass(spvtools::CreatePropagateLineInfoPass());
}
+ else if (options->stripDebugInfo) {
+ optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass());
+ }
optimizer.RegisterPass(spvtools::CreateWrapOpKillPass());
optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass());
optimizer.RegisterPass(spvtools::CreateMergeReturnPass());
optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions);
}
+// Apply the SPIRV-Tools optimizer to strip debug info from SPIR-V. This is implicitly done by
+// SpirvToolsTransform if spvOptions->stripDebugInfo is set, but can be called separately if
+// optimization is disabled.
+void SpirvToolsStripDebugInfo(const glslang::TIntermediate& intermediate,
+ std::vector<unsigned int>& spirv, spv::SpvBuildLogger* logger)
+{
+ spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2;
+
+ spvtools::Optimizer optimizer(target_env);
+ optimizer.SetMessageConsumer(OptimizerMesssageConsumer);
+
+ optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass());
+
+ spvtools::OptimizerOptions spvOptOptions;
+ optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger));
+ spvOptOptions.set_run_validator(false); // The validator may run as a separate step later on
+ optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions);
+}
+
}; // end namespace glslang
#endif
namespace glslang {
struct SpvOptions {
- SpvOptions() : generateDebugInfo(false), disableOptimizer(true),
+ SpvOptions() : generateDebugInfo(false), stripDebugInfo(false), disableOptimizer(true),
optimizeSize(false), disassemble(false), validate(false) { }
bool generateDebugInfo;
+ bool stripDebugInfo;
bool disableOptimizer;
bool optimizeSize;
bool disassemble;
void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger*, bool prelegalization);
-// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of
-// legalizing HLSL SPIR-V.
-void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
- spv::SpvBuildLogger*, const SpvOptions*);
+// Apply the SPIRV-Tools optimizer to generated SPIR-V. HLSL SPIR-V is legalized in the process.
+void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
+ spv::SpvBuildLogger*, const SpvOptions*);
+
+// Apply the SPIRV-Tools optimizer to strip debug info from SPIR-V. This is implicitly done by
+// SpirvToolsTransform if spvOptions->stripDebugInfo is set, but can be called separately if
+// optimization is disabled.
+void SpirvToolsStripDebugInfo(const glslang::TIntermediate& intermediate,
+ std::vector<unsigned int>& spirv, spv::SpvBuildLogger*);
#endif
bool SpvToolsDisassembler = false;
bool SpvToolsValidate = false;
bool NaNClamp = false;
+bool stripDebugInfo = false;
//
// Return codes from main/exit().
Error("-f: expected hlsl_functionality1");
break;
case 'g':
- Options |= EOptionDebug;
+ // Override previous -g or -g0 argument
+ stripDebugInfo = false;
+ Options &= ~EOptionDebug;
+ if (argv[0][2] == '0')
+ stripDebugInfo = true;
+ else
+ Options |= EOptionDebug;
break;
case 'h':
usage();
glslang::SpvOptions spvOptions;
if (Options & EOptionDebug)
spvOptions.generateDebugInfo = true;
+ else if (stripDebugInfo)
+ spvOptions.stripDebugInfo = true;
spvOptions.disableOptimizer = (Options & EOptionOptimizeDisable) != 0;
spvOptions.optimizeSize = (Options & EOptionOptimizeSize) != 0;
spvOptions.disassemble = SpvToolsDisassembler;
" 'hlsl_functionality1' enables use of the\n"
" SPV_GOOGLE_hlsl_functionality1 extension\n"
" -g generate debug information\n"
+ " -g0 strip debug information\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"