From 9ce31581934ebe2ef5fcc0acf0933c5caa1ba428 Mon Sep 17 00:00:00 2001 From: Mark Satterthwaite Date: Wed, 14 Aug 2019 10:57:23 -0400 Subject: [PATCH] When compiling from HLSL which pads and aligns float[]/float2[] within structures to float4[] we need to unpack the original type in Metal from the float4. --- spirv_glsl.hpp | 4 +++- spirv_msl.cpp | 28 +++++++++++++++++++++++++++- spirv_msl.hpp | 3 +++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/spirv_glsl.hpp b/spirv_glsl.hpp index 315df49d..5c78afda 100644 --- a/spirv_glsl.hpp +++ b/spirv_glsl.hpp @@ -528,7 +528,9 @@ protected: std::string to_unpacked_expression(uint32_t id, bool register_expression_read = true); std::string to_unpacked_row_major_matrix_expression(uint32_t id); std::string to_enclosed_unpacked_expression(uint32_t id, bool register_expression_read = true); - std::string to_dereferenced_expression(uint32_t id, bool register_expression_read = true); + /* UE Change Begin: Metal expands float[]/float2[] members inside structs to float4[] so we must unpack */ + virtual std::string to_dereferenced_expression(uint32_t id, bool register_expression_read = true); + /* UE Change End: Metal expands float[]/float2[] members inside structs to float4[] so we must unpack */ std::string to_pointer_expression(uint32_t id, bool register_expression_read = true); std::string to_enclosed_pointer_expression(uint32_t id, bool register_expression_read = true); std::string to_extract_component_expression(uint32_t id, uint32_t index); diff --git a/spirv_msl.cpp b/spirv_msl.cpp index 9ab847c2..4c955675 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -3120,6 +3120,32 @@ void CompilerMSL::emit_store_statement(uint32_t lhs_expression, uint32_t rhs_exp } } +/* UE Change Begin: Metal expands float[]/float2[] members inside structs to float4[] so we must unpack */ +string CompilerMSL::to_dereferenced_expression(uint32_t id, bool register_expression_read) +{ + auto &type = expression_type(id); + if (!type.pointer || !should_dereference(id)) + { + uint32_t packed_type_id = get_extended_decoration(id, SPIRVCrossDecorationPhysicalTypePacked); + const SPIRType *packed_type = nullptr; + if (packed_type_id) + packed_type = &get(packed_type_id); + + if (packed_type && is_array(*packed_type) && is_scalar(*packed_type)) + return to_unpacked_expression(id, register_expression_read); + } + + return CompilerGLSL::to_dereferenced_expression(id, register_expression_read); +} + +static bool expression_ends_with(string const& expr_str, std::string const& ending) +{ + if (expr_str.length() >= ending.length()) + return (0 == expr_str.compare(expr_str.length() - ending.length(), ending.length(), ending)); + else + return false; +} + // Converts the format of the current expression from packed to unpacked, // by wrapping the expression in a constructor of the appropriate type. // Also, handle special physical ID remapping scenarios, similar to emit_store_statement(). @@ -3141,7 +3167,7 @@ string CompilerMSL::unpack_expression_type(string expr_str, const SPIRType &type }; // std140 array cases for vectors. - if (physical_type && is_vector(*physical_type) && is_array(*physical_type) && physical_type->vecsize > type.vecsize) + if (physical_type && is_vector(*physical_type) && is_array(*physical_type) && physical_type->vecsize > type.vecsize && !expression_ends_with(expr_str, swizzle_lut[type.vecsize - 1])) { assert(type.vecsize >= 1 && type.vecsize <= 3); return enclose_expression(expr_str) + swizzle_lut[type.vecsize - 1]; diff --git a/spirv_msl.hpp b/spirv_msl.hpp index d48f3d8d..7c394307 100644 --- a/spirv_msl.hpp +++ b/spirv_msl.hpp @@ -580,6 +580,9 @@ protected: uint32_t grad_y, uint32_t lod, uint32_t coffset, uint32_t offset, uint32_t bias, uint32_t comp, uint32_t sample, uint32_t minlod, bool *p_forward) override; std::string to_initializer_expression(const SPIRVariable &var) override; + /* UE Change Begin: Metal expands float[]/float2[] members inside structs to float4[] so we must unpack */ + virtual std::string to_dereferenced_expression(uint32_t id, bool register_expression_read = true) override; + /* UE Change End: Metal expands float[]/float2[] members inside structs to float4[] so we must unpack */ std::string unpack_expression_type(std::string expr_str, const SPIRType &type, uint32_t physical_type_id, bool is_packed, bool row_major) override;