diff --git a/3rdparty/spirv-cross/spirv_common.hpp b/3rdparty/spirv-cross/spirv_common.hpp index 0264e8185..3bf558334 100644 --- a/3rdparty/spirv-cross/spirv_common.hpp +++ b/3rdparty/spirv-cross/spirv_common.hpp @@ -729,6 +729,9 @@ struct SPIRExpression : IVariant // Whether or not this is an access chain expression. bool access_chain = false; + // Whether or not gl_MeshVerticesEXT[].gl_Position (as a whole or .y) is referenced + bool access_meshlet_position_y = false; + // A list of expressions which this expression depends on. SmallVector expression_dependencies; @@ -1580,6 +1583,7 @@ struct AccessChainMeta bool storage_is_invariant = false; bool flattened_struct = false; bool relaxed_precision = false; + bool access_meshlet_position_y = false; }; enum ExtendedDecorations diff --git a/3rdparty/spirv-cross/spirv_glsl.cpp b/3rdparty/spirv-cross/spirv_glsl.cpp index d7ee9356c..690bc9d35 100644 --- a/3rdparty/spirv-cross/spirv_glsl.cpp +++ b/3rdparty/spirv-cross/spirv_glsl.cpp @@ -9942,6 +9942,12 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice bool relaxed_precision = has_decoration(base, DecorationRelaxedPrecision); bool pending_array_enclose = false; bool dimension_flatten = false; + bool access_meshlet_position_y = false; + + if (auto *base_expr = maybe_get(base)) + { + access_meshlet_position_y = base_expr->access_meshlet_position_y; + } // If we are translating access to a structured buffer, the first subscript '._m0' must be hidden bool hide_first_subscript = count > 1 && is_user_type_structured(base); @@ -10114,6 +10120,13 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice append_index(index, is_literal); } + if (var && has_decoration(var->self, DecorationBuiltIn) && + get_decoration(var->self, DecorationBuiltIn) == BuiltInPosition && + get_execution_model() == ExecutionModelMeshEXT) + { + access_meshlet_position_y = true; + } + type_id = type->parent_type; type = &get(type_id); @@ -10149,6 +10162,11 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice } else expr = builtin_to_glsl(builtin, type->storage); + + if (builtin == BuiltInPosition && get_execution_model() == ExecutionModelMeshEXT) + { + access_meshlet_position_y = true; + } } else { @@ -10293,6 +10311,26 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice is_packed); } + if (access_meshlet_position_y) + { + if (is_literal) + { + access_meshlet_position_y = index == 1; + } + else + { + const auto *c = maybe_get(index); + if (c) + access_meshlet_position_y = c->scalar() == 1; + else + { + // We don't know, but we have to assume no. + // Flip Y in mesh shaders is an opt-in horrible hack, so we'll have to assume shaders try to behave. + access_meshlet_position_y = false; + } + } + } + expr += deferred_index; row_major_matrix_needs_conversion = false; @@ -10319,6 +10357,7 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice meta->storage_is_invariant = is_invariant; meta->storage_physical_type = physical_type; meta->relaxed_precision = relaxed_precision; + meta->access_meshlet_position_y = access_meshlet_position_y; } return expr; @@ -11891,6 +11930,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction) expr.loaded_from = backing_variable ? backing_variable->self : ID(ops[2]); expr.need_transpose = meta.need_transpose; expr.access_chain = true; + expr.access_meshlet_position_y = meta.access_meshlet_position_y; // Mark the result as being packed. Some platforms handled packed vectors differently than non-packed. if (meta.storage_is_packed) diff --git a/3rdparty/spirv-cross/spirv_hlsl.cpp b/3rdparty/spirv-cross/spirv_hlsl.cpp index e7b6f03a8..8ba79b630 100644 --- a/3rdparty/spirv-cross/spirv_hlsl.cpp +++ b/3rdparty/spirv-cross/spirv_hlsl.cpp @@ -2254,6 +2254,20 @@ void CompilerHLSL::emit_resources() end_scope(); statement(""); } + + if (is_mesh_shader && options.vertex.flip_vert_y) + { + statement("float4 spvFlipVertY(float4 v)"); + begin_scope(); + statement("return float4(v.x, -v.y, v.z, v.w);"); + end_scope(); + statement(""); + statement("float spvFlipVertY(float v)"); + begin_scope(); + statement("return -v;"); + end_scope(); + statement(""); + } } void CompilerHLSL::emit_texture_size_variants(uint64_t variant_mask, const char *vecsize_qualifier, bool uav, @@ -4950,6 +4964,19 @@ void CompilerHLSL::write_access_chain(const SPIRAccessChain &chain, uint32_t val void CompilerHLSL::emit_store(const Instruction &instruction) { auto ops = stream(instruction); + if (options.vertex.flip_vert_y) + { + auto *expr = maybe_get(ops[0]); + if (expr != nullptr && expr->access_meshlet_position_y) + { + auto lhs = to_dereferenced_expression(ops[0]); + auto rhs = to_unpacked_expression(ops[1]); + statement(lhs, " = spvFlipVertY(", rhs, ");"); + register_write(ops[0]); + return; + } + } + auto *chain = maybe_get(ops[0]); if (chain) write_access_chain(*chain, ops[1], {}); diff --git a/3rdparty/spirv-cross/spirv_msl.cpp b/3rdparty/spirv-cross/spirv_msl.cpp index 0c7abb478..5ff72abe3 100644 --- a/3rdparty/spirv-cross/spirv_msl.cpp +++ b/3rdparty/spirv-cross/spirv_msl.cpp @@ -7187,6 +7187,35 @@ void CompilerMSL::emit_custom_functions() end_scope(); end_scope_decl(); statement(""); + break; + + case SPVFuncImplRayQueryIntersectionParams: + statement("intersection_params spvMakeIntersectionParams(uint flags)"); + begin_scope(); + statement("intersection_params ip;"); + statement("if ((flags & ", RayFlagsOpaqueKHRMask, ") != 0)"); + statement(" ip.force_opacity(forced_opacity::opaque);"); + statement("if ((flags & ", RayFlagsNoOpaqueKHRMask, ") != 0)"); + statement(" ip.force_opacity(forced_opacity::non_opaque);"); + statement("if ((flags & ", RayFlagsTerminateOnFirstHitKHRMask, ") != 0)"); + statement(" ip.accept_any_intersection(true);"); + // RayFlagsSkipClosestHitShaderKHRMask is not available in MSL + statement("if ((flags & ", RayFlagsCullBackFacingTrianglesKHRMask, ") != 0)"); + statement(" ip.set_triangle_cull_mode(triangle_cull_mode::back);"); + statement("if ((flags & ", RayFlagsCullFrontFacingTrianglesKHRMask, ") != 0)"); + statement(" ip.set_triangle_cull_mode(triangle_cull_mode::front);"); + statement("if ((flags & ", RayFlagsCullOpaqueKHRMask, ") != 0)"); + statement(" ip.set_opacity_cull_mode(opacity_cull_mode::opaque);"); + statement("if ((flags & ", RayFlagsCullNoOpaqueKHRMask, ") != 0)"); + statement(" ip.set_opacity_cull_mode(opacity_cull_mode::non_opaque);"); + statement("if ((flags & ", RayFlagsSkipTrianglesKHRMask, ") != 0)"); + statement(" ip.set_geometry_cull_mode(geometry_cull_mode::triangle);"); + statement("if ((flags & ", RayFlagsSkipAABBsKHRMask, ") != 0)"); + statement(" ip.set_geometry_cull_mode(geometry_cull_mode::bounding_box);"); + statement("return ip;"); + end_scope(); + statement(""); + break; default: break; @@ -9237,10 +9266,11 @@ void CompilerMSL::emit_instruction(const Instruction &instruction) case OpRayQueryInitializeKHR: { flush_variable_declaration(ops[0]); + add_spv_func_and_recompile(SPVFuncImplRayQueryIntersectionParams); statement(to_expression(ops[0]), ".reset(", "ray(", to_expression(ops[4]), ", ", to_expression(ops[6]), ", ", to_expression(ops[5]), ", ", to_expression(ops[7]), "), ", to_expression(ops[1]), - ", intersection_params());"); + ", spvMakeIntersectionParams(", to_expression(ops[2]), "));"); break; } case OpRayQueryProceedKHR: diff --git a/3rdparty/spirv-cross/spirv_msl.hpp b/3rdparty/spirv-cross/spirv_msl.hpp index 4c5c753db..57993978b 100644 --- a/3rdparty/spirv-cross/spirv_msl.hpp +++ b/3rdparty/spirv-cross/spirv_msl.hpp @@ -795,6 +795,7 @@ protected: SPVFuncImplConvertYCbCrBT601, SPVFuncImplConvertYCbCrBT2020, SPVFuncImplDynamicImageSampler, + SPVFuncImplRayQueryIntersectionParams, }; // If the underlying resource has been used for comparison then duplicate loads of that resource must be too