Enable HLSL legalization
Also added known-good mechanism to fetch latest validated spirv-tools.
Also added -Od and -Os to disable optimizer and optimize for size.
Fetching spirv-tools is optional for both glsl and hlsl. Legalization
of hlsl is done by default if spirv-opt is present at cmake time.
Optimization for glsl is currently done through the option -Os.
Legalization testing is currently only done on four existing shaders.
A separate baseLegalResults directory holds those results. All previous
testing is done with the optimizer disabled.
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 54dc61f..a0a1c83 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -52,6 +52,16 @@
#endif
}
+#ifdef ENABLE_OPT
+ #include "spirv-tools/optimizer.hpp"
+ #include "message.h"
+ #include "SPVRemapper.h"
+#endif
+
+#ifdef ENABLE_OPT
+using namespace spvtools;
+#endif
+
// Glslang includes
#include "../glslang/MachineIndependent/localintermediate.h"
#include "../glslang/MachineIndependent/SymbolTable.h"
@@ -5960,6 +5970,12 @@
out.close();
}
+#ifdef ENABLE_OPT
+void errHandler(const std::string& str) {
+ std::cerr << str << std::endl;
+}
+#endif
+
//
// Set up the glslang traversal
//
@@ -5988,6 +6004,49 @@
it.finishSpv();
it.dumpSpv(spirv);
+#ifdef ENABLE_OPT
+ // If from HLSL, run spirv-opt to "legalize" the SPIR-V for Vulkan
+ // eg. forward and remove memory writes of opaque types.
+ if ((intermediate.getSource() == EShSourceHlsl ||
+ options->optimizeSize) &&
+ !options->disableOptimizer) {
+ 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) {
+ std::cerr << StringifyMessage(level, source, position, message)
+ << std::endl;
+ });
+
+ optimizer.RegisterPass(CreateInlineExhaustivePass());
+ optimizer.RegisterPass(CreateLocalAccessChainConvertPass());
+ optimizer.RegisterPass(CreateLocalSingleBlockLoadStoreElimPass());
+ optimizer.RegisterPass(CreateLocalSingleStoreElimPass());
+ optimizer.RegisterPass(CreateInsertExtractElimPass());
+ optimizer.RegisterPass(CreateAggressiveDCEPass());
+ optimizer.RegisterPass(CreateDeadBranchElimPass());
+ optimizer.RegisterPass(CreateBlockMergePass());
+ optimizer.RegisterPass(CreateLocalMultiStoreElimPass());
+ optimizer.RegisterPass(CreateInsertExtractElimPass());
+ optimizer.RegisterPass(CreateAggressiveDCEPass());
+ // TODO(greg-lunarg): Add this when AMD driver issues are resolved
+ // if (options->optimizeSize)
+ // optimizer.RegisterPass(CreateCommonUniformElimPass());
+
+ if (!optimizer.Run(spirv.data(), spirv.size(), &spirv))
+ return;
+
+ // Remove dead module-level objects: functions, types, vars
+ // TODO(greg-lunarg): Switch to spirv-opt versions when available
+ spv::spirvbin_t Remapper(0);
+ Remapper.registerErrorHandler(errHandler);
+ Remapper.remap(spirv, spv::spirvbin_t::DCE_ALL);
+ }
+#endif
+
glslang::GetThreadPoolAllocator().pop();
}
diff --git a/SPIRV/GlslangToSpv.h b/SPIRV/GlslangToSpv.h
index 0dad4d2..0398501 100644
--- a/SPIRV/GlslangToSpv.h
+++ b/SPIRV/GlslangToSpv.h
@@ -48,8 +48,11 @@
namespace glslang {
struct SpvOptions {
- SpvOptions() : generateDebugInfo(false) { }
+ SpvOptions() : generateDebugInfo(false), disableOptimizer(true),
+ optimizeSize(false) { }
bool generateDebugInfo;
+ bool disableOptimizer;
+ bool optimizeSize;
};
void GetSpirvVersion(std::string&);