Skip to content

Commit

Permalink
Enable HLSL legalization
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
greg-lunarg committed Sep 27, 2017
1 parent 44dd6a0 commit cd1f169
Show file tree
Hide file tree
Showing 16 changed files with 535 additions and 22 deletions.
1 change: 1 addition & 0 deletions .appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ matrix:
# scripts that run after cloning repository
install:
- git clone https://github.com/google/googletest.git External/googletest
- update_glslang_sources.py

build:
parallel: true # enable MSBuild parallel builds
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ TAGS
build/
Test/localResults/
External/googletest
External/spirv-tools
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ install:

before_script:
- git clone --depth=1 https://github.com/google/googletest.git External/googletest
- update_glslang_sources.py

script:
- mkdir build && cd build
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ cd <the directory glslang was cloned to, "External" will be a subdirectory>
git clone https://github.com/google/googletest.git External/googletest
```

If you wish to assure that SPIR-V generated from HLSL is legal for Vulkan,
or wish to invoke -Os to reduce SPIR-V size from HLSL or GLSL, install
spirv-tools with this:

```bash
./update_glslang_sources.py
```

#### 3) Configure

Assume the source directory is `$SOURCE_DIR` and
Expand Down
59 changes: 59 additions & 0 deletions SPIRV/GlslangToSpv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ namespace spv {
#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"
Expand Down Expand Up @@ -5960,6 +5970,12 @@ void OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName,
out.close();
}

#ifdef ENABLE_OPT
void errHandler(const std::string& str) {
std::cerr << str << std::endl;
}
#endif

//
// Set up the glslang traversal
//
Expand Down Expand Up @@ -5988,6 +6004,49 @@ void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsign
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();
}

Expand Down
5 changes: 4 additions & 1 deletion SPIRV/GlslangToSpv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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&);
Expand Down
18 changes: 18 additions & 0 deletions StandAlone/StandAlone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ enum TOptions {
EOptionAutoMapLocations = (1 << 25),
EOptionDebug = (1 << 26),
EOptionStdin = (1 << 27),
EOptionOptimizeDisable = (1 << 28),
EOptionOptimizeSize = (1 << 29),
};

//
Expand Down Expand Up @@ -528,6 +530,18 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
case 'I':
IncludeDirectoryList.push_back(getStringOperand("-I<dir> include path"));
break;
case 'O':
if (argv[0][2] == 'd')
Options |= EOptionOptimizeDisable;
else if (argv[0][2] == 's')
#ifdef ENABLE_OPT
Options |= EOptionOptimizeSize;
#else
Error("-Os not available; optimizer not linked");
#endif
else
Error("unknown -O option");
break;
case 'S':
if (argc <= 1)
Error("no <stage> specified for -S");
Expand Down Expand Up @@ -882,6 +896,8 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
glslang::SpvOptions spvOptions;
if (Options & EOptionDebug)
spvOptions.generateDebugInfo = true;
spvOptions.disableOptimizer = Options & EOptionOptimizeDisable;
spvOptions.optimizeSize = Options & EOptionOptimizeSize;
glslang::GlslangToSpv(*program.getIntermediate((EShLanguage)stage), spirv, &logger, &spvOptions);

// Dump the spv to a file or stdout, etc., but only if not doing
Expand Down Expand Up @@ -1201,6 +1217,8 @@ void usage()
" -H print human readable form of SPIR-V; turns on -V\n"
" -I<dir> add dir to the include search path; includer's directory\n"
" is searched first, followed by left-to-right order of -I\n"
" -Od disables optimization. May cause illegal SPIR-V for HLSL.\n"
" -Os optimizes SPIR-V to minimize size.\n"
" -S <stage> uses specified stage rather than parsing the file extension\n"
" choices for <stage> are vert, tesc, tese, geom, frag, or comp\n"
" -U<macro> undefine a pre-processor macro\n"
Expand Down
46 changes: 46 additions & 0 deletions Test/baseLegalResults/hlsl.aliasOpaque.frag.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
hlsl.aliasOpaque.frag
// Module Version 10000
// Generated by (magic number): 80001
// Id's are bound by 61

Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Fragment 4 "main" 46
ExecutionMode 4 OriginUpperLeft
Source HLSL 500
Name 4 "main"
Name 36 "gss"
Name 37 "gtex"
Name 46 "@entryPointOutput"
Decorate 36(gss) DescriptorSet 0
Decorate 37(gtex) DescriptorSet 0
Decorate 46(@entryPointOutput) Location 0
2: TypeVoid
3: TypeFunction 2
6: TypeSampler
7: TypePointer UniformConstant 6
8: TypeFloat 32
10: TypeImage 8(float) 2D sampled format:Unknown
11: TypePointer UniformConstant 10
12: TypeVector 8(float) 4
25: TypeSampledImage 10
27: TypeVector 8(float) 2
28: 8(float) Constant 1045220557
29: 8(float) Constant 1050253722
30: 27(fvec2) ConstantComposite 28 29
36(gss): 7(ptr) Variable UniformConstant
37(gtex): 11(ptr) Variable UniformConstant
39: 8(float) Constant 1077936128
45: TypePointer Output 12(fvec4)
46(@entryPointOutput): 45(ptr) Variable Output
4(main): 2 Function None 3
5: Label
56: 10 Load 37(gtex)
57: 6 Load 36(gss)
58: 25 SampledImage 56 57
59: 12(fvec4) ImageSampleImplicitLod 58 30
60: 12(fvec4) VectorTimesScalar 59 39
Store 46(@entryPointOutput) 60
Return
FunctionEnd
65 changes: 65 additions & 0 deletions Test/baseLegalResults/hlsl.flattenOpaque.frag.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
hlsl.flattenOpaque.frag
// Module Version 10000
// Generated by (magic number): 80001
// Id's are bound by 118

Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Fragment 4 "main" 83
ExecutionMode 4 OriginUpperLeft
Source HLSL 500
Name 4 "main"
Name 37 "tex"
Name 68 "s.s2D"
Name 73 "s2.s2D"
Name 74 "s2.tex"
Name 83 "@entryPointOutput"
Decorate 37(tex) DescriptorSet 0
Decorate 68(s.s2D) DescriptorSet 0
Decorate 73(s2.s2D) DescriptorSet 0
Decorate 74(s2.tex) DescriptorSet 0
Decorate 83(@entryPointOutput) Location 0
2: TypeVoid
3: TypeFunction 2
6: TypeSampler
7: TypePointer UniformConstant 6
8: TypeFloat 32
9: TypeVector 8(float) 4
14: TypeVector 8(float) 2
21: TypeImage 8(float) 2D sampled format:Unknown
22: TypePointer UniformConstant 21
37(tex): 22(ptr) Variable UniformConstant
40: TypeSampledImage 21
42: 8(float) Constant 1045220557
43: 8(float) Constant 1050253722
44: 14(fvec2) ConstantComposite 42 43
68(s.s2D): 7(ptr) Variable UniformConstant
73(s2.s2D): 7(ptr) Variable UniformConstant
74(s2.tex): 22(ptr) Variable UniformConstant
82: TypePointer Output 9(fvec4)
83(@entryPointOutput): 82(ptr) Variable Output
4(main): 2 Function None 3
5: Label
97: 21 Load 37(tex)
98: 6 Load 68(s.s2D)
99: 40 SampledImage 97 98
100: 9(fvec4) ImageSampleImplicitLod 99 44
102: 21 Load 37(tex)
103: 6 Load 68(s.s2D)
104: 40 SampledImage 102 103
106: 9(fvec4) ImageSampleImplicitLod 104 44
91: 9(fvec4) FAdd 100 106
108: 21 Load 74(s2.tex)
109: 6 Load 73(s2.s2D)
110: 40 SampledImage 108 109
111: 9(fvec4) ImageSampleImplicitLod 110 44
93: 9(fvec4) FAdd 91 111
113: 21 Load 74(s2.tex)
114: 6 Load 73(s2.s2D)
115: 40 SampledImage 113 114
117: 9(fvec4) ImageSampleImplicitLod 115 44
95: 9(fvec4) FAdd 93 117
Store 83(@entryPointOutput) 95
Return
FunctionEnd
70 changes: 70 additions & 0 deletions Test/baseLegalResults/hlsl.flattenOpaqueInit.vert.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
hlsl.flattenOpaqueInit.vert
WARNING: 0:20: '=' : cannot do member-wise aliasing for opaque members with this initializer

// Module Version 10000
// Generated by (magic number): 80001
// Id's are bound by 76

Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Vertex 4 "main" 58
Source HLSL 500
Name 4 "main"
Name 17 "FxaaTex"
MemberName 17(FxaaTex) 0 "smpl"
MemberName 17(FxaaTex) 1 "tex"
Name 36 "g_tInputTexture_sampler"
Name 37 "g_tInputTexture"
Name 39 "t"
Name 43 "flattenTemp"
Name 45 "tex2.smpl"
Name 50 "tex2.tex"
Name 58 "@entryPointOutput"
Decorate 36(g_tInputTexture_sampler) DescriptorSet 0
Decorate 37(g_tInputTexture) DescriptorSet 0
Decorate 58(@entryPointOutput) Location 0
2: TypeVoid
3: TypeFunction 2
6: TypeSampler
7: TypePointer UniformConstant 6
8: TypeFloat 32
9: TypeImage 8(float) 2D sampled format:Unknown
10: TypePointer UniformConstant 9
11: TypeVector 8(float) 4
17(FxaaTex): TypeStruct 6 9
26: TypeSampledImage 9
28: TypeVector 8(float) 2
29: 8(float) Constant 1050253722
30: 8(float) Constant 1053609165
31: 28(fvec2) ConstantComposite 29 30
32: 8(float) Constant 0
36(g_tInputTexture_sampler): 7(ptr) Variable UniformConstant
37(g_tInputTexture): 10(ptr) Variable UniformConstant
38: TypePointer UniformConstant 17(FxaaTex)
39(t): 38(ptr) Variable UniformConstant
43(flattenTemp): 38(ptr) Variable UniformConstant
45(tex2.smpl): 7(ptr) Variable UniformConstant
46: TypeInt 32 1
47: 46(int) Constant 0
50(tex2.tex): 10(ptr) Variable UniformConstant
51: 46(int) Constant 1
57: TypePointer Output 11(fvec4)
58(@entryPointOutput): 57(ptr) Variable Output
4(main): 2 Function None 3
5: Label
70: 17(FxaaTex) Load 39(t)
Store 43(flattenTemp) 70
63: 7(ptr) AccessChain 43(flattenTemp) 47
64: 6 Load 63
Store 45(tex2.smpl) 64
65: 10(ptr) AccessChain 43(flattenTemp) 51
66: 9 Load 65
Store 50(tex2.tex) 66
72: 9 Load 37(g_tInputTexture)
73: 6 Load 36(g_tInputTexture_sampler)
74: 26 SampledImage 72 73
75: 11(fvec4) ImageSampleExplicitLod 74 31 Lod 32
Store 58(@entryPointOutput) 75
Return
FunctionEnd
Loading

0 comments on commit cd1f169

Please sign in to comment.