diff --git a/main.cpp b/main.cpp index 660d77e3..26908a95 100644 --- a/main.cpp +++ b/main.cpp @@ -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); } diff --git a/spirv_glsl.hpp b/spirv_glsl.hpp index f42e98d3..6192e7a4 100644 --- a/spirv_glsl.hpp +++ b/spirv_glsl.hpp @@ -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. diff --git a/spirv_hlsl.cpp b/spirv_hlsl.cpp index 486fec54..124ff3a5 100644 --- a/spirv_hlsl.cpp +++ b/spirv_hlsl.cpp @@ -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(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; diff --git a/spirv_hlsl.hpp b/spirv_hlsl.hpp index 67243637..02d989ed 100644 --- a/spirv_hlsl.hpp +++ b/spirv_hlsl.hpp @@ -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 spirv_)