Files
Noita-GPU-Vulkan/shaders/proj_lua_dispatch.glsl
T
2026-10-19 20:59:15 +02:00

51 lines
2.4 KiB
GLSL

// Shared by the runtime-compiled program and the offline reference target.
layout(std430,binding=64) buffer LuaTasks { uvec4 luaTasks[]; };
void main() {
uint id=gl_GlobalInvocationID.x;
if(id>=32768u)return;
FProj p=fprojs[id];
uvec4 task=luaTasks[id];
// Gather all additive fields into this target invocation. No invocation
// writes another projectile, so overlapping fields cannot race or lose force.
if(p.d.w!=0&&(p.d.z&(1<<29))==0&&p.d.x>=0&&p.d.x<512) {
uint flags=ft[p.d.x*18+11].y;
if((flags&(3u<<29))==(3u<<29)) {
uint count=luaTasks[32768].y==uint(pc.frame)?min(luaTasks[32768].x,512u):0u;
for(uint field=0u;field<count;++field) {
uvec4 data=luaTasks[32769u+field*2u];
uvec4 source=luaTasks[32770u+field*2u];
if((source.z&1u)!=0u&&source.x==id+1u&&source.y==uint(p.d.w))continue;
FProj candidate=p;
uvec4 fault=ngp_neighbor_dispatch(data.z,candidate,vec3(uintBitsToFloat(data.xy),0.0));
if(fault.x==0u)p=candidate;
else {luaTasks[id]=uvec4(uint(p.d.w),uint(pc.frame),2u,fault.x);}
}
if(count!=0u)fprojs[id]=p;
}
}
if(p.d.w!=0 && p.d.x>=0 && p.d.x<512) {
const uint flags=ft[p.d.x*18+11].y;
const uint period=(flags>>21)&255u;
// bit 30 transfers this instance to a CPU query's materialized twin.
if((flags&(1u<<20))!=0u && (p.d.z&(1<<30))==0 && period!=0u) {
if((uint(pc.frame)+uint(p.d.w))%period!=0u)return;
if(p.a.x<float(pc.view_x-128)||p.a.y<float(pc.view_y-128)||p.a.x>float(pc.view_x+pc.gw+128)||p.a.y>float(pc.view_y+pc.gh+128))return;
if(task.x==uint(p.d.w)&&task.y==uint(pc.frame)&&task.z==2u)return;
task=uvec4(uint(p.d.w),uint(pc.frame),257u,0u); // program 1, pending
luaTasks[id]=task;
}
}
if((task.z&255u)!=1u)return;
uint program=task.z>>8;
luaTasks[id].z=2u;
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;
bool known=owner>=0&&owner<ctrl.inp.w;
if(known)known=(ents[owner].st.w&8)==0;
// The original chunk does nothing when mWhoShot is NULL_ENTITY.
vec3 transform=known?vec3(ents[owner].a.xy,0.0):vec3(0.0);
uvec4 fault=ngp_dispatch(program,p,transform,known?float(owner+1):0.0);
luaTasks[id].w=fault.x;
fprojs[id]=p;
}