#include "cluster_bounds.h"
#include "pipelines.h"
#include "renderer.h"
#include "shaders/renderer_types.h"
namespace cluster_bounds {
static u64 cluster_total(u32 w, u32 h) {
return (u64)((w + TILE_SIZE_X - 1) / TILE_SIZE_X) * ((h + TILE_SIZE_Y - 1) / TILE_SIZE_Y) * CLUSTER_COUNT_Z;
}
static u64 cluster_bounds_size(u32 w, u32 h) {
return cluster_total(w, h) * sizeof(ClusterBounds);
}
static u64 cluster_records_size(u32 w, u32 h) {
return cluster_total(w, h) * sizeof(ClusterRecord);
}
Resources
record(rhi::Device &device, Pipelines &pipelines, rhi::ShaderCompiler &sc, FrameGraph &fg, u32 width, u32 height) {
rhi::ComputePipelineDesc pd;
pd.device = &device;
pd.set_shader(sc, "src/passes/cluster/cluster_bounds.slang", "csMain");
rhi::ComputePipeline &pipeline = pipelines.add_compute("ClusterBounds", pd);
Resources out;
out.cluster_bounds = fg.add_buffer({
.desc = {.usage = rhi::BufferUsage::StorageBuffer | rhi::BufferUsage::ShaderAddr},
.name = "fg/cluster/bounds",
.size_fn = cluster_bounds_size,
});
out.cluster_records = fg.add_buffer({
.desc = {.usage = rhi::BufferUsage::StorageBuffer | rhi::BufferUsage::ShaderAddr},
.name = "fg/cluster/records",
.size_fn = cluster_records_size,
});
auto &builder = fg.add_pass("ClusterBounds");
builder.write(out.cluster_bounds, rhi::ResourceState::StorageReadWrite);
builder.execute([=, &pipeline](PassContext &ctx) {
auto &frame = ctx.frame_data[ctx.frame_index];
u32 cx = (ctx.render_width + TILE_SIZE_X - 1) / TILE_SIZE_X;
u32 cy = (ctx.render_height + TILE_SIZE_Y - 1) / TILE_SIZE_Y;
u32 cz = CLUSTER_COUNT_Z;
u32 total_clusters = cx * cy * cz;
rhi::set_pipeline(ctx.cmd, pipeline);
ClusterGrid cb{
.cluster_count_x = cx,
.cluster_count_y = cy,
.cluster_count_z = cz,
.cluster_total = total_clusters,
.clusters_bounds = rhi::buffer_device_address(ctx.device, ctx.get_buffer(out.cluster_bounds)),
};
memcpy((u8 *)frame.frame_ubo.mapped + offsetof(FrameUBO, cluster), &cb, sizeof(ClusterGrid));
ClusterBoundsPushConstants pc{};
pc.frame = (u64)ctx.render_data->frame_ubo_view[ctx.frame_index].slot;
{
static_assert(sizeof(pc) <= 128, "push constants exceed global 128B range");
char pc128[128] = {};
std::memcpy(pc128, &pc, sizeof(pc));
rhi::set_constants(ctx.cmd, pipeline, rhi::ShaderStage::ALL, sizeof(pc128), pc128);
}
u32 total = cx * cy * cz;
u32 groups = (total + 63u) / 64u;
if (groups > 0) {
rhi::dispatch(ctx.cmd, groups);
}
});
return out;
}
} // namespace cluster_bounds