HLSL: Support BaseVertex/BaseInstance offsets.

Opt-in, since user need to know about a cbuffer.
Conflicts a bit with the GLSL option for base instance,
since that one is enabled by default, but the HLSL one isn't (because
user needs to know about a magic cbuffer, whereas GLSL can only get
default initialized uniform).
This commit is contained in:
Hans-Kristian Arntzen 2019-01-11 10:32:14 +01:00
parent a57b93f6b7
commit a2a44d944e
4 changed files with 42 additions and 2 deletions

View File

@ -516,6 +516,7 @@ struct CLIArguments
bool msl = false;
bool hlsl = false;
bool hlsl_compat = false;
bool hlsl_support_nonzero_base = false;
bool vulkan_semantics = false;
bool flatten_multidimensional_arrays = false;
bool use_420pack_extension = true;
@ -549,6 +550,7 @@ static void print_help()
"\t[--reflect]\n"
"\t[--shader-model]\n"
"\t[--hlsl-enable-compat]\n"
"\t[--hlsl-support-nonzero-basevertex-baseinstance]\n"
"\t[--separate-shader-objects]\n"
"\t[--pls-in format input-name]\n"
"\t[--pls-out format output-name]\n"
@ -705,6 +707,7 @@ static int main_inner(int argc, char *argv[])
cbs.add("--msl", [&args](CLIParser &) { args.msl = true; });
cbs.add("--hlsl", [&args](CLIParser &) { args.hlsl = true; });
cbs.add("--hlsl-enable-compat", [&args](CLIParser &) { args.hlsl_compat = true; });
cbs.add("--hlsl-support-nonzero-basevertex-baseinstance", [&args](CLIParser &) { args.hlsl_support_nonzero_base = true; });
cbs.add("--vulkan-semantics", [&args](CLIParser &) { args.vulkan_semantics = true; });
cbs.add("--flatten-multidimensional-arrays", [&args](CLIParser &) { args.flatten_multidimensional_arrays = true; });
cbs.add("--no-420pack-extension", [&args](CLIParser &) { args.use_420pack_extension = false; });
@ -991,6 +994,7 @@ static int main_inner(int argc, char *argv[])
build_dummy_sampler = true;
}
hlsl_opts.support_nonzero_base_vertex_base_instance = args.hlsl_support_nonzero_base;
hlsl->set_hlsl_options(hlsl_opts);
}

View File

@ -105,6 +105,7 @@ public:
// Inverts gl_Position.y or equivalent.
bool flip_vert_y = false;
// GLSL only, for HLSL version of this option, see CompilerHLSL.
// If true, the backend will assume that InstanceIndex will need to apply
// a base instance offset. Set to false if you know you will never use base instance
// functionality as it might remove some internal uniforms.

View File

@ -902,6 +902,8 @@ void CompilerHLSL::emit_builtin_variables()
Bitset builtins = active_input_builtins;
builtins.merge_or(active_output_builtins);
bool need_base_vertex_info = false;
// Emit global variables for the interface variables which are statically used by the shader.
builtins.for_each_bit([&](uint32_t i) {
const char *type = nullptr;
@ -921,8 +923,13 @@ void CompilerHLSL::emit_builtin_variables()
case BuiltInVertexId:
case BuiltInVertexIndex:
case BuiltInInstanceId:
case BuiltInInstanceIndex:
type = "int";
if (hlsl_options.support_nonzero_base_vertex_base_instance)
need_base_vertex_info = true;
break;
case BuiltInInstanceId:
case BuiltInSampleId:
type = "int";
break;
@ -998,6 +1005,16 @@ void CompilerHLSL::emit_builtin_variables()
statement("static ", type, " ", builtin_to_glsl(builtin, storage), ";");
}
});
if (need_base_vertex_info)
{
statement("cbuffer SPIRV_Cross_VertexInfo");
begin_scope();
statement("int SPIRV_Cross_BaseVertex;");
statement("int SPIRV_Cross_BaseInstance;");
end_scope_decl();
statement("");
}
}
void CompilerHLSL::emit_composite_constants()
@ -2243,8 +2260,20 @@ void CompilerHLSL::emit_hlsl_entry_point()
case BuiltInVertexId:
case BuiltInVertexIndex:
case BuiltInInstanceId:
case BuiltInInstanceIndex:
// D3D semantics are uint, but shader wants int.
if (hlsl_options.support_nonzero_base_vertex_base_instance)
{
if (static_cast<BuiltIn>(i) == BuiltInInstanceIndex)
statement(builtin, " = int(stage_input.", builtin, ") + SPIRV_Cross_BaseInstance;");
else
statement(builtin, " = int(stage_input.", builtin, ") + SPIRV_Cross_BaseVertex;");
}
else
statement(builtin, " = int(stage_input.", builtin, ");");
break;
case BuiltInInstanceId:
// D3D semantics are uint, but shader wants int.
statement(builtin, " = int(stage_input.", builtin, ");");
break;

View File

@ -54,6 +54,12 @@ public:
// Allows the PointCoord builtin, returns float2(0.5, 0.5), as PointCoord is not supported in HLSL.
bool point_coord_compat = false;
// If true, the backend will assume that VertexIndex and InstanceIndex will need to apply
// a base offset, and you will need to fill in a cbuffer with offsets.
// Set to false if you know you will never use base instance or base vertex
// functionality as it might remove an internal cbuffer.
bool support_nonzero_base_vertex_base_instance = false;
};
explicit CompilerHLSL(std::vector<uint32_t> spirv_)