MSL: Deal with array copies from and to threadgroup.

This commit is contained in:
Hans-Kristian Arntzen 2019-08-27 13:16:16 +02:00
Родитель 1017a02aad
Коммит 9436cd3036
23 изменённых файлов: 998 добавлений и 168 удалений

Просмотреть файл

@ -19,17 +19,58 @@ struct main0_in
int index [[user(locn0)]];
};
// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
template<typename T, uint N>
void spvArrayCopyFromStack1(thread T (&dst)[N], thread const T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToStack1(thread T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint N>
void spvArrayCopyFromConstant1(thread T (&dst)[N], constant T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToThreadGroup1(threadgroup T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToStack1(thread T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToThreadGroup1(threadgroup T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToStack1(thread T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToThreadGroup1(threadgroup T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
fragment main0_out main0(main0_in in [[stage_in]])
@ -61,7 +102,7 @@ fragment main0_out main0(main0_in in [[stage_in]])
}
int _37 = in.index & 3;
out.FragColor += foobar[_37].z;
spvArrayCopyFromConstant1(baz, _90);
spvArrayCopyFromConstantToStack1(baz, _90);
out.FragColor += baz[_37].z;
return out;
}

Просмотреть файл

@ -33,17 +33,58 @@ struct main0_in
float4 gl_Position [[attribute(1)]];
};
// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
template<typename T, uint N>
void spvArrayCopyFromStack1(thread T (&dst)[N], thread const T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToStack1(thread T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint N>
void spvArrayCopyFromConstant1(thread T (&dst)[N], constant T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToThreadGroup1(threadgroup T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToStack1(thread T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToThreadGroup1(threadgroup T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToStack1(thread T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToThreadGroup1(threadgroup T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
kernel void main0(main0_in in [[stage_in]], uint gl_InvocationID [[thread_index_in_threadgroup]], uint gl_PrimitiveID [[threadgroup_position_in_grid]], device main0_out* spvOut [[buffer(28)]], constant uint* spvIndirectParams [[buffer(29)]], device MTLTriangleTessellationFactorsHalf* spvTessLevel [[buffer(26)]], threadgroup main0_in* gl_in [[threadgroup(0)]])
@ -56,7 +97,7 @@ kernel void main0(main0_in in [[stage_in]], uint gl_InvocationID [[thread_index_
return;
VertexOutput _223[3] = { VertexOutput{ gl_in[0].gl_Position, gl_in[0].VertexOutput_uv }, VertexOutput{ gl_in[1].gl_Position, gl_in[1].VertexOutput_uv }, VertexOutput{ gl_in[2].gl_Position, gl_in[2].VertexOutput_uv } };
VertexOutput param[3];
spvArrayCopyFromStack1(param, _223);
spvArrayCopyFromStackToStack1(param, _223);
gl_out[gl_InvocationID].gl_Position = param[gl_InvocationID].pos;
gl_out[gl_InvocationID]._entryPointOutput.uv = param[gl_InvocationID].uv;
threadgroup_barrier(mem_flags::mem_device);

Просмотреть файл

@ -29,24 +29,65 @@ constant uint3 gl_WorkGroupSize [[maybe_unused]] = uint3(2u, 1u, 1u);
constant Data _25[2] = { Data{ 1.0, 2.0 }, Data{ 3.0, 4.0 } };
// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
template<typename T, uint N>
void spvArrayCopyFromStack1(thread T (&dst)[N], thread const T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToStack1(thread T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint N>
void spvArrayCopyFromConstant1(thread T (&dst)[N], constant T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToThreadGroup1(threadgroup T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToStack1(thread T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToThreadGroup1(threadgroup T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToStack1(thread T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToThreadGroup1(threadgroup T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
kernel void main0(device SSBO& _53 [[buffer(0)]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]])
{
Data _31[2] = { Data{ X, 2.0 }, Data{ 3.0, 5.0 } };
Data data2[2];
spvArrayCopyFromStack1(data2, _31);
spvArrayCopyFromStackToStack1(data2, _31);
_53.outdata[gl_WorkGroupID.x].a = _25[gl_LocalInvocationID.x].a + data2[gl_LocalInvocationID.x].a;
_53.outdata[gl_WorkGroupID.x].b = _25[gl_LocalInvocationID.x].b + data2[gl_LocalInvocationID.x].b;
}

Просмотреть файл

@ -15,24 +15,65 @@ struct SSBO1
float4 bs[1];
};
// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
template<typename T, uint N>
void spvArrayCopyFromStack1(thread T (&dst)[N], thread const T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToStack1(thread T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint N>
void spvArrayCopyFromConstant1(thread T (&dst)[N], constant T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToThreadGroup1(threadgroup T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToStack1(thread T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToThreadGroup1(threadgroup T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToStack1(thread T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToThreadGroup1(threadgroup T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
kernel void main0(device SSBO0& _16 [[buffer(0)]], device SSBO1& _32 [[buffer(1)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]], uint gl_LocalInvocationIndex [[thread_index_in_threadgroup]])
{
float4 _37[2] = { _16.as[gl_GlobalInvocationID.x], _32.bs[gl_GlobalInvocationID.x] };
float4 values[2];
spvArrayCopyFromStack1(values, _37);
spvArrayCopyFromStackToStack1(values, _37);
_16.as[0] = values[gl_LocalInvocationIndex];
_32.bs[1] = float4(40.0);
}

Просмотреть файл

@ -19,17 +19,58 @@ struct main0_in
int index [[user(locn0)]];
};
// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
template<typename T, uint N>
void spvArrayCopyFromStack1(thread T (&dst)[N], thread const T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToStack1(thread T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint N>
void spvArrayCopyFromConstant1(thread T (&dst)[N], constant T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToThreadGroup1(threadgroup T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToStack1(thread T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToThreadGroup1(threadgroup T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToStack1(thread T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToThreadGroup1(threadgroup T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
fragment main0_out main0(main0_in in [[stage_in]])

Просмотреть файл

@ -0,0 +1,79 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
constant uint3 gl_WorkGroupSize [[maybe_unused]] = uint3(8u, 1u, 1u);
template<typename T, uint A>
void spvArrayCopyFromConstantToStack1(thread T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromConstantToThreadGroup1(threadgroup T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToStack1(thread T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToThreadGroup1(threadgroup T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToStack1(thread T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToThreadGroup1(threadgroup T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
kernel void main0(uint gl_LocalInvocationIndex [[thread_index_in_threadgroup]])
{
threadgroup float shared_group[8][8];
threadgroup float shared_group_alt[8][8];
float blob[8];
for (int i = 0; i < 8; i++)
{
blob[i] = float(i);
}
spvArrayCopyFromStackToThreadGroup1(shared_group[gl_LocalInvocationIndex], blob);
threadgroup_barrier(mem_flags::mem_threadgroup);
float copied_blob[8];
spvArrayCopyFromThreadGroupToStack1(copied_blob, shared_group[gl_LocalInvocationIndex ^ 1u]);
spvArrayCopyFromThreadGroupToThreadGroup1(shared_group_alt[gl_LocalInvocationIndex], shared_group[gl_LocalInvocationIndex]);
}

Просмотреть файл

@ -18,25 +18,66 @@ struct main0_in
int Index2 [[attribute(1)]];
};
// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
template<typename T, uint N>
void spvArrayCopyFromStack1(thread T (&dst)[N], thread const T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToStack1(thread T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint N>
void spvArrayCopyFromConstant1(thread T (&dst)[N], constant T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToThreadGroup1(threadgroup T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToStack1(thread T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToThreadGroup1(threadgroup T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToStack1(thread T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToThreadGroup1(threadgroup T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
float4 consume_constant_arrays2(thread const float4 (&positions)[4], thread const float4 (&positions2)[4], thread int& Index1, thread int& Index2)
{
float4 indexable[4];
spvArrayCopyFromStack1(indexable, positions);
spvArrayCopyFromStackToStack1(indexable, positions);
float4 indexable_1[4];
spvArrayCopyFromStack1(indexable_1, positions2);
spvArrayCopyFromStackToStack1(indexable_1, positions2);
return indexable[Index1] + indexable_1[Index2];
}

Просмотреть файл

@ -19,17 +19,58 @@ struct main0_in
int index [[user(locn0)]];
};
// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
template<typename T, uint N>
void spvArrayCopyFromStack1(thread T (&dst)[N], thread const T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToStack1(thread T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint N>
void spvArrayCopyFromConstant1(thread T (&dst)[N], constant T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToThreadGroup1(threadgroup T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToStack1(thread T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToThreadGroup1(threadgroup T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToStack1(thread T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToThreadGroup1(threadgroup T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
fragment main0_out main0(main0_in in [[stage_in]])
@ -59,7 +100,7 @@ fragment main0_out main0(main0_in in [[stage_in]])
foobar[1].z = 20.0;
}
out.FragColor += foobar[in.index & 3].z;
spvArrayCopyFromConstant1(baz, _90);
spvArrayCopyFromConstantToStack1(baz, _90);
out.FragColor += baz[in.index & 3].z;
return out;
}

Просмотреть файл

@ -24,17 +24,58 @@ Tx mod(Tx x, Ty y)
return x - y * floor(x / y);
}
// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
template<typename T, uint N>
void spvArrayCopyFromStack1(thread T (&dst)[N], thread const T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToStack1(thread T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint N>
void spvArrayCopyFromConstant1(thread T (&dst)[N], constant T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToThreadGroup1(threadgroup T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToStack1(thread T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToThreadGroup1(threadgroup T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToStack1(thread T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToThreadGroup1(threadgroup T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
fragment main0_out main0(float4 gl_FragCoord [[position]])

Просмотреть файл

@ -45,17 +45,58 @@ struct main0_in
float4 gl_Position [[attribute(1)]];
};
// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
template<typename T, uint N>
void spvArrayCopyFromStack1(thread T (&dst)[N], thread const T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToStack1(thread T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint N>
void spvArrayCopyFromConstant1(thread T (&dst)[N], constant T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToThreadGroup1(threadgroup T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToStack1(thread T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToThreadGroup1(threadgroup T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToStack1(thread T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToThreadGroup1(threadgroup T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
HSOut _hs_main(thread const VertexOutput (&p)[3], thread const uint& i)
@ -93,7 +134,7 @@ kernel void main0(main0_in in [[stage_in]], uint gl_InvocationID [[thread_index_
p[2].uv = gl_in[2].VertexOutput_uv;
uint i = gl_InvocationID;
VertexOutput param[3];
spvArrayCopyFromStack1(param, p);
spvArrayCopyFromStackToStack1(param, p);
uint param_1 = i;
HSOut flattenTemp = _hs_main(param, param_1);
gl_out[gl_InvocationID].gl_Position = flattenTemp.pos;
@ -102,7 +143,7 @@ kernel void main0(main0_in in [[stage_in]], uint gl_InvocationID [[thread_index_
if (int(gl_InvocationID) == 0)
{
VertexOutput param_2[3];
spvArrayCopyFromStack1(param_2, p);
spvArrayCopyFromStackToStack1(param_2, p);
HSConstantOut _patchConstantResult = PatchHS(param_2);
spvTessLevel[gl_PrimitiveID].edgeTessellationFactor[0] = half(_patchConstantResult.EdgeTess[0]);
spvTessLevel[gl_PrimitiveID].edgeTessellationFactor[1] = half(_patchConstantResult.EdgeTess[1]);

Просмотреть файл

@ -29,17 +29,58 @@ constant uint3 gl_WorkGroupSize [[maybe_unused]] = uint3(2u, 1u, 1u);
constant Data _25[2] = { Data{ 1.0, 2.0 }, Data{ 3.0, 4.0 } };
// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
template<typename T, uint N>
void spvArrayCopyFromStack1(thread T (&dst)[N], thread const T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToStack1(thread T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint N>
void spvArrayCopyFromConstant1(thread T (&dst)[N], constant T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToThreadGroup1(threadgroup T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToStack1(thread T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToThreadGroup1(threadgroup T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToStack1(thread T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToThreadGroup1(threadgroup T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
Data combine(thread const Data& a, thread const Data& b)
@ -52,7 +93,7 @@ kernel void main0(device SSBO& _53 [[buffer(0)]], uint3 gl_WorkGroupID [[threadg
Data data[2] = { Data{ 1.0, 2.0 }, Data{ 3.0, 4.0 } };
Data _31[2] = { Data{ X, 2.0 }, Data{ 3.0, 5.0 } };
Data data2[2];
spvArrayCopyFromStack1(data2, _31);
spvArrayCopyFromStackToStack1(data2, _31);
Data param = data[gl_LocalInvocationID.x];
Data param_1 = data2[gl_LocalInvocationID.x];
Data _73 = combine(param, param_1);

Просмотреть файл

@ -23,24 +23,65 @@ struct Composite
constant float4 _43[2] = { float4(20.0), float4(40.0) };
// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
template<typename T, uint N>
void spvArrayCopyFromStack1(thread T (&dst)[N], thread const T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToStack1(thread T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint N>
void spvArrayCopyFromConstant1(thread T (&dst)[N], constant T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToThreadGroup1(threadgroup T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToStack1(thread T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToThreadGroup1(threadgroup T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToStack1(thread T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToThreadGroup1(threadgroup T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
kernel void main0(device SSBO0& _16 [[buffer(0)]], device SSBO1& _32 [[buffer(1)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]], uint gl_LocalInvocationIndex [[thread_index_in_threadgroup]])
{
float4 _37[2] = { _16.as[gl_GlobalInvocationID.x], _32.bs[gl_GlobalInvocationID.x] };
float4 values[2];
spvArrayCopyFromStack1(values, _37);
spvArrayCopyFromStackToStack1(values, _37);
Composite c = Composite{ values[0], _43[1] };
_16.as[0] = values[gl_LocalInvocationIndex];
_32.bs[1] = c.b;

Просмотреть файл

@ -17,59 +17,172 @@ constant float _19[2] = { 3.0, 4.0 };
constant float _20[2][2] = { { 1.0, 2.0 }, { 3.0, 4.0 } };
constant float _21[2][2][2] = { { { 1.0, 2.0 }, { 3.0, 4.0 } }, { { 1.0, 2.0 }, { 3.0, 4.0 } } };
// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
template<typename T, uint N>
void spvArrayCopyFromStack1(thread T (&dst)[N], thread const T (&src)[N])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
}
template<typename T, uint N>
void spvArrayCopyFromConstant1(thread T (&dst)[N], constant T (&src)[N])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
}
template<typename T, uint A, uint B>
void spvArrayCopyFromStack2(thread T (&dst)[A][B], thread const T (&src)[A][B])
template<typename T, uint A>
void spvArrayCopyFromConstantToStack1(thread T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
spvArrayCopyFromStack1(dst[i], src[i]);
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromConstantToThreadGroup1(threadgroup T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToStack1(thread T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToThreadGroup1(threadgroup T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToStack1(thread T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToThreadGroup1(threadgroup T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A, uint B>
void spvArrayCopyFromConstant2(thread T (&dst)[A][B], constant T (&src)[A][B])
void spvArrayCopyFromConstantToStack2(thread T (&dst)[A][B], constant T (&src)[A][B])
{
for (uint i = 0; i < A; i++)
{
spvArrayCopyFromConstant1(dst[i], src[i]);
spvArrayCopyFromConstantToStack1(dst[i], src[i]);
}
}
template<typename T, uint A, uint B>
void spvArrayCopyFromConstantToThreadGroup2(threadgroup T (&dst)[A][B], constant T (&src)[A][B])
{
for (uint i = 0; i < A; i++)
{
spvArrayCopyFromConstantToThreadGroup1(dst[i], src[i]);
}
}
template<typename T, uint A, uint B>
void spvArrayCopyFromStackToStack2(thread T (&dst)[A][B], thread const T (&src)[A][B])
{
for (uint i = 0; i < A; i++)
{
spvArrayCopyFromStackToStack1(dst[i], src[i]);
}
}
template<typename T, uint A, uint B>
void spvArrayCopyFromStackToThreadGroup2(threadgroup T (&dst)[A][B], thread const T (&src)[A][B])
{
for (uint i = 0; i < A; i++)
{
spvArrayCopyFromStackToThreadGroup1(dst[i], src[i]);
}
}
template<typename T, uint A, uint B>
void spvArrayCopyFromThreadGroupToStack2(thread T (&dst)[A][B], threadgroup const T (&src)[A][B])
{
for (uint i = 0; i < A; i++)
{
spvArrayCopyFromThreadGroupToStack1(dst[i], src[i]);
}
}
template<typename T, uint A, uint B>
void spvArrayCopyFromThreadGroupToThreadGroup2(threadgroup T (&dst)[A][B], threadgroup const T (&src)[A][B])
{
for (uint i = 0; i < A; i++)
{
spvArrayCopyFromThreadGroupToThreadGroup1(dst[i], src[i]);
}
}
template<typename T, uint A, uint B, uint C>
void spvArrayCopyFromStack3(thread T (&dst)[A][B][C], thread const T (&src)[A][B][C])
void spvArrayCopyFromConstantToStack3(thread T (&dst)[A][B][C], constant T (&src)[A][B][C])
{
for (uint i = 0; i < A; i++)
{
spvArrayCopyFromStack2(dst[i], src[i]);
spvArrayCopyFromConstantToStack2(dst[i], src[i]);
}
}
template<typename T, uint A, uint B, uint C>
void spvArrayCopyFromConstant3(thread T (&dst)[A][B][C], constant T (&src)[A][B][C])
void spvArrayCopyFromConstantToThreadGroup3(threadgroup T (&dst)[A][B][C], constant T (&src)[A][B][C])
{
for (uint i = 0; i < A; i++)
{
spvArrayCopyFromConstant2(dst[i], src[i]);
spvArrayCopyFromConstantToThreadGroup2(dst[i], src[i]);
}
}
template<typename T, uint A, uint B, uint C>
void spvArrayCopyFromStackToStack3(thread T (&dst)[A][B][C], thread const T (&src)[A][B][C])
{
for (uint i = 0; i < A; i++)
{
spvArrayCopyFromStackToStack2(dst[i], src[i]);
}
}
template<typename T, uint A, uint B, uint C>
void spvArrayCopyFromStackToThreadGroup3(threadgroup T (&dst)[A][B][C], thread const T (&src)[A][B][C])
{
for (uint i = 0; i < A; i++)
{
spvArrayCopyFromStackToThreadGroup2(dst[i], src[i]);
}
}
template<typename T, uint A, uint B, uint C>
void spvArrayCopyFromThreadGroupToStack3(thread T (&dst)[A][B][C], threadgroup const T (&src)[A][B][C])
{
for (uint i = 0; i < A; i++)
{
spvArrayCopyFromThreadGroupToStack2(dst[i], src[i]);
}
}
template<typename T, uint A, uint B, uint C>
void spvArrayCopyFromThreadGroupToThreadGroup3(threadgroup T (&dst)[A][B][C], threadgroup const T (&src)[A][B][C])
{
for (uint i = 0; i < A; i++)
{
spvArrayCopyFromThreadGroupToThreadGroup2(dst[i], src[i]);
}
}
kernel void main0(device BUF& o [[buffer(0)]])
{
float c[2][2][2];
spvArrayCopyFromConstant3(c, _21);
spvArrayCopyFromConstantToStack3(c, _21);
o.a = int(c[1][1][1]);
float _43[2] = { o.b, o.c };
float _48[2] = { o.b, o.b };
@ -79,9 +192,9 @@ kernel void main0(device BUF& o [[buffer(0)]])
float _60[2][2] = { { _54[0], _54[1] }, { _59[0], _59[1] } };
float _61[2][2][2] = { { { _49[0][0], _49[0][1] }, { _49[1][0], _49[1][1] } }, { { _60[0][0], _60[0][1] }, { _60[1][0], _60[1][1] } } };
float d[2][2][2];
spvArrayCopyFromStack3(d, _61);
spvArrayCopyFromStackToStack3(d, _61);
float e[2][2][2];
spvArrayCopyFromStack3(e, d);
spvArrayCopyFromStackToStack3(e, d);
o.b = e[1][0][1];
}

Просмотреть файл

@ -24,17 +24,58 @@ struct main0_in
int line [[user(locn0)]];
};
// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
template<typename T, uint N>
void spvArrayCopyFromStack1(thread T (&dst)[N], thread const T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToStack1(thread T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint N>
void spvArrayCopyFromConstant1(thread T (&dst)[N], constant T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToThreadGroup1(threadgroup T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToStack1(thread T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToThreadGroup1(threadgroup T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToStack1(thread T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToThreadGroup1(threadgroup T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
fragment main0_out main0(main0_in in [[stage_in]])

Просмотреть файл

@ -19,17 +19,58 @@ struct main0_in
int index [[user(locn0)]];
};
// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
template<typename T, uint N>
void spvArrayCopyFromStack1(thread T (&dst)[N], thread const T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToStack1(thread T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint N>
void spvArrayCopyFromConstant1(thread T (&dst)[N], constant T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToThreadGroup1(threadgroup T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToStack1(thread T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToThreadGroup1(threadgroup T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToStack1(thread T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToThreadGroup1(threadgroup T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
fragment main0_out main0(main0_in in [[stage_in]])
@ -59,7 +100,7 @@ fragment main0_out main0(main0_in in [[stage_in]])
}
out.FragColor += foobar[in.index & 3].z;
float4 baz[4] = { float4(0.0), float4(1.0), float4(8.0), float4(5.0) };
spvArrayCopyFromConstant1(baz, _104);
spvArrayCopyFromConstantToStack1(baz, _104);
out.FragColor += baz[in.index & 3].z;
return out;
}

Просмотреть файл

@ -18,22 +18,63 @@ struct main0_in
float4 vInput1 [[attribute(1)]];
};
// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
template<typename T, uint N>
void spvArrayCopyFromStack1(thread T (&dst)[N], thread const T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToStack1(thread T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint N>
void spvArrayCopyFromConstant1(thread T (&dst)[N], constant T (&src)[N])
template<typename T, uint A>
void spvArrayCopyFromConstantToThreadGroup1(threadgroup T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < N; dst[i] = src[i], i++);
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToStack1(thread T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromStackToThreadGroup1(threadgroup T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToStack1(thread T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
void spvArrayCopyFromThreadGroupToThreadGroup1(threadgroup T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
void test(thread float4 (&SPIRV_Cross_return_value)[2])
{
spvArrayCopyFromConstant1(SPIRV_Cross_return_value, _20);
spvArrayCopyFromConstantToStack1(SPIRV_Cross_return_value, _20);
}
void test2(thread float4 (&SPIRV_Cross_return_value)[2], thread float4& vInput0, thread float4& vInput1)
@ -41,7 +82,7 @@ void test2(thread float4 (&SPIRV_Cross_return_value)[2], thread float4& vInput0,
float4 foobar[2];
foobar[0] = vInput0;
foobar[1] = vInput1;
spvArrayCopyFromStack1(SPIRV_Cross_return_value, foobar);
spvArrayCopyFromStackToStack1(SPIRV_Cross_return_value, foobar);
}
vertex main0_out main0(main0_in in [[stage_in]])

Просмотреть файл

@ -0,0 +1,18 @@
#version 450
layout(local_size_x = 8) in;
shared float shared_group[8][8];
shared float shared_group_alt[8][8];
void main()
{
float blob[8];
for (int i = 0; i < 8; i++)
blob[i] = float(i);
shared_group[gl_LocalInvocationIndex] = blob;
barrier();
float copied_blob[8] = shared_group[gl_LocalInvocationIndex ^ 1u];
shared_group_alt[gl_LocalInvocationIndex] = shared_group[gl_LocalInvocationIndex];
}

Просмотреть файл

@ -265,6 +265,15 @@ SPIRVariable *Compiler::maybe_get_backing_variable(uint32_t chain)
return var;
}
StorageClass Compiler::get_backing_variable_storage(uint32_t ptr)
{
auto *var = maybe_get_backing_variable(ptr);
if (var)
return var->storage;
else
return expression_type(ptr).storage;
}
void Compiler::register_read(uint32_t expr, uint32_t chain, bool forwarded)
{
auto &e = get<SPIRExpression>(expr);

Просмотреть файл

@ -605,6 +605,7 @@ protected:
bool expression_is_lvalue(uint32_t id) const;
bool variable_storage_is_aliased(const SPIRVariable &var);
SPIRVariable *maybe_get_backing_variable(uint32_t chain);
spv::StorageClass get_backing_variable_storage(uint32_t ptr);
void register_read(uint32_t expr, uint32_t chain, bool forwarded);
void register_write(uint32_t chain);

Просмотреть файл

@ -7888,7 +7888,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
// it is an array, and our backend does not support arrays as value types.
// Emit the temporary, and copy it explicitly.
e = &emit_uninitialized_temporary_expression(result_type, id);
emit_array_copy(to_expression(id), ptr);
emit_array_copy(to_expression(id), ptr, StorageClassFunction, get_backing_variable_storage(ptr));
}
else
e = &emit_op(result_type, id, expr, forward, !usage_tracking);
@ -12232,7 +12232,10 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
// If we cannot return arrays, we will have a special out argument we can write to instead.
// The backend is responsible for setting this up, and redirection the return values as appropriate.
if (ir.ids[block.return_value].get_type() != TypeUndef)
emit_array_copy("SPIRV_Cross_return_value", block.return_value);
{
emit_array_copy("SPIRV_Cross_return_value", block.return_value,
StorageClassFunction, get_backing_variable_storage(block.return_value));
}
if (!cfg.node_terminates_control_flow_in_sub_graph(current_function->entry_block, block.self) ||
block.loop_dominator != SPIRBlock::NoDominator)
@ -12427,7 +12430,7 @@ uint32_t CompilerGLSL::mask_relevant_memory_semantics(uint32_t semantics)
MemorySemanticsCrossWorkgroupMemoryMask | MemorySemanticsSubgroupMemoryMask);
}
void CompilerGLSL::emit_array_copy(const string &lhs, uint32_t rhs_id)
void CompilerGLSL::emit_array_copy(const string &lhs, uint32_t rhs_id, StorageClass, StorageClass)
{
statement(lhs, " = ", to_expression(rhs_id), ";");
}

Просмотреть файл

@ -546,7 +546,8 @@ protected:
std::string layout_for_variable(const SPIRVariable &variable);
std::string to_combined_image_sampler(uint32_t image_id, uint32_t samp_id);
virtual bool skip_argument(uint32_t id) const;
virtual void emit_array_copy(const std::string &lhs, uint32_t rhs_id);
virtual void emit_array_copy(const std::string &lhs, uint32_t rhs_id,
spv::StorageClass lhs_storage, spv::StorageClass rhs_storage);
virtual void emit_block_hints(const SPIRBlock &block);
virtual std::string to_initializer_expression(const SPIRVariable &var);

Просмотреть файл

@ -3185,40 +3185,41 @@ void CompilerMSL::emit_custom_functions()
break;
case SPVFuncImplArrayCopy:
statement("// Implementation of an array copy function to cover GLSL's ability to copy an array via "
"assignment.");
statement("template<typename T, uint N>");
statement("void spvArrayCopyFromStack1(thread T (&dst)[N], thread const T (&src)[N])");
begin_scope();
statement("for (uint i = 0; i < N; dst[i] = src[i], i++);");
end_scope();
statement("");
statement("template<typename T, uint N>");
statement("void spvArrayCopyFromConstant1(thread T (&dst)[N], constant T (&src)[N])");
begin_scope();
statement("for (uint i = 0; i < N; dst[i] = src[i], i++);");
end_scope();
statement("");
break;
case SPVFuncImplArrayOfArrayCopy2Dim:
case SPVFuncImplArrayOfArrayCopy3Dim:
case SPVFuncImplArrayOfArrayCopy4Dim:
case SPVFuncImplArrayOfArrayCopy5Dim:
case SPVFuncImplArrayOfArrayCopy6Dim:
{
// Unfortunately we cannot template on the address space, so combinatorial explosion it is.
static const char *function_name_tags[] = {
"FromStack",
"FromConstant",
"FromConstantToStack",
"FromConstantToThreadGroup",
"FromStackToStack",
"FromStackToThreadGroup",
"FromThreadGroupToStack",
"FromThreadGroupToThreadGroup",
};
static const char *src_address_space[] = {
"thread const",
"constant",
"constant",
"thread const",
"thread const",
"threadgroup const",
"threadgroup const",
};
for (uint32_t variant = 0; variant < 2; variant++)
static const char *dst_address_space[] = {
"thread",
"threadgroup",
"thread",
"threadgroup",
"thread",
"threadgroup",
};
for (uint32_t variant = 0; variant < 6; variant++)
{
uint32_t dimensions = spv_func - SPVFuncImplArrayCopyMultidimBase;
string tmp = "template<typename T";
@ -3238,17 +3239,24 @@ void CompilerMSL::emit_custom_functions()
array_arg += "]";
}
statement("void spvArrayCopy", function_name_tags[variant], dimensions, "(thread T (&dst)", array_arg,
statement("void spvArrayCopy", function_name_tags[variant], dimensions, "(", dst_address_space[variant],
" T (&dst)",
array_arg,
", ", src_address_space[variant], " T (&src)", array_arg, ")");
begin_scope();
statement("for (uint i = 0; i < A; i++)");
begin_scope();
statement("spvArrayCopy", function_name_tags[variant], dimensions - 1, "(dst[i], src[i]);");
if (dimensions == 1)
statement("dst[i] = src[i];");
else
statement("spvArrayCopy", function_name_tags[variant], dimensions - 1, "(dst[i], src[i]);");
end_scope();
end_scope();
statement("");
}
break;
}
@ -4890,7 +4898,8 @@ void CompilerMSL::emit_barrier(uint32_t id_exe_scope, uint32_t id_mem_scope, uin
flush_all_active_variables();
}
void CompilerMSL::emit_array_copy(const string &lhs, uint32_t rhs_id)
void CompilerMSL::emit_array_copy(const string &lhs, uint32_t rhs_id,
StorageClass lhs_storage, StorageClass rhs_storage)
{
// Assignment from an array initializer is fine.
auto &type = expression_type(rhs_id);
@ -4932,7 +4941,29 @@ void CompilerMSL::emit_array_copy(const string &lhs, uint32_t rhs_id)
force_recompile();
}
const char *tag = is_constant ? "FromConstant" : "FromStack";
bool lhs_thread = lhs_storage == StorageClassFunction ||
lhs_storage == StorageClassGeneric ||
lhs_storage == StorageClassPrivate;
bool rhs_thread = rhs_storage == StorageClassFunction ||
rhs_storage == StorageClassGeneric ||
rhs_storage == StorageClassPrivate;
const char *tag = nullptr;
if (lhs_thread && is_constant)
tag = "FromConstantToStack";
else if (lhs_storage == StorageClassWorkgroup && is_constant)
tag = "FromConstantToThreadGroup";
else if (lhs_thread && rhs_thread)
tag = "FromStackToStack";
else if (lhs_storage == StorageClassWorkgroup && rhs_thread)
tag = "FromStackToThreadGroup";
else if (lhs_thread && rhs_storage == StorageClassWorkgroup)
tag = "FromThreadGroupToStack";
else if (lhs_storage == StorageClassWorkgroup && rhs_storage == StorageClassWorkgroup)
tag = "FromThreadGroupToThreadGroup";
else
SPIRV_CROSS_THROW("Unknown storage class used for copying arrays.");
statement("spvArrayCopy", tag, type.array.size(), "(", lhs, ", ", to_expression(rhs_id), ");");
}
@ -4969,7 +5000,7 @@ bool CompilerMSL::maybe_emit_array_assignment(uint32_t id_lhs, uint32_t id_rhs)
if (p_v_lhs)
flush_variable_declaration(p_v_lhs->self);
emit_array_copy(to_expression(id_lhs), id_rhs);
emit_array_copy(to_expression(id_lhs), id_rhs, get_backing_variable_storage(id_lhs), get_backing_variable_storage(id_rhs));
register_write(id_lhs);
return true;

Просмотреть файл

@ -555,7 +555,8 @@ protected:
void add_pragma_line(const std::string &line);
void add_typedef_line(const std::string &line);
void emit_barrier(uint32_t id_exe_scope, uint32_t id_mem_scope, uint32_t id_mem_sem);
void emit_array_copy(const std::string &lhs, uint32_t rhs_id) override;
void emit_array_copy(const std::string &lhs, uint32_t rhs_id,
spv::StorageClass lhs_storage, spv::StorageClass rhs_storage) override;
void build_implicit_builtins();
uint32_t build_constant_uint_array_pointer();
void emit_entry_point_declarations() override;