diff --git a/spirv_msl.cpp b/spirv_msl.cpp index 35b3980f..27b35409 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -2315,11 +2315,23 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage, bool patch) { // The first member of the indirect buffer is always the number of vertices // to draw. - statement("device ", to_name(ir.default_entry_point), "_", ib_var_ref, "& ", ib_var_ref, " = ", - output_buffer_var_name, "[(", to_expression(builtin_instance_idx_id), " - ", - to_expression(builtin_base_instance_id), ") * spvIndirectParams[0] + ", - to_expression(builtin_vertex_idx_id), " - ", to_expression(builtin_base_vertex_id), - "];"); + /* UE Change Begin: We zero-base the InstanceID & VertexID variables for HLSL emulation elsewhere, so don't do it twice */ + if (ir.source.hlsl == true) + { + statement("device ", to_name(ir.default_entry_point), "_", ib_var_ref, "& ", ib_var_ref, " = ", + output_buffer_var_name, "[", to_expression(builtin_instance_idx_id), " * spvIndirectParams[0] + ", + to_expression(builtin_vertex_idx_id), + "];"); + } + else + { + statement("device ", to_name(ir.default_entry_point), "_", ib_var_ref, "& ", ib_var_ref, " = ", + output_buffer_var_name, "[(", to_expression(builtin_instance_idx_id), " - ", + to_expression(builtin_base_instance_id), ") * spvIndirectParams[0] + ", + to_expression(builtin_vertex_idx_id), " - ", to_expression(builtin_base_vertex_id), + "];"); + } + /* UE Change End: We zero-base the InstanceID & VertexID variables for HLSL emulation elsewhere, so don't do it twice */ } }); break; @@ -8024,7 +8036,11 @@ void CompilerMSL::emit_struct_member(const SPIRType &type, uint32_t member_type_ statement("char _m", index, "_pad", "[", pad_len, "];"); } + /* UE Change Begin: Handle HLSL-style 0-based vertex/instance index. */ + builtin_declaration = true; statement(to_struct_member(type, member_type_id, index, qualifier)); + builtin_declaration = false; + /* UE Change End: Handle HLSL-style 0-based vertex/instance index. */ } void CompilerMSL::emit_struct_padding_target(const SPIRType &type) @@ -8572,6 +8588,8 @@ void CompilerMSL::entry_point_args_builtin(string &ep_args) if (!ep_args.empty()) ep_args += ", "; + /* UE Change Begin: Handle HLSL-style 0-based vertex/instance index. */ + builtin_declaration = true; ep_args += builtin_type_decl(bi_type, var_id) + " " + to_expression(var_id); ep_args += " [[" + builtin_qualifier(bi_type); if (bi_type == BuiltInSampleMask && get_entry_point().flags.get(ExecutionModePostDepthCoverage)) @@ -8583,6 +8601,8 @@ void CompilerMSL::entry_point_args_builtin(string &ep_args) ep_args += ", post_depth_coverage"; } ep_args += "]]"; + builtin_declaration = false; + /* UE Change End: Handle HLSL-style 0-based vertex/instance index. */ } } @@ -8613,6 +8633,14 @@ void CompilerMSL::entry_point_args_builtin(string &ep_args) if (needs_instance_idx_arg) ep_args += built_in_func_arg(BuiltInInstanceIndex, !ep_args.empty()); + /* UE Change Begin: Handle HLSL-style 0-based vertex/instance index. */ + if (needs_base_vertex_arg > 0) + ep_args += built_in_func_arg(BuiltInBaseVertex, !ep_args.empty()); + + if (needs_base_instance_arg > 0) + ep_args += built_in_func_arg(BuiltInBaseInstance, !ep_args.empty()); + /* UE Change End: Handle HLSL-style 0-based vertex/instance index. */ + if (capture_output_to_buffer) { // Add parameters to hold the indirect draw parameters and the shader output. This has to be handled @@ -10580,19 +10608,97 @@ string CompilerMSL::builtin_to_glsl(BuiltIn builtin, StorageClass storage) switch (builtin) { + /* UE Change Begin: Handle HLSL-style 0-based vertex/instance index. */ // Override GLSL compiler strictness case BuiltInVertexId: - return "gl_VertexID"; + if ((ir.source.hlsl == true) && msl_options.supports_msl_version(1, 1) && (msl_options.ios_support_base_vertex_instance || msl_options.is_macos())) + { + if (builtin_declaration) + { + needs_base_vertex_arg++; + return "gl_VertexID"; + } + else + { + return "(gl_VertexID - gl_BaseVertex)"; + } + } + else + { + return "gl_VertexID"; + } case BuiltInInstanceId: - return "gl_InstanceID"; + if ((ir.source.hlsl == true) && msl_options.supports_msl_version(1, 1) && (msl_options.ios_support_base_vertex_instance || msl_options.is_macos())) + { + if (builtin_declaration) + { + needs_base_instance_arg++; + return "gl_InstanceID"; + } + else + { + return "(gl_InstanceID - gl_BaseInstance)"; + } + } + else + { + return "gl_InstanceID"; + } case BuiltInVertexIndex: - return "gl_VertexIndex"; + if ((ir.source.hlsl == true) && msl_options.supports_msl_version(1, 1) && (msl_options.ios_support_base_vertex_instance || msl_options.is_macos())) + { + if (builtin_declaration) + { + needs_base_vertex_arg++; + return "gl_VertexIndex"; + } + else + { + return "(gl_VertexIndex - gl_BaseVertex)"; + } + } + else + { + return "gl_VertexIndex"; + } case BuiltInInstanceIndex: - return "gl_InstanceIndex"; + if ((ir.source.hlsl == true) && msl_options.supports_msl_version(1, 1) && (msl_options.ios_support_base_vertex_instance || msl_options.is_macos())) + { + if (builtin_declaration) + { + needs_base_instance_arg++; + return "gl_InstanceIndex"; + } + else + { + return "(gl_InstanceIndex - gl_BaseInstance)"; + } + } + else + { + return "gl_InstanceIndex"; + } case BuiltInBaseVertex: + if (msl_options.supports_msl_version(1, 1) && (msl_options.ios_support_base_vertex_instance || msl_options.is_macos())) + { + needs_base_vertex_arg--; return "gl_BaseVertex"; + } + else + { + SPIRV_CROSS_THROW("BaseVertex requires Metal 1.1 and Mac or Apple A9+ hardware."); + } case BuiltInBaseInstance: + if (msl_options.supports_msl_version(1, 1) && (msl_options.ios_support_base_vertex_instance || msl_options.is_macos())) + { + needs_base_instance_arg--; return "gl_BaseInstance"; + } + else + { + SPIRV_CROSS_THROW("BaseInstance requires Metal 1.1 and Mac or Apple A9+ hardware."); + } + /* UE Change End: Handle HLSL-style 0-based vertex/instance index. */ case BuiltInDrawIndex: SPIRV_CROSS_THROW("DrawIndex is not supported in MSL."); @@ -10975,9 +11081,13 @@ string CompilerMSL::built_in_func_arg(BuiltIn builtin, bool prefix_comma) if (prefix_comma) bi_arg += ", "; + /* UE Change Begin: Handle HLSL-style 0-based vertex/instance index. */ + builtin_declaration = true; bi_arg += builtin_type_decl(builtin); bi_arg += " " + builtin_to_glsl(builtin, StorageClassInput); bi_arg += " [[" + builtin_qualifier(builtin) + "]]"; + builtin_declaration = false; + /* UE Change End: Handle HLSL-style 0-based vertex/instance index. */ return bi_arg; } diff --git a/spirv_msl.hpp b/spirv_msl.hpp index 47518374..90a0639f 100644 --- a/spirv_msl.hpp +++ b/spirv_msl.hpp @@ -281,6 +281,9 @@ public: // Fragment output in MSL must have at least as many components as the render pass. // Add support to explicit pad out components. bool pad_fragment_output_components = false; + /* UE Change Begin: Handle HLSL-style 0-based vertex/instance index. */ + bool ios_support_base_vertex_instance = false; + /* UE Change End: Handle HLSL-style 0-based vertex/instance index. */ /* UE Change Begin: Use Metal's native frame-buffer fetch API for subpass inputs. */ bool ios_use_framebuffer_fetch_subpasses = true; /* UE Change End: Use Metal's native frame-buffer fetch API for subpass inputs. */ @@ -773,9 +776,16 @@ protected: uint32_t patch_stage_out_var_id = 0; uint32_t stage_in_ptr_var_id = 0; uint32_t stage_out_ptr_var_id = 0; + /* UE Change Begin: Handle HLSL-style 0-based vertex/instance index. */ + int32_t needs_base_vertex_arg = 0; + int32_t needs_base_instance_arg = 0; + /* UE Change End: Handle HLSL-style 0-based vertex/instance index. */ bool has_sampled_images = false; bool needs_vertex_idx_arg = false; bool needs_instance_idx_arg = false; + /* UE Change Begin: Handle HLSL-style 0-based vertex/instance index. */ + bool builtin_declaration = false; + /* UE Change End: Handle HLSL-style 0-based vertex/instance index. */ /* UE Change Begin: Force the use of C style array declaration. */ bool use_builtin_array = false; /* UE Change End: Force the use of C style array declaration. */