#version 450 #extension GL_GOOGLE_include_directive : require layout(local_size_x = 64) in; #include "fx_common.glsl" #include "generated/proj_lua_generated.glsl" // Serial prevents a recycled projectile slot from executing a previous task. // x=cast serial, y=scheduled frame, z=1 pending / 2 complete, w=fault code. layout(std430, set = 0, binding = 64) buffer LuaTasks { uvec4 luaTasks[]; }; void main() { uint id = gl_GlobalInvocationID.x; if (id >= uint(FP_MAX)) return; uvec4 task = luaTasks[id]; if (task.z != 1u) return; luaTasks[id].z = 2u; FProj p = fprojs[id]; if (task.y != uint(pc.frame) || task.x != uint(p.d.w) || p.d.w == 0 || (p.d.z & (1 << 29)) != 0) { luaTasks[id].w = 13u; return; } int owner = int(p.e.z) - 1; if (owner < 0 || owner >= ctrl.inp.w) { luaTasks[id].w = 3u; return; } uvec4 fault = ngp_execute(p, vec3(ents[owner].a.xy, 0.0), float(owner + 1)); luaTasks[id].w = fault.x; // Bindings write only this projectile. No state races between invocations. fprojs[id] = p; }