HLSL: Add location offsets per resource type
This PR adds the ability to offset sampler, texture, and UBO bindings from provided base bindings, and to auto-number bindings that are not provided with explicit register numbers. The mechanism works as follows: - Offsets may be given on the command line for all stages, or individually for one or more single stages, in which case the offset will be auto-selected according to the stage being compiled. There is also an API to set them. The new command line options are --shift-sampler-binding, --shift-texture-binding, and --shift-UBO-binding. - Uniforms which are not given explicit bindings in the source code are auto-numbered if and only if they are in live code as determined by the algorithm used to build the reflection database, and the --auto-map-bindings option is given. This auto-numbering avoids using any binding slots which were explicitly provided in the code, whether or not that explicit use was live. E.g, "uniform Texture1D foo : register(t3);" with --shift-texture-binding 10 will reserve binding 13, whether or not foo is used in live code. - Shorter synonyms for the command line options are available. See the --help output. The testing infrastructure is slightly extended to allow use of the binding offset API, and two new tests spv.register.(no)autoassign.frag are added for comparing the resulting SPIR-V.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
//
|
||||
//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
//Copyright (C) 2013 LunarG, Inc.
|
||||
//Copyright (C) 2013-2016 LunarG, Inc.
|
||||
//
|
||||
//All rights reserved.
|
||||
//
|
||||
@@ -48,7 +48,9 @@
|
||||
#include "../SPIRV/disassemble.h"
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <cctype>
|
||||
#include <cmath>
|
||||
#include <array>
|
||||
|
||||
#include "../glslang/OSDependent/osinclude.h"
|
||||
|
||||
@@ -78,6 +80,7 @@ enum TOptions {
|
||||
EOptionOutputHexadecimal = (1 << 16),
|
||||
EOptionReadHlsl = (1 << 17),
|
||||
EOptionCascadingErrors = (1 << 18),
|
||||
EOptionAutoMapBindings = (1 << 19),
|
||||
};
|
||||
|
||||
//
|
||||
@@ -96,7 +99,7 @@ enum TFailCode {
|
||||
//
|
||||
// Forward declarations.
|
||||
//
|
||||
EShLanguage FindLanguage(const std::string& name);
|
||||
EShLanguage FindLanguage(const std::string& name, bool parseSuffix=true);
|
||||
void CompileFile(const char* fileName, ShHandle);
|
||||
void usage();
|
||||
void FreeFileData(char** data);
|
||||
@@ -157,6 +160,10 @@ const char* binaryFileName = nullptr;
|
||||
const char* entryPointName = nullptr;
|
||||
const char* shaderStageName = nullptr;
|
||||
|
||||
std::array<unsigned int, EShLangCount> baseSamplerBinding;
|
||||
std::array<unsigned int, EShLangCount> baseTextureBinding;
|
||||
std::array<unsigned int, EShLangCount> baseUboBinding;
|
||||
|
||||
//
|
||||
// Create the default name for saving a binary if -o is not provided.
|
||||
//
|
||||
@@ -204,6 +211,35 @@ void Error(const char* message)
|
||||
exit(EFailUsage);
|
||||
}
|
||||
|
||||
//
|
||||
// Process an optional binding base of the form:
|
||||
// --argname [stage] base
|
||||
// Where stage is one of the forms accepted by FindLanguage, and base is an integer
|
||||
//
|
||||
void ProcessBindingBase(int& argc, char**& argv, std::array<unsigned int, EShLangCount>& base)
|
||||
{
|
||||
if (argc < 2)
|
||||
usage();
|
||||
|
||||
if (!isdigit(argv[1][0])) {
|
||||
if (argc < 3) // this form needs one more argument
|
||||
usage();
|
||||
|
||||
// Parse form: --argname stage base
|
||||
const EShLanguage lang = FindLanguage(argv[1], false);
|
||||
base[lang] = atoi(argv[2]);
|
||||
argc-= 2;
|
||||
argv+= 2;
|
||||
} else {
|
||||
// Parse form: --argname base
|
||||
for (int lang=0; lang<EShLangCount; ++lang)
|
||||
base[lang] = atoi(argv[1]);
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Do all command-line argument parsing. This includes building up the work-items
|
||||
// to be processed later, and saving all the command-line options.
|
||||
@@ -212,6 +248,10 @@ void Error(const char* message)
|
||||
//
|
||||
void ProcessArguments(int argc, char* argv[])
|
||||
{
|
||||
baseSamplerBinding.fill(0);
|
||||
baseTextureBinding.fill(0);
|
||||
baseUboBinding.fill(0);
|
||||
|
||||
ExecutableName = argv[0];
|
||||
NumWorkItems = argc; // will include some empties where the '-' options were, but it doesn't matter, they'll be 0
|
||||
Work = new glslang::TWorkItem*[NumWorkItems];
|
||||
@@ -223,6 +263,33 @@ void ProcessArguments(int argc, char* argv[])
|
||||
for (; argc >= 1; argc--, argv++) {
|
||||
if (argv[0][0] == '-') {
|
||||
switch (argv[0][1]) {
|
||||
case '-':
|
||||
{
|
||||
std::string lowerword(argv[0]+2);
|
||||
std::transform(lowerword.begin(), lowerword.end(), lowerword.begin(), ::tolower);
|
||||
|
||||
// handle --word style options
|
||||
if (lowerword == "shift-sampler-bindings" || // synonyms
|
||||
lowerword == "shift-sampler-binding" ||
|
||||
lowerword == "ssb") {
|
||||
ProcessBindingBase(argc, argv, baseSamplerBinding);
|
||||
} else if (lowerword == "shift-texture-bindings" || // synonyms
|
||||
lowerword == "shift-texture-binding" ||
|
||||
lowerword == "stb") {
|
||||
ProcessBindingBase(argc, argv, baseTextureBinding);
|
||||
} else if (lowerword == "shift-ubo-bindings" || // synonyms
|
||||
lowerword == "shift-ubo-binding" ||
|
||||
lowerword == "sub") {
|
||||
ProcessBindingBase(argc, argv, baseUboBinding);
|
||||
} else if (lowerword == "auto-map-bindings" || // synonyms
|
||||
lowerword == "auto-map-binding" ||
|
||||
lowerword == "amb") {
|
||||
Options |= EOptionAutoMapBindings;
|
||||
} else {
|
||||
usage();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'H':
|
||||
Options |= EOptionHumanReadableSpv;
|
||||
if ((Options & EOptionSpv) == 0) {
|
||||
@@ -461,6 +528,14 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
|
||||
shader->setStringsWithLengthsAndNames(compUnit.text, NULL, compUnit.fileNameList, 1);
|
||||
if (entryPointName) // HLSL todo: this needs to be tracked per compUnits
|
||||
shader->setEntryPoint(entryPointName);
|
||||
|
||||
shader->setShiftSamplerBinding(baseSamplerBinding[compUnit.stage]);
|
||||
shader->setShiftTextureBinding(baseTextureBinding[compUnit.stage]);
|
||||
shader->setShiftUboBinding(baseUboBinding[compUnit.stage]);
|
||||
|
||||
if (Options & EOptionAutoMapBindings)
|
||||
shader->setAutoMapBindings(true);
|
||||
|
||||
shaders.push_back(shader);
|
||||
|
||||
const int defaultVersion = Options & EOptionDefaultDesktop? 110: 100;
|
||||
@@ -506,6 +581,10 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
|
||||
PutsIfNonEmpty(program.getInfoDebugLog());
|
||||
}
|
||||
|
||||
// Map IO
|
||||
if (Options & EOptionSpv)
|
||||
program.mapIO();
|
||||
|
||||
// Reflect
|
||||
if (Options & EOptionDumpReflection) {
|
||||
program.buildReflection();
|
||||
@@ -705,15 +784,22 @@ int C_DECL main(int argc, char* argv[])
|
||||
// .frag = fragment
|
||||
// .comp = compute
|
||||
//
|
||||
EShLanguage FindLanguage(const std::string& name)
|
||||
EShLanguage FindLanguage(const std::string& name, bool parseSuffix)
|
||||
{
|
||||
size_t ext = name.rfind('.');
|
||||
if (ext == std::string::npos) {
|
||||
usage();
|
||||
return EShLangVertex;
|
||||
size_t ext = 0;
|
||||
|
||||
// Search for a suffix on a filename: e.g, "myfile.frag". If given
|
||||
// the suffix directly, we skip looking the '.'
|
||||
if (parseSuffix) {
|
||||
ext = name.rfind('.');
|
||||
if (ext == std::string::npos) {
|
||||
usage();
|
||||
return EShLangVertex;
|
||||
}
|
||||
++ext;
|
||||
}
|
||||
|
||||
std::string suffix = name.substr(ext + 1, std::string::npos);
|
||||
std::string suffix = name.substr(ext, std::string::npos);
|
||||
if (shaderStageName)
|
||||
suffix = shaderStageName;
|
||||
|
||||
@@ -831,6 +917,19 @@ void usage()
|
||||
" -v print version strings\n"
|
||||
" -w suppress warnings (except as required by #extension : warn)\n"
|
||||
" -x save 32-bit hexadecimal numbers as text, requires a binary option (e.g., -V)\n"
|
||||
"\n"
|
||||
" --shift-sampler-binding [stage] num set base binding number for samplers\n"
|
||||
" --ssb [stage] num synonym for --shift-sampler-binding\n"
|
||||
"\n"
|
||||
" --shift-texture-binding [stage] num set base binding number for textures\n"
|
||||
" --stb [stage] num synonym for --shift-texture-binding\n"
|
||||
"\n"
|
||||
" --shift-UBO-binding [stage] num set base binding number for UBOs\n"
|
||||
" --sub [stage] num synonym for --shift-UBO-binding\n"
|
||||
"\n"
|
||||
" --auto-map-bindings automatically bind uniform variables without\n"
|
||||
" explicit bindings.\n"
|
||||
" --amb synonym for --auto-map-bindings\n"
|
||||
);
|
||||
|
||||
exit(EFailUsage);
|
||||
|
||||
Reference in New Issue
Block a user