KhronosGroup / KhronosGroup/SPIRV-Tools
Reducing binary size by breaking implicit dependency of spvtools_opt on spvtools_val
- Dominant language
- C++
- Stars
- 1.4k
- Forks
- 709
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 28
Description
Hello, I'm on the Google Chrome GPU team, specifically on the [SwiftShader project](https://swiftshader.googlesource.com/SwiftShader), a Vulkan driver implementation that targets CPUs. I've been investigating reducing the size of our binaries, and SPIRV-Tools adds a significant amount.
For SwiftShader, we only require the SPIR-V optimization feature; however, linking against only `spvtools_opt` results in linker errors because of a couple of functions from the `spvtools_val` target:
```
lld-link: error: undefined symbol: spvValidateBinary
>>> referenced by .\..\..\third_party\SPIRV-Tools\src\source\libspirv.cpp:108
>>> obj/third_party/SPIRV-Tools/src\spvtools/libspirv.obj:(public: bool __cdecl spvtools::SpirvTools::Validate(class std::__1::vector> const &) const)
>>> referenced by .\..\..\third_party\SPIRV-Tools\src\source\libspirv.cpp:113
>>> obj/third_party/SPIRV-Tools/src\spvtools/libspirv.obj:(public: bool __cdecl spvtools::SpirvTools::Validate(unsigned int const *, unsigned __int64) const)
lld-link: error: undefined symbol: spvValidateWithOptions
>>> referenced by .\..\..\third_party\SPIRV-Tools\src\source\libspirv.cpp:121
>>> obj/third_party/SPIRV-Tools/src\spvtools/libspirv.obj:(public: bool __cdecl spvtools::SpirvTools::Validate(unsigned int const *, unsigned __int64, struct spv_validator_options_t *) const)
```
This results from a couple of calls being made to `SpirvTools::Validate()`, one in `Optimizer::Run()` and one in `PassManager::Run()`. When I stub the two missing functions, `spvValidateBinary` and `spvValidateWithOptions`, our binary size is reduced by about 500 KB.
For now, I'm going with stubbing these two functions; however, I think it would be useful if there was a way to link against only `spvtools_opt` without requiring `spvtools_val`. I'm not sure what the best approach would be here, though, as the decision to validate is based on runtime flags, and the binary size reduction would have to happen at compile/link time. Perhaps there can be overloads of `Optimizer::Run()` and `PassManager::Run()` that do not call `SpirvTools::Validate()`, which would rely on the linker removing the reference to these functions.
Alternately, perhaps a build-time flag could be exposed to stub out the implementations of the `SpirvTools::Validate()` overloads to do nothing and return success. However, this option would need to be exposed in the different build systems (GN in our case, for Chrome), and we'd need it set only for our non-debug build. This is trickier than deciding which function to call.
Note that there are other teams/projects at Google that would benefit greatly from this type of binary size reduction, as SPIRVTools is used by projects like [ANGLE](https://chromium.googlesource.com/angle/angle/) and [Dawn](https://dawn.googlesource.com/dawn).
Would love to hear any thoughts or ideas for this.
Contributor guide
Research direction
Start with source/libspirv.cpp and the Optimizer::Run() and PassManager::Run() paths that reference SpirvTools::Validate(), then inspect how spvtools_opt and spvtools_val are linked. Compare the available build configurations, including GN; done means spvtools_opt can be linked without spvtools_val while the intended optimization path remains functional.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- build-system, performance
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 32/100