blob: 93a76ead1c2839f6f0c0cc2028ce715b94b2070a [file] [log] [blame]
#include <metal_stdlib>
using namespace metal;
template<typename T, int N, int M>
inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) {
return lhs * vec<T, N>(rhs);
}
template<typename T, int N, int M>
inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) {
return vec<T, M>(lhs) * rhs;
}
struct Camera {
/* 0x0000 */ float4x4 projection;
/* 0x0040 */ float4x4 inverseProjection;
/* 0x0080 */ float4x4 view;
/* 0x00c0 */ packed_float3 position;
/* 0x00cc */ float time;
/* 0x00d0 */ float2 outputSize;
/* 0x00d8 */ float zNear;
/* 0x00dc */ float zFar;
};
struct ClusterBounds {
/* 0x0000 */ packed_float3 minAABB;
/* 0x000c */ int8_t tint_pad[4];
/* 0x0010 */ packed_float3 maxAABB;
/* 0x001c */ int8_t tint_pad_1[4];
};
struct tint_array_wrapper {
/* 0x0000 */ ClusterBounds arr[27648];
};
struct Clusters {
/* 0x0000 */ tint_array_wrapper bounds;
};
struct ClusterLights {
/* 0x0000 */ uint offset;
/* 0x0004 */ uint count;
};
struct tint_array_wrapper_1 {
/* 0x0000 */ ClusterLights arr[27648];
};
struct tint_array_wrapper_2 {
/* 0x0000 */ uint arr[1769472];
};
struct ClusterLightGroup {
/* 0x0000 */ atomic_uint offset;
/* 0x0004 */ tint_array_wrapper_1 lights;
/* 0x36004 */ tint_array_wrapper_2 indices;
};
struct Light {
/* 0x0000 */ packed_float3 position;
/* 0x000c */ float range;
/* 0x0010 */ packed_float3 color;
/* 0x001c */ float intensity;
};
struct GlobalLights {
/* 0x0000 */ packed_float3 ambient;
/* 0x000c */ int8_t tint_pad_2[4];
/* 0x0010 */ packed_float3 dirColor;
/* 0x001c */ float dirIntensity;
/* 0x0020 */ packed_float3 dirDirection;
/* 0x002c */ uint lightCount;
/* 0x0030 */ Light lights[1];
};
struct tint_array_wrapper_3 {
uint arr[256];
};
constant uint3 tileCount = uint3(32u, 18u, 48u);
float linearDepth(float depthSample, const constant Camera* const tint_symbol) {
return (((*(tint_symbol)).zFar * (*(tint_symbol)).zNear) / fma(depthSample, ((*(tint_symbol)).zNear - (*(tint_symbol)).zFar), (*(tint_symbol)).zFar));
}
uint3 getTile(float4 fragCoord, const constant Camera* const tint_symbol_1) {
float const sliceScale = (float(tileCount[2]) / log2(((*(tint_symbol_1)).zFar / (*(tint_symbol_1)).zNear)));
float const sliceBias = -(((float(tileCount[2]) * log2((*(tint_symbol_1)).zNear)) / log2(((*(tint_symbol_1)).zFar / (*(tint_symbol_1)).zNear))));
uint const zTile = uint(fmax(((log2(linearDepth(fragCoord[2], tint_symbol_1)) * sliceScale) + sliceBias), 0.0f));
return uint3(uint((fragCoord[0] / ((*(tint_symbol_1)).outputSize[0] / float(tileCount[0])))), uint((fragCoord[1] / ((*(tint_symbol_1)).outputSize[1] / float(tileCount[1])))), zTile);
}
uint getClusterIndex(float4 fragCoord, const constant Camera* const tint_symbol_2) {
uint3 const tile = getTile(fragCoord, tint_symbol_2);
return ((tile[0] + (tile[1] * tileCount[0])) + ((tile[2] * tileCount[0]) * tileCount[1]));
}
float sqDistPointAABB(float3 point, float3 minAABB, float3 maxAABB) {
float sqDist = 0.0f;
for(int i = 0; (i < 3); i = as_type<int>((as_type<uint>(i) + as_type<uint>(1)))) {
float const v = point[i];
if ((v < minAABB[i])) {
sqDist = (sqDist + ((minAABB[i] - v) * (minAABB[i] - v)));
}
if ((v > maxAABB[i])) {
sqDist = (sqDist + ((v - maxAABB[i]) * (v - maxAABB[i])));
}
}
return sqDist;
}
void computeMain_inner(uint3 global_id, const device GlobalLights* const tint_symbol_3, const constant Camera* const tint_symbol_4, const device Clusters* const tint_symbol_5, device ClusterLightGroup* const tint_symbol_6) {
uint const tileIndex = ((global_id[0] + (global_id[1] * tileCount[0])) + ((global_id[2] * tileCount[0]) * tileCount[1]));
uint clusterLightCount = 0u;
tint_array_wrapper_3 cluserLightIndices = {};
for(uint i = 0u; (i < (*(tint_symbol_3)).lightCount); i = (i + 1u)) {
float const range = (*(tint_symbol_3)).lights[i].range;
bool lightInCluster = (range <= 0.0f);
if (!(lightInCluster)) {
float4 const lightViewPos = ((*(tint_symbol_4)).view * float4((*(tint_symbol_3)).lights[i].position, 1.0f));
float const sqDist = sqDistPointAABB(float4(lightViewPos).xyz, (*(tint_symbol_5)).bounds.arr[tileIndex].minAABB, (*(tint_symbol_5)).bounds.arr[tileIndex].maxAABB);
lightInCluster = (sqDist <= (range * range));
}
if (lightInCluster) {
cluserLightIndices.arr[clusterLightCount] = i;
clusterLightCount = (clusterLightCount + 1u);
}
if ((clusterLightCount == 256u)) {
break;
}
}
uint const lightCount = clusterLightCount;
uint offset = atomic_fetch_add_explicit(&((*(tint_symbol_6)).offset), lightCount, memory_order_relaxed);
if ((offset >= 1769472u)) {
return;
}
for(uint i = 0u; (i < clusterLightCount); i = (i + 1u)) {
(*(tint_symbol_6)).indices.arr[(offset + i)] = cluserLightIndices.arr[i];
}
(*(tint_symbol_6)).lights.arr[tileIndex].offset = offset;
(*(tint_symbol_6)).lights.arr[tileIndex].count = clusterLightCount;
}
kernel void computeMain(const device GlobalLights* tint_symbol_7 [[buffer(2)]], const constant Camera* tint_symbol_8 [[buffer(0)]], const device Clusters* tint_symbol_9 [[buffer(3)]], device ClusterLightGroup* tint_symbol_10 [[buffer(1)]], uint3 global_id [[thread_position_in_grid]]) {
computeMain_inner(global_id, tint_symbol_7, tint_symbol_8, tint_symbol_9, tint_symbol_10);
return;
}