2020-04-22 10:55:17 +10:00
|
|
|
// This is "kernel 1" in a 4-kernel pipeline. It traverses the scene graph
|
|
|
|
// and outputs "instances" (references to item + translation) for each item
|
|
|
|
// that intersects the tilegroup.
|
|
|
|
//
|
|
|
|
// This implementation is simplistic and leaves a lot of performance on the
|
|
|
|
// table. A fancier implementation would use threadgroup shared memory or
|
|
|
|
// subgroups (or possibly both) to parallelize the reading of the input and
|
|
|
|
// the computation of tilegroup intersection.
|
|
|
|
//
|
|
|
|
// In addition, there are some features currently missing. One is the use of
|
|
|
|
// a bump allocator to extend the current fixed allocation. Another is support
|
|
|
|
// for clipping.
|
|
|
|
|
2020-04-21 10:15:36 +10:00
|
|
|
#version 450
|
|
|
|
#extension GL_GOOGLE_include_directive : enable
|
|
|
|
|
|
|
|
// It's possible we should lay this out with x and do our own math.
|
|
|
|
layout(local_size_x = 1, local_size_y = 32) in;
|
|
|
|
|
|
|
|
layout(set = 0, binding = 0) readonly buffer SceneBuf {
|
|
|
|
uint[] scene;
|
|
|
|
};
|
|
|
|
|
|
|
|
layout(set = 0, binding = 1) buffer TilegroupBuf {
|
|
|
|
uint[] tilegroup;
|
|
|
|
};
|
|
|
|
|
2020-04-26 03:15:22 +10:00
|
|
|
layout(set = 0, binding = 2) buffer AllocBuf {
|
|
|
|
uint alloc;
|
|
|
|
};
|
|
|
|
|
2020-04-21 10:15:36 +10:00
|
|
|
#include "scene.h"
|
|
|
|
#include "tilegroup.h"
|
|
|
|
|
2020-04-25 06:06:47 +10:00
|
|
|
#include "setup.h"
|
2020-04-21 10:15:36 +10:00
|
|
|
|
|
|
|
#define MAX_STACK 8
|
|
|
|
|
|
|
|
struct StackElement {
|
|
|
|
PietItemRef group;
|
|
|
|
uint index;
|
|
|
|
vec2 offset;
|
|
|
|
};
|
|
|
|
|
|
|
|
void main() {
|
|
|
|
StackElement stack[MAX_STACK];
|
|
|
|
uint stack_ix = 0;
|
|
|
|
uint tilegroup_ix = gl_GlobalInvocationID.y * WIDTH_IN_TILEGROUPS + gl_GlobalInvocationID.x;
|
2020-04-22 10:55:17 +10:00
|
|
|
TileGroupRef tg_ref = TileGroupRef(tilegroup_ix * TILEGROUP_INITIAL_ALLOC);
|
2020-04-26 03:15:22 +10:00
|
|
|
uint tg_limit = tg_ref.offset + TILEGROUP_INITIAL_ALLOC - 2 * TileGroup_size;
|
2020-04-22 10:55:17 +10:00
|
|
|
vec2 xy0 = vec2(gl_GlobalInvocationID.xy) * vec2(TILEGROUP_WIDTH_PX, TILEGROUP_HEIGHT_PX);
|
2020-04-21 10:15:36 +10:00
|
|
|
PietItemRef root = PietItemRef(0);
|
|
|
|
SimpleGroup group = PietItem_Group_read(root);
|
|
|
|
StackElement tos = StackElement(root, 0, group.offset.xy);
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
if (tos.index < group.n_items) {
|
|
|
|
Bbox bbox = Bbox_read(Bbox_index(group.bboxes, tos.index));
|
|
|
|
vec4 bb = vec4(bbox.bbox) + tos.offset.xyxy;
|
2020-04-22 10:55:17 +10:00
|
|
|
bool hit = max(bb.x, xy0.x) < min(bb.z, xy0.x + float(TILEGROUP_WIDTH_PX))
|
|
|
|
&& max(bb.y, xy0.y) < min(bb.w, xy0.y + float(TILEGROUP_HEIGHT_PX));
|
2020-04-21 10:15:36 +10:00
|
|
|
bool is_group = false;
|
|
|
|
if (hit) {
|
|
|
|
PietItemRef item_ref = PietItem_index(group.items, tos.index);
|
|
|
|
is_group = PietItem_tag(item_ref) == PietItem_Group;
|
|
|
|
}
|
|
|
|
if (hit && !is_group) {
|
|
|
|
PietItemRef item_ref = PietItem_index(group.items, tos.index);
|
|
|
|
Instance ins = Instance(item_ref.offset, tos.offset);
|
2020-04-26 03:15:22 +10:00
|
|
|
if (tg_ref.offset > tg_limit) {
|
|
|
|
// Allocation exceeded; do atomic bump alloc.
|
|
|
|
uint new_tg = atomicAdd(alloc, TILEGROUP_INITIAL_ALLOC);
|
|
|
|
Jump jump = Jump(new_tg);
|
|
|
|
TileGroup_Jump_write(tg_ref, jump);
|
|
|
|
tg_ref = TileGroupRef(new_tg);
|
|
|
|
tg_limit = tg_ref.offset + TILEGROUP_INITIAL_ALLOC - 2 * TileGroup_size;
|
|
|
|
}
|
2020-04-21 10:15:36 +10:00
|
|
|
TileGroup_Instance_write(tg_ref, ins);
|
|
|
|
tg_ref.offset += TileGroup_size;
|
|
|
|
}
|
|
|
|
if (is_group) {
|
|
|
|
PietItemRef item_ref = PietItem_index(group.items, tos.index);
|
|
|
|
tos.index++;
|
|
|
|
if (tos.index < group.n_items) {
|
|
|
|
stack[stack_ix++] = tos;
|
|
|
|
}
|
|
|
|
group = PietItem_Group_read(item_ref);
|
|
|
|
tos = StackElement(item_ref, 0, tos.offset + group.offset.xy);
|
|
|
|
} else {
|
|
|
|
tos.index++;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// processed all items in this group; pop the stack
|
|
|
|
if (stack_ix == 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
tos = stack[--stack_ix];
|
|
|
|
group = PietItem_Group_read(tos.group);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TileGroup_End_write(tg_ref);
|
|
|
|
}
|