diff options
-rw-r--r-- | reference/opt/shaders-msl/vert/uniform-struct-out-of-order-offests.vert | 32 | ||||
-rw-r--r-- | reference/shaders-msl/vert/uniform-struct-out-of-order-offests.vert | 35 | ||||
-rw-r--r-- | shaders-msl/vert/uniform-struct-out-of-order-offests.vert | 31 | ||||
-rw-r--r-- | spirv_glsl.cpp | 5 | ||||
-rw-r--r-- | spirv_msl.cpp | 11 |
5 files changed, 107 insertions, 7 deletions
diff --git a/reference/opt/shaders-msl/vert/uniform-struct-out-of-order-offests.vert b/reference/opt/shaders-msl/vert/uniform-struct-out-of-order-offests.vert new file mode 100644 index 00000000..c69775e3 --- /dev/null +++ b/reference/opt/shaders-msl/vert/uniform-struct-out-of-order-offests.vert @@ -0,0 +1,32 @@ +#include <metal_stdlib> +#include <simd/simd.h> + +using namespace metal; + +struct data_u_t +{ + int4 m1[3]; + uint m3; + uint3 m2; + int4 m0[8]; +}; + +struct main0_out +{ + float foo [[user(locn0)]]; + float4 gl_Position [[position]]; +}; + +struct main0_in +{ + float4 vtx_posn [[attribute(0)]]; +}; + +vertex main0_out main0(main0_in in [[stage_in]], constant data_u_t& data_u [[buffer(0)]]) +{ + main0_out out = {}; + out.gl_Position = in.vtx_posn; + out.foo = float((uint3(data_u.m1[1].xyz) + data_u.m2).y * uint(data_u.m0[4].x)); + return out; +} + diff --git a/reference/shaders-msl/vert/uniform-struct-out-of-order-offests.vert b/reference/shaders-msl/vert/uniform-struct-out-of-order-offests.vert new file mode 100644 index 00000000..4f71b205 --- /dev/null +++ b/reference/shaders-msl/vert/uniform-struct-out-of-order-offests.vert @@ -0,0 +1,35 @@ +#include <metal_stdlib> +#include <simd/simd.h> + +using namespace metal; + +struct data_u_t +{ + int4 m1[3]; + uint m3; + uint3 m2; + int4 m0[8]; +}; + +struct main0_out +{ + float foo [[user(locn0)]]; + float4 gl_Position [[position]]; +}; + +struct main0_in +{ + float4 vtx_posn [[attribute(0)]]; +}; + +vertex main0_out main0(main0_in in [[stage_in]], constant data_u_t& data_u [[buffer(0)]]) +{ + main0_out out = {}; + out.gl_Position = in.vtx_posn; + int4 a = data_u.m1[1]; + uint3 b = data_u.m2; + int c = data_u.m0[4].x; + out.foo = float((uint3(a.xyz) + b).y * uint(c)); + return out; +} + diff --git a/shaders-msl/vert/uniform-struct-out-of-order-offests.vert b/shaders-msl/vert/uniform-struct-out-of-order-offests.vert new file mode 100644 index 00000000..21234f94 --- /dev/null +++ b/shaders-msl/vert/uniform-struct-out-of-order-offests.vert @@ -0,0 +1,31 @@ +#version 450 + +out gl_PerVertex +{ + vec4 gl_Position; + float gl_PointSize; + float gl_ClipDistance[1]; + float gl_CullDistance[1]; +}; + +layout(set = 0, binding = 0, std140) uniform data_u_t +{ + layout(offset = 80) mediump int m0[8]; + layout(offset = 0) mediump ivec4 m1[3]; + layout(offset = 64) uvec3 m2; + layout(offset = 48) mediump uint m3; +} data_u; + +layout(location = 0) in vec4 vtx_posn; +layout(location = 0) out mediump float foo; + +void main() +{ + gl_Position = vtx_posn; + ivec4 a = data_u.m1[1]; + uvec3 b = data_u.m2; + int c = data_u.m0[4]; + foo = (a.xyz + b).y * c; +} + + diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index 0a00947f..61acda6a 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -8761,13 +8761,16 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice access_chain_is_arrayed = true; } - // For structs, the index refers to a constant, which indexes into the members. + // For structs, the index refers to a constant, which indexes into the members, possibly through a redirection mapping. // We also check if this member is a builtin, since we then replace the entire expression with the builtin one. else if (type->basetype == SPIRType::Struct) { if (!is_literal) index = evaluate_constant_u32(index); + if (index < uint32_t(type->member_type_index_redirection.size())) + index = type->member_type_index_redirection[index]; + if (index >= type->member_types.size()) SPIRV_CROSS_THROW("Member index is out of bounds!"); diff --git a/spirv_msl.cpp b/spirv_msl.cpp index ceed1c61..a7ec6d97 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -13234,9 +13234,6 @@ void CompilerMSL::sync_entry_point_aliases_and_names() string CompilerMSL::to_member_reference(uint32_t base, const SPIRType &type, uint32_t index, bool ptr_chain) { - if (index < uint32_t(type.member_type_index_redirection.size())) - index = type.member_type_index_redirection[index]; - auto *var = maybe_get<SPIRVariable>(base); // If this is a buffer array, we have to dereference the buffer pointers. // Otherwise, if this is a pointer expression, dereference it. @@ -15374,11 +15371,13 @@ void CompilerMSL::MemberSorter::sort() meta.members[mbr_idx] = mbr_meta_cpy[mbr_idxs[mbr_idx]]; } + // If we're sorting by Offset, this might affect user code which accesses a buffer block. + // We will need to redirect member indices from defined index to sorted index using reverse lookup. if (sort_aspect == SortAspect::Offset) { - // If we're sorting by Offset, this might affect user code which accesses a buffer block. - // We will need to redirect member indices from one index to sorted index. - type.member_type_index_redirection = std::move(mbr_idxs); + type.member_type_index_redirection.resize(mbr_cnt); + for (uint32_t map_idx = 0; map_idx < mbr_cnt; map_idx++) + type.member_type_index_redirection[mbr_idxs[map_idx]] = map_idx; } } |