mirror of
https://github.com/KhronosGroup/SPIRV-Cross.git
synced 2024-11-09 22:00:05 +00:00
HLSL: Support loading complex composites from ByteAddressBuffer.
This commit is contained in:
parent
b522b409ae
commit
ca9398c122
108
reference/opt/shaders-hlsl/comp/access-chain-load-composite.comp
Normal file
108
reference/opt/shaders-hlsl/comp/access-chain-load-composite.comp
Normal file
@ -0,0 +1,108 @@
|
||||
struct Baz
|
||||
{
|
||||
float c;
|
||||
};
|
||||
|
||||
struct Bar
|
||||
{
|
||||
float d[2][4];
|
||||
Baz baz[2];
|
||||
};
|
||||
|
||||
struct Foo
|
||||
{
|
||||
column_major float2x2 a;
|
||||
float2 b;
|
||||
Bar c[5];
|
||||
};
|
||||
|
||||
static const uint3 gl_WorkGroupSize = uint3(1u, 1u, 1u);
|
||||
|
||||
RWByteAddressBuffer _31 : register(u0);
|
||||
|
||||
void comp_main()
|
||||
{
|
||||
Foo _36;
|
||||
_36.a = asfloat(uint2x2(_31.Load(0), _31.Load(8), _31.Load(4), _31.Load(12)));
|
||||
_36.b = asfloat(uint2(_31.Load(16), _31.Load(24)));
|
||||
[unroll]
|
||||
for (int _4ident = 0; _4ident < 5; _4ident++)
|
||||
{
|
||||
[unroll]
|
||||
for (int _5ident = 0; _5ident < 2; _5ident++)
|
||||
{
|
||||
[unroll]
|
||||
for (int _6ident = 0; _6ident < 4; _6ident++)
|
||||
{
|
||||
_36.c[_4ident].d[_5ident][_6ident] = asfloat(_31.Load(_6ident * 4 + _5ident * 16 + _4ident * 40 + 24));
|
||||
}
|
||||
}
|
||||
[unroll]
|
||||
for (int _7ident = 0; _7ident < 2; _7ident++)
|
||||
{
|
||||
_36.c[_4ident].baz[_7ident].c = asfloat(_31.Load(_7ident * 4 + _4ident * 40 + 56));
|
||||
}
|
||||
}
|
||||
float2x2 _234 = float2x2(_36.a[0] + 1.0f.xx, _36.a[1] + 1.0f.xx);
|
||||
_31.Store(224, asuint(_234[0].x));
|
||||
_31.Store(228, asuint(_234[1].x));
|
||||
_31.Store(232, asuint(_234[0].y));
|
||||
_31.Store(236, asuint(_234[1].y));
|
||||
_31.Store2(240, asuint(_36.b + 2.0f.xx));
|
||||
_31.Store(248, asuint(_36.c[0].d[0][0]));
|
||||
_31.Store(252, asuint(_36.c[0].d[0][1]));
|
||||
_31.Store(256, asuint(_36.c[0].d[0][2]));
|
||||
_31.Store(260, asuint(_36.c[0].d[0][3]));
|
||||
_31.Store(264, asuint(_36.c[0].d[1][0]));
|
||||
_31.Store(268, asuint(_36.c[0].d[1][1]));
|
||||
_31.Store(272, asuint(_36.c[0].d[1][2]));
|
||||
_31.Store(276, asuint(_36.c[0].d[1][3]));
|
||||
_31.Store(280, asuint(_36.c[0].baz[0].c));
|
||||
_31.Store(284, asuint(_36.c[0].baz[1].c));
|
||||
_31.Store(288, asuint(_36.c[1].d[0][0]));
|
||||
_31.Store(292, asuint(_36.c[1].d[0][1]));
|
||||
_31.Store(296, asuint(_36.c[1].d[0][2]));
|
||||
_31.Store(300, asuint(_36.c[1].d[0][3]));
|
||||
_31.Store(304, asuint(_36.c[1].d[1][0]));
|
||||
_31.Store(308, asuint(_36.c[1].d[1][1]));
|
||||
_31.Store(312, asuint(_36.c[1].d[1][2]));
|
||||
_31.Store(316, asuint(_36.c[1].d[1][3]));
|
||||
_31.Store(320, asuint(_36.c[1].baz[0].c));
|
||||
_31.Store(324, asuint(_36.c[1].baz[1].c));
|
||||
_31.Store(328, asuint(_36.c[2].d[0][0]));
|
||||
_31.Store(332, asuint(_36.c[2].d[0][1]));
|
||||
_31.Store(336, asuint(_36.c[2].d[0][2]));
|
||||
_31.Store(340, asuint(_36.c[2].d[0][3]));
|
||||
_31.Store(344, asuint(_36.c[2].d[1][0]));
|
||||
_31.Store(348, asuint(_36.c[2].d[1][1]));
|
||||
_31.Store(352, asuint(_36.c[2].d[1][2]));
|
||||
_31.Store(356, asuint(_36.c[2].d[1][3]));
|
||||
_31.Store(360, asuint(_36.c[2].baz[0].c));
|
||||
_31.Store(364, asuint(_36.c[2].baz[1].c));
|
||||
_31.Store(368, asuint(_36.c[3].d[0][0]));
|
||||
_31.Store(372, asuint(_36.c[3].d[0][1]));
|
||||
_31.Store(376, asuint(_36.c[3].d[0][2]));
|
||||
_31.Store(380, asuint(_36.c[3].d[0][3]));
|
||||
_31.Store(384, asuint(_36.c[3].d[1][0]));
|
||||
_31.Store(388, asuint(_36.c[3].d[1][1] + 5.0f));
|
||||
_31.Store(392, asuint(_36.c[3].d[1][2]));
|
||||
_31.Store(396, asuint(_36.c[3].d[1][3]));
|
||||
_31.Store(400, asuint(_36.c[3].baz[0].c));
|
||||
_31.Store(404, asuint(_36.c[3].baz[1].c));
|
||||
_31.Store(408, asuint(_36.c[4].d[0][0]));
|
||||
_31.Store(412, asuint(_36.c[4].d[0][1]));
|
||||
_31.Store(416, asuint(_36.c[4].d[0][2]));
|
||||
_31.Store(420, asuint(_36.c[4].d[0][3]));
|
||||
_31.Store(424, asuint(_36.c[4].d[1][0]));
|
||||
_31.Store(428, asuint(_36.c[4].d[1][1]));
|
||||
_31.Store(432, asuint(_36.c[4].d[1][2]));
|
||||
_31.Store(436, asuint(_36.c[4].d[1][3]));
|
||||
_31.Store(440, asuint(_36.c[4].baz[0].c));
|
||||
_31.Store(444, asuint(_36.c[4].baz[1].c));
|
||||
}
|
||||
|
||||
[numthreads(1, 1, 1)]
|
||||
void main()
|
||||
{
|
||||
comp_main();
|
||||
}
|
164
reference/shaders-hlsl/comp/access-chain-load-composite.comp
Normal file
164
reference/shaders-hlsl/comp/access-chain-load-composite.comp
Normal file
@ -0,0 +1,164 @@
|
||||
struct Baz
|
||||
{
|
||||
float c;
|
||||
};
|
||||
|
||||
struct Bar
|
||||
{
|
||||
float d[2][4];
|
||||
Baz baz[2];
|
||||
};
|
||||
|
||||
struct Foo
|
||||
{
|
||||
column_major float2x2 a;
|
||||
float2 b;
|
||||
Bar c[5];
|
||||
};
|
||||
|
||||
static const uint3 gl_WorkGroupSize = uint3(1u, 1u, 1u);
|
||||
|
||||
RWByteAddressBuffer _31 : register(u0);
|
||||
|
||||
void comp_main()
|
||||
{
|
||||
Foo _36;
|
||||
_36.a = asfloat(uint2x2(_31.Load(0), _31.Load(8), _31.Load(4), _31.Load(12)));
|
||||
_36.b = asfloat(uint2(_31.Load(16), _31.Load(24)));
|
||||
[unroll]
|
||||
for (int _4ident = 0; _4ident < 5; _4ident++)
|
||||
{
|
||||
[unroll]
|
||||
for (int _5ident = 0; _5ident < 2; _5ident++)
|
||||
{
|
||||
[unroll]
|
||||
for (int _6ident = 0; _6ident < 4; _6ident++)
|
||||
{
|
||||
_36.c[_4ident].d[_5ident][_6ident] = asfloat(_31.Load(_6ident * 4 + _5ident * 16 + _4ident * 40 + 24));
|
||||
}
|
||||
}
|
||||
[unroll]
|
||||
for (int _7ident = 0; _7ident < 2; _7ident++)
|
||||
{
|
||||
_36.c[_4ident].baz[_7ident].c = asfloat(_31.Load(_7ident * 4 + _4ident * 40 + 56));
|
||||
}
|
||||
}
|
||||
Foo f;
|
||||
f.a = _36.a;
|
||||
f.b = _36.b;
|
||||
f.c[0].d[0][0] = _36.c[0].d[0][0];
|
||||
f.c[0].d[0][1] = _36.c[0].d[0][1];
|
||||
f.c[0].d[0][2] = _36.c[0].d[0][2];
|
||||
f.c[0].d[0][3] = _36.c[0].d[0][3];
|
||||
f.c[0].d[1][0] = _36.c[0].d[1][0];
|
||||
f.c[0].d[1][1] = _36.c[0].d[1][1];
|
||||
f.c[0].d[1][2] = _36.c[0].d[1][2];
|
||||
f.c[0].d[1][3] = _36.c[0].d[1][3];
|
||||
f.c[0].baz[0].c = _36.c[0].baz[0].c;
|
||||
f.c[0].baz[1].c = _36.c[0].baz[1].c;
|
||||
f.c[1].d[0][0] = _36.c[1].d[0][0];
|
||||
f.c[1].d[0][1] = _36.c[1].d[0][1];
|
||||
f.c[1].d[0][2] = _36.c[1].d[0][2];
|
||||
f.c[1].d[0][3] = _36.c[1].d[0][3];
|
||||
f.c[1].d[1][0] = _36.c[1].d[1][0];
|
||||
f.c[1].d[1][1] = _36.c[1].d[1][1];
|
||||
f.c[1].d[1][2] = _36.c[1].d[1][2];
|
||||
f.c[1].d[1][3] = _36.c[1].d[1][3];
|
||||
f.c[1].baz[0].c = _36.c[1].baz[0].c;
|
||||
f.c[1].baz[1].c = _36.c[1].baz[1].c;
|
||||
f.c[2].d[0][0] = _36.c[2].d[0][0];
|
||||
f.c[2].d[0][1] = _36.c[2].d[0][1];
|
||||
f.c[2].d[0][2] = _36.c[2].d[0][2];
|
||||
f.c[2].d[0][3] = _36.c[2].d[0][3];
|
||||
f.c[2].d[1][0] = _36.c[2].d[1][0];
|
||||
f.c[2].d[1][1] = _36.c[2].d[1][1];
|
||||
f.c[2].d[1][2] = _36.c[2].d[1][2];
|
||||
f.c[2].d[1][3] = _36.c[2].d[1][3];
|
||||
f.c[2].baz[0].c = _36.c[2].baz[0].c;
|
||||
f.c[2].baz[1].c = _36.c[2].baz[1].c;
|
||||
f.c[3].d[0][0] = _36.c[3].d[0][0];
|
||||
f.c[3].d[0][1] = _36.c[3].d[0][1];
|
||||
f.c[3].d[0][2] = _36.c[3].d[0][2];
|
||||
f.c[3].d[0][3] = _36.c[3].d[0][3];
|
||||
f.c[3].d[1][0] = _36.c[3].d[1][0];
|
||||
f.c[3].d[1][1] = _36.c[3].d[1][1];
|
||||
f.c[3].d[1][2] = _36.c[3].d[1][2];
|
||||
f.c[3].d[1][3] = _36.c[3].d[1][3];
|
||||
f.c[3].baz[0].c = _36.c[3].baz[0].c;
|
||||
f.c[3].baz[1].c = _36.c[3].baz[1].c;
|
||||
f.c[4].d[0][0] = _36.c[4].d[0][0];
|
||||
f.c[4].d[0][1] = _36.c[4].d[0][1];
|
||||
f.c[4].d[0][2] = _36.c[4].d[0][2];
|
||||
f.c[4].d[0][3] = _36.c[4].d[0][3];
|
||||
f.c[4].d[1][0] = _36.c[4].d[1][0];
|
||||
f.c[4].d[1][1] = _36.c[4].d[1][1];
|
||||
f.c[4].d[1][2] = _36.c[4].d[1][2];
|
||||
f.c[4].d[1][3] = _36.c[4].d[1][3];
|
||||
f.c[4].baz[0].c = _36.c[4].baz[0].c;
|
||||
f.c[4].baz[1].c = _36.c[4].baz[1].c;
|
||||
float2 _229 = 1.0f.xx;
|
||||
f.a = float2x2(f.a[0] + _229, f.a[1] + _229);
|
||||
f.b += 2.0f.xx;
|
||||
f.c[3].d[1][1] += 5.0f;
|
||||
_31.Store(224, asuint(f.a[0].x));
|
||||
_31.Store(228, asuint(f.a[1].x));
|
||||
_31.Store(232, asuint(f.a[0].y));
|
||||
_31.Store(236, asuint(f.a[1].y));
|
||||
_31.Store2(240, asuint(f.b));
|
||||
_31.Store(248, asuint(f.c[0].d[0][0]));
|
||||
_31.Store(252, asuint(f.c[0].d[0][1]));
|
||||
_31.Store(256, asuint(f.c[0].d[0][2]));
|
||||
_31.Store(260, asuint(f.c[0].d[0][3]));
|
||||
_31.Store(264, asuint(f.c[0].d[1][0]));
|
||||
_31.Store(268, asuint(f.c[0].d[1][1]));
|
||||
_31.Store(272, asuint(f.c[0].d[1][2]));
|
||||
_31.Store(276, asuint(f.c[0].d[1][3]));
|
||||
_31.Store(280, asuint(f.c[0].baz[0].c));
|
||||
_31.Store(284, asuint(f.c[0].baz[1].c));
|
||||
_31.Store(288, asuint(f.c[1].d[0][0]));
|
||||
_31.Store(292, asuint(f.c[1].d[0][1]));
|
||||
_31.Store(296, asuint(f.c[1].d[0][2]));
|
||||
_31.Store(300, asuint(f.c[1].d[0][3]));
|
||||
_31.Store(304, asuint(f.c[1].d[1][0]));
|
||||
_31.Store(308, asuint(f.c[1].d[1][1]));
|
||||
_31.Store(312, asuint(f.c[1].d[1][2]));
|
||||
_31.Store(316, asuint(f.c[1].d[1][3]));
|
||||
_31.Store(320, asuint(f.c[1].baz[0].c));
|
||||
_31.Store(324, asuint(f.c[1].baz[1].c));
|
||||
_31.Store(328, asuint(f.c[2].d[0][0]));
|
||||
_31.Store(332, asuint(f.c[2].d[0][1]));
|
||||
_31.Store(336, asuint(f.c[2].d[0][2]));
|
||||
_31.Store(340, asuint(f.c[2].d[0][3]));
|
||||
_31.Store(344, asuint(f.c[2].d[1][0]));
|
||||
_31.Store(348, asuint(f.c[2].d[1][1]));
|
||||
_31.Store(352, asuint(f.c[2].d[1][2]));
|
||||
_31.Store(356, asuint(f.c[2].d[1][3]));
|
||||
_31.Store(360, asuint(f.c[2].baz[0].c));
|
||||
_31.Store(364, asuint(f.c[2].baz[1].c));
|
||||
_31.Store(368, asuint(f.c[3].d[0][0]));
|
||||
_31.Store(372, asuint(f.c[3].d[0][1]));
|
||||
_31.Store(376, asuint(f.c[3].d[0][2]));
|
||||
_31.Store(380, asuint(f.c[3].d[0][3]));
|
||||
_31.Store(384, asuint(f.c[3].d[1][0]));
|
||||
_31.Store(388, asuint(f.c[3].d[1][1]));
|
||||
_31.Store(392, asuint(f.c[3].d[1][2]));
|
||||
_31.Store(396, asuint(f.c[3].d[1][3]));
|
||||
_31.Store(400, asuint(f.c[3].baz[0].c));
|
||||
_31.Store(404, asuint(f.c[3].baz[1].c));
|
||||
_31.Store(408, asuint(f.c[4].d[0][0]));
|
||||
_31.Store(412, asuint(f.c[4].d[0][1]));
|
||||
_31.Store(416, asuint(f.c[4].d[0][2]));
|
||||
_31.Store(420, asuint(f.c[4].d[0][3]));
|
||||
_31.Store(424, asuint(f.c[4].d[1][0]));
|
||||
_31.Store(428, asuint(f.c[4].d[1][1]));
|
||||
_31.Store(432, asuint(f.c[4].d[1][2]));
|
||||
_31.Store(436, asuint(f.c[4].d[1][3]));
|
||||
_31.Store(440, asuint(f.c[4].baz[0].c));
|
||||
_31.Store(444, asuint(f.c[4].baz[1].c));
|
||||
}
|
||||
|
||||
[numthreads(1, 1, 1)]
|
||||
void main()
|
||||
{
|
||||
comp_main();
|
||||
}
|
35
shaders-hlsl/comp/access-chain-load-composite.comp
Normal file
35
shaders-hlsl/comp/access-chain-load-composite.comp
Normal file
@ -0,0 +1,35 @@
|
||||
#version 450
|
||||
layout(local_size_x = 1) in;
|
||||
|
||||
struct Baz
|
||||
{
|
||||
float c;
|
||||
};
|
||||
|
||||
struct Bar
|
||||
{
|
||||
float d[2][4];
|
||||
Baz baz[2];
|
||||
};
|
||||
|
||||
struct Foo
|
||||
{
|
||||
mat2 a;
|
||||
vec2 b;
|
||||
Bar c[5];
|
||||
};
|
||||
|
||||
layout(row_major, std430, set = 0, binding = 0) buffer SSBO
|
||||
{
|
||||
Foo foo;
|
||||
Foo foo2;
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
Foo f = foo;
|
||||
f.a += 1.0;
|
||||
f.b += 2.0;
|
||||
f.c[3].d[1][1] += 5.0;
|
||||
foo2 = f;
|
||||
}
|
@ -975,6 +975,7 @@ struct SPIRAccessChain : IVariant
|
||||
|
||||
VariableID loaded_from = 0;
|
||||
uint32_t matrix_stride = 0;
|
||||
uint32_t array_stride = 0;
|
||||
bool row_major_matrix = false;
|
||||
bool immutable = false;
|
||||
|
||||
|
@ -7012,9 +7012,10 @@ string CompilerGLSL::access_chain(uint32_t base, const uint32_t *indices, uint32
|
||||
if (flattened_buffer_blocks.count(base))
|
||||
{
|
||||
uint32_t matrix_stride = 0;
|
||||
uint32_t array_stride = 0;
|
||||
bool need_transpose = false;
|
||||
flattened_access_chain_offset(expression_type(base), indices, count, 0, 16, &need_transpose, &matrix_stride,
|
||||
ptr_chain);
|
||||
&array_stride, ptr_chain);
|
||||
|
||||
if (meta)
|
||||
{
|
||||
@ -7022,7 +7023,7 @@ string CompilerGLSL::access_chain(uint32_t base, const uint32_t *indices, uint32
|
||||
meta->storage_is_packed = false;
|
||||
}
|
||||
|
||||
return flattened_access_chain(base, indices, count, target_type, 0, matrix_stride, need_transpose);
|
||||
return flattened_access_chain(base, indices, count, target_type, 0, matrix_stride, array_stride, need_transpose);
|
||||
}
|
||||
else if (flattened_structs.count(base) && count > 0)
|
||||
{
|
||||
@ -7093,7 +7094,7 @@ void CompilerGLSL::store_flattened_struct(SPIRVariable &var, uint32_t value)
|
||||
|
||||
std::string CompilerGLSL::flattened_access_chain(uint32_t base, const uint32_t *indices, uint32_t count,
|
||||
const SPIRType &target_type, uint32_t offset, uint32_t matrix_stride,
|
||||
bool need_transpose)
|
||||
uint32_t /* array_stride */, bool need_transpose)
|
||||
{
|
||||
if (!target_type.array.empty())
|
||||
SPIRV_CROSS_THROW("Access chains that result in an array can not be flattened");
|
||||
@ -7132,7 +7133,7 @@ std::string CompilerGLSL::flattened_access_chain_struct(uint32_t base, const uin
|
||||
}
|
||||
|
||||
auto tmp = flattened_access_chain(base, indices, count, member_type, offset + member_offset, matrix_stride,
|
||||
need_transpose);
|
||||
0 /* array_stride */, need_transpose);
|
||||
|
||||
// Cannot forward transpositions, so resolve them here.
|
||||
if (need_transpose)
|
||||
@ -7239,24 +7240,17 @@ std::string CompilerGLSL::flattened_access_chain_vector(uint32_t base, const uin
|
||||
|
||||
std::pair<std::string, uint32_t> CompilerGLSL::flattened_access_chain_offset(
|
||||
const SPIRType &basetype, const uint32_t *indices, uint32_t count, uint32_t offset, uint32_t word_stride,
|
||||
bool *need_transpose, uint32_t *out_matrix_stride, bool ptr_chain)
|
||||
bool *need_transpose, uint32_t *out_matrix_stride, uint32_t *out_array_stride, bool ptr_chain)
|
||||
{
|
||||
// Start traversing type hierarchy at the proper non-pointer types.
|
||||
const auto *type = &get_pointee_type(basetype);
|
||||
|
||||
// This holds the type of the current pointer which we are traversing through.
|
||||
// We always start out from a struct type which is the block.
|
||||
// This is primarily used to reflect the array strides and matrix strides later.
|
||||
// For the first access chain index, type_id won't be needed, so just keep it as 0, it will be set
|
||||
// accordingly as members of structs are accessed.
|
||||
assert(type->basetype == SPIRType::Struct);
|
||||
uint32_t type_id = 0;
|
||||
|
||||
std::string expr;
|
||||
|
||||
// Inherit matrix information in case we are access chaining a vector which might have come from a row major layout.
|
||||
bool row_major_matrix_needs_conversion = need_transpose ? *need_transpose : false;
|
||||
uint32_t matrix_stride = out_matrix_stride ? *out_matrix_stride : 0;
|
||||
uint32_t array_stride = out_array_stride ? *out_array_stride : 0;
|
||||
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
{
|
||||
@ -7266,7 +7260,7 @@ std::pair<std::string, uint32_t> CompilerGLSL::flattened_access_chain_offset(
|
||||
if (ptr_chain && i == 0)
|
||||
{
|
||||
// Here, the pointer type will be decorated with an array stride.
|
||||
uint32_t array_stride = get_decoration(basetype.self, DecorationArrayStride);
|
||||
array_stride = get_decoration(basetype.self, DecorationArrayStride);
|
||||
if (!array_stride)
|
||||
SPIRV_CROSS_THROW("SPIR-V does not define ArrayStride for buffer block.");
|
||||
|
||||
@ -7292,16 +7286,10 @@ std::pair<std::string, uint32_t> CompilerGLSL::flattened_access_chain_offset(
|
||||
expr += convert_to_string(array_stride / word_stride);
|
||||
expr += " + ";
|
||||
}
|
||||
// Type ID is unchanged.
|
||||
}
|
||||
// Arrays
|
||||
else if (!type->array.empty())
|
||||
{
|
||||
// Here, the type_id will be a type ID for the array type itself.
|
||||
uint32_t array_stride = get_decoration(type_id, DecorationArrayStride);
|
||||
if (!array_stride)
|
||||
SPIRV_CROSS_THROW("SPIR-V does not define ArrayStride for buffer block.");
|
||||
|
||||
auto *constant = maybe_get<SPIRConstant>(index);
|
||||
if (constant)
|
||||
{
|
||||
@ -7327,9 +7315,9 @@ std::pair<std::string, uint32_t> CompilerGLSL::flattened_access_chain_offset(
|
||||
|
||||
uint32_t parent_type = type->parent_type;
|
||||
type = &get<SPIRType>(parent_type);
|
||||
type_id = parent_type;
|
||||
|
||||
// Type ID now refers to the array type with one less dimension.
|
||||
if (!type->array.empty())
|
||||
array_stride = get_decoration(parent_type, DecorationArrayStride);
|
||||
}
|
||||
// For structs, the index refers to a constant, which indexes into the members.
|
||||
// We also check if this member is a builtin, since we then replace the entire expression with the builtin one.
|
||||
@ -7341,7 +7329,6 @@ std::pair<std::string, uint32_t> CompilerGLSL::flattened_access_chain_offset(
|
||||
SPIRV_CROSS_THROW("Member index is out of bounds!");
|
||||
|
||||
offset += type_struct_member_offset(*type, index);
|
||||
type_id = type->member_types[index];
|
||||
|
||||
auto &struct_type = *type;
|
||||
type = &get<SPIRType>(type->member_types[index]);
|
||||
@ -7354,6 +7341,9 @@ std::pair<std::string, uint32_t> CompilerGLSL::flattened_access_chain_offset(
|
||||
}
|
||||
else
|
||||
row_major_matrix_needs_conversion = false;
|
||||
|
||||
if (!type->array.empty())
|
||||
array_stride = type_struct_member_array_stride(struct_type, index);
|
||||
}
|
||||
// Matrix -> Vector
|
||||
else if (type->columns > 1)
|
||||
@ -7382,9 +7372,7 @@ std::pair<std::string, uint32_t> CompilerGLSL::flattened_access_chain_offset(
|
||||
expr += " + ";
|
||||
}
|
||||
|
||||
uint32_t parent_type = type->parent_type;
|
||||
type = &get<SPIRType>(type->parent_type);
|
||||
type_id = parent_type;
|
||||
}
|
||||
// Vector -> Scalar
|
||||
else if (type->vecsize > 1)
|
||||
@ -7413,9 +7401,7 @@ std::pair<std::string, uint32_t> CompilerGLSL::flattened_access_chain_offset(
|
||||
expr += " + ";
|
||||
}
|
||||
|
||||
uint32_t parent_type = type->parent_type;
|
||||
type = &get<SPIRType>(type->parent_type);
|
||||
type_id = parent_type;
|
||||
}
|
||||
else
|
||||
SPIRV_CROSS_THROW("Cannot subdivide a scalar value!");
|
||||
@ -7425,6 +7411,8 @@ std::pair<std::string, uint32_t> CompilerGLSL::flattened_access_chain_offset(
|
||||
*need_transpose = row_major_matrix_needs_conversion;
|
||||
if (out_matrix_stride)
|
||||
*out_matrix_stride = matrix_stride;
|
||||
if (out_array_stride)
|
||||
*out_array_stride = array_stride;
|
||||
|
||||
return std::make_pair(expr, offset);
|
||||
}
|
||||
|
@ -506,7 +506,7 @@ protected:
|
||||
|
||||
std::string flattened_access_chain(uint32_t base, const uint32_t *indices, uint32_t count,
|
||||
const SPIRType &target_type, uint32_t offset, uint32_t matrix_stride,
|
||||
bool need_transpose);
|
||||
uint32_t array_stride, bool need_transpose);
|
||||
std::string flattened_access_chain_struct(uint32_t base, const uint32_t *indices, uint32_t count,
|
||||
const SPIRType &target_type, uint32_t offset);
|
||||
std::string flattened_access_chain_matrix(uint32_t base, const uint32_t *indices, uint32_t count,
|
||||
@ -519,6 +519,7 @@ protected:
|
||||
uint32_t count, uint32_t offset,
|
||||
uint32_t word_stride, bool *need_transpose = nullptr,
|
||||
uint32_t *matrix_stride = nullptr,
|
||||
uint32_t *array_stride = nullptr,
|
||||
bool ptr_chain = false);
|
||||
|
||||
const char *index_to_swizzle(uint32_t index);
|
||||
|
141
spirv_hlsl.cpp
141
spirv_hlsl.cpp
@ -3401,7 +3401,52 @@ void CompilerHLSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop,
|
||||
}
|
||||
}
|
||||
|
||||
string CompilerHLSL::read_access_chain(const SPIRAccessChain &chain)
|
||||
void CompilerHLSL::read_access_chain_array(const string &lhs, const SPIRAccessChain &chain)
|
||||
{
|
||||
auto &type = get<SPIRType>(chain.basetype);
|
||||
|
||||
// Need to use a reserved identifier here since it might shadow an identifier in the access chain input or other loops.
|
||||
auto ident = get_unique_identifier();
|
||||
|
||||
statement("[unroll]");
|
||||
statement("for (int ", ident, " = 0; ", ident, " < ", to_array_size(type, uint32_t(type.array.size() - 1)), "; ", ident, "++)");
|
||||
begin_scope();
|
||||
auto subchain = chain;
|
||||
subchain.dynamic_index = join(ident, " * ", chain.array_stride, " + ", chain.dynamic_index);
|
||||
subchain.basetype = type.parent_type;
|
||||
if (!get<SPIRType>(subchain.basetype).array.empty())
|
||||
subchain.array_stride = get_decoration(subchain.basetype, DecorationArrayStride);
|
||||
read_access_chain(nullptr, join(lhs, "[", ident, "]"), subchain);
|
||||
end_scope();
|
||||
}
|
||||
|
||||
void CompilerHLSL::read_access_chain_struct(const string &lhs, const SPIRAccessChain &chain)
|
||||
{
|
||||
auto &type = get<SPIRType>(chain.basetype);
|
||||
auto subchain = chain;
|
||||
uint32_t member_count = uint32_t(type.member_types.size());
|
||||
|
||||
for (uint32_t i = 0; i < member_count; i++)
|
||||
{
|
||||
uint32_t offset = type_struct_member_offset(type, i);
|
||||
subchain.static_index = chain.static_index + offset;
|
||||
subchain.basetype = type.member_types[i];
|
||||
|
||||
auto &member_type = get<SPIRType>(subchain.basetype);
|
||||
if (member_type.columns > 1)
|
||||
{
|
||||
subchain.matrix_stride = type_struct_member_matrix_stride(type, i);
|
||||
subchain.row_major_matrix = has_member_decoration(type.self, i, DecorationRowMajor);
|
||||
}
|
||||
|
||||
if (!member_type.array.empty())
|
||||
subchain.array_stride = type_struct_member_array_stride(type, i);
|
||||
|
||||
read_access_chain(nullptr, join(lhs, ".", to_member_name(type, i)), subchain);
|
||||
}
|
||||
}
|
||||
|
||||
void CompilerHLSL::read_access_chain(string *expr, const string &lhs, const SPIRAccessChain &chain)
|
||||
{
|
||||
auto &type = get<SPIRType>(chain.basetype);
|
||||
|
||||
@ -3410,14 +3455,18 @@ string CompilerHLSL::read_access_chain(const SPIRAccessChain &chain)
|
||||
target_type.vecsize = type.vecsize;
|
||||
target_type.columns = type.columns;
|
||||
|
||||
if (type.basetype == SPIRType::Struct)
|
||||
SPIRV_CROSS_THROW("Reading structs from ByteAddressBuffer not yet supported.");
|
||||
|
||||
if (type.width != 32)
|
||||
SPIRV_CROSS_THROW("Reading types other than 32-bit from ByteAddressBuffer not yet supported.");
|
||||
|
||||
if (!type.array.empty())
|
||||
SPIRV_CROSS_THROW("Reading arrays from ByteAddressBuffer not yet supported.");
|
||||
{
|
||||
read_access_chain_array(lhs, chain);
|
||||
return;
|
||||
}
|
||||
else if (type.basetype == SPIRType::Struct)
|
||||
{
|
||||
read_access_chain_struct(lhs, chain);
|
||||
return;
|
||||
}
|
||||
else if (type.width != 32)
|
||||
SPIRV_CROSS_THROW("Reading types other than 32-bit from ByteAddressBuffer not yet supported.");
|
||||
|
||||
string load_expr;
|
||||
|
||||
@ -3525,7 +3574,13 @@ string CompilerHLSL::read_access_chain(const SPIRAccessChain &chain)
|
||||
if (!bitcast_op.empty())
|
||||
load_expr = join(bitcast_op, "(", load_expr, ")");
|
||||
|
||||
return load_expr;
|
||||
if (lhs.empty())
|
||||
{
|
||||
assert(expr);
|
||||
*expr = move(load_expr);
|
||||
}
|
||||
else
|
||||
statement(lhs, " = ", load_expr, ";");
|
||||
}
|
||||
|
||||
void CompilerHLSL::emit_load(const Instruction &instruction)
|
||||
@ -3542,27 +3597,41 @@ void CompilerHLSL::emit_load(const Instruction &instruction)
|
||||
if (has_decoration(ptr, DecorationNonUniformEXT))
|
||||
propagate_nonuniform_qualifier(ptr);
|
||||
|
||||
auto load_expr = read_access_chain(*chain);
|
||||
|
||||
bool forward = should_forward(ptr) && forced_temporaries.find(id) == end(forced_temporaries);
|
||||
|
||||
// If we are forwarding this load,
|
||||
// don't register the read to access chain here, defer that to when we actually use the expression,
|
||||
// using the add_implied_read_expression mechanism.
|
||||
if (!forward)
|
||||
track_expression_read(chain->self);
|
||||
|
||||
// Do not forward complex load sequences like matrices, structs and arrays.
|
||||
auto &type = get<SPIRType>(result_type);
|
||||
if (type.columns > 1 || !type.array.empty() || type.basetype == SPIRType::Struct)
|
||||
forward = false;
|
||||
bool composite_load = !type.array.empty() || type.basetype == SPIRType::Struct;
|
||||
|
||||
auto &e = emit_op(result_type, id, load_expr, forward, true);
|
||||
e.need_transpose = false;
|
||||
register_read(id, ptr, forward);
|
||||
inherit_expression_dependencies(id, ptr);
|
||||
if (forward)
|
||||
add_implied_read_expression(e, chain->self);
|
||||
if (composite_load)
|
||||
{
|
||||
// We cannot make this work in one single expression as we might have nested structures and arrays,
|
||||
// so unroll the load to an uninitialized temporary.
|
||||
emit_uninitialized_temporary_expression(result_type, id);
|
||||
read_access_chain(nullptr, to_expression(id), *chain);
|
||||
track_expression_read(chain->self);
|
||||
}
|
||||
else
|
||||
{
|
||||
string load_expr;
|
||||
read_access_chain(&load_expr, "", *chain);
|
||||
|
||||
bool forward = should_forward(ptr) && forced_temporaries.find(id) == end(forced_temporaries);
|
||||
|
||||
// If we are forwarding this load,
|
||||
// don't register the read to access chain here, defer that to when we actually use the expression,
|
||||
// using the add_implied_read_expression mechanism.
|
||||
if (!forward)
|
||||
track_expression_read(chain->self);
|
||||
|
||||
// Do not forward complex load sequences like matrices, structs and arrays.
|
||||
if (type.columns > 1)
|
||||
forward = false;
|
||||
|
||||
auto &e = emit_op(result_type, id, load_expr, forward, true);
|
||||
e.need_transpose = false;
|
||||
register_read(id, ptr, forward);
|
||||
inherit_expression_dependencies(id, ptr);
|
||||
if (forward)
|
||||
add_implied_read_expression(e, chain->self);
|
||||
}
|
||||
}
|
||||
else
|
||||
CompilerGLSL::emit_instruction(instruction);
|
||||
@ -3723,7 +3792,10 @@ void CompilerHLSL::emit_access_chain(const Instruction &instruction)
|
||||
|
||||
if (need_byte_access_chain)
|
||||
{
|
||||
uint32_t to_plain_buffer_length = static_cast<uint32_t>(type.array.size());
|
||||
// If we have a chain variable, we are already inside the SSBO, and any array type will refer to arrays within a block,
|
||||
// and not array of SSBO.
|
||||
uint32_t to_plain_buffer_length = chain ? 0u : static_cast<uint32_t>(type.array.size());
|
||||
|
||||
auto *backing_variable = maybe_get_backing_variable(ops[2]);
|
||||
|
||||
string base;
|
||||
@ -3745,6 +3817,7 @@ void CompilerHLSL::emit_access_chain(const Instruction &instruction)
|
||||
}
|
||||
|
||||
uint32_t matrix_stride = 0;
|
||||
uint32_t array_stride = 0;
|
||||
bool row_major_matrix = false;
|
||||
|
||||
// Inherit matrix information.
|
||||
@ -3752,15 +3825,18 @@ void CompilerHLSL::emit_access_chain(const Instruction &instruction)
|
||||
{
|
||||
matrix_stride = chain->matrix_stride;
|
||||
row_major_matrix = chain->row_major_matrix;
|
||||
array_stride = chain->array_stride;
|
||||
}
|
||||
|
||||
auto offsets =
|
||||
flattened_access_chain_offset(*basetype, &ops[3 + to_plain_buffer_length],
|
||||
length - 3 - to_plain_buffer_length, 0, 1, &row_major_matrix, &matrix_stride);
|
||||
length - 3 - to_plain_buffer_length, 0, 1,
|
||||
&row_major_matrix, &matrix_stride, &array_stride);
|
||||
|
||||
auto &e = set<SPIRAccessChain>(ops[1], ops[0], type.storage, base, offsets.first, offsets.second);
|
||||
e.row_major_matrix = row_major_matrix;
|
||||
e.matrix_stride = matrix_stride;
|
||||
e.array_stride = array_stride;
|
||||
e.immutable = should_forward(ops[2]);
|
||||
e.loaded_from = backing_variable ? backing_variable->self : ID(0);
|
||||
|
||||
@ -5030,3 +5106,8 @@ void CompilerHLSL::emit_block_hints(const SPIRBlock &block)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
string CompilerHLSL::get_unique_identifier()
|
||||
{
|
||||
return join("_", unique_identifier_count++, "ident");
|
||||
}
|
||||
|
@ -182,7 +182,9 @@ private:
|
||||
void emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id) override;
|
||||
void emit_access_chain(const Instruction &instruction);
|
||||
void emit_load(const Instruction &instruction);
|
||||
std::string read_access_chain(const SPIRAccessChain &chain);
|
||||
void read_access_chain(std::string *expr, const std::string &lhs, const SPIRAccessChain &chain);
|
||||
void read_access_chain_struct(const std::string &lhs, const SPIRAccessChain &chain);
|
||||
void read_access_chain_array(const std::string &lhs, const SPIRAccessChain &chain);
|
||||
void write_access_chain(const SPIRAccessChain &chain, uint32_t value);
|
||||
void emit_store(const Instruction &instruction);
|
||||
void emit_atomic(const uint32_t *ops, uint32_t length, spv::Op op);
|
||||
@ -257,6 +259,9 @@ private:
|
||||
std::vector<RootConstants> root_constants_layout;
|
||||
|
||||
void validate_shader_model();
|
||||
|
||||
std::string get_unique_identifier();
|
||||
uint32_t unique_identifier_count = 0;
|
||||
};
|
||||
} // namespace SPIRV_CROSS_NAMESPACE
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user