///|
/// Benchmarks for the gfx command queue (enqueue + flush + merging).
/// Lives here so we have a stable place to track queue overhead from
/// kagura's perspective without touching the mizchi/gfx package.
///|
fn bench_queue_command(i : Int, alt_state : Bool) -> @gfx.DrawTrianglesCommand {
let dst = @gfx.new_image_handle(1, 1920, 1080)
let shader_id = if alt_state { 2 + (i % 4) } else { 2 }
let shader = @gfx.new_shader_handle(shader_id, "queue_bench")
let dst_region = @gfx.new_dst_region(0, 0, 1920, 1080, 6)
let blend = @gfx.BlendMode::from_int(1)
let left = (i % 256).to_double() * 2.0
let top = (i / 256).to_double() * 2.0
@gfx.new_draw_triangles_command(
dst,
shader,
[dst_region],
0,
7,
11,
blend,
[left, top, 0.0, 0.0, left + 2.0, top, 1.0, 0.0, left + 2.0, top + 2.0, 1.0, 1.0,
left, top + 2.0, 0.0, 1.0],
[0, 1, 2, 2, 3, 0],
[42],
[1, 2, 3, 4],
resource_cache_key=i + 1,
)
}
///|
test "bench gfx queue enqueue+flush 10000 same state" (b : @bench.T) {
// 10000 commands all sharing pipeline/blend/uniform_hash - exercises the
// merge fast path.
let commands : Array[@gfx.DrawTrianglesCommand] = []
for i in 0..<10000 {
commands.push(bench_queue_command(i, false))
}
b.bench(name="gfx_queue/flush_same_state_10000", fn() {
let queue = @gfx.new_simple_command_queue()
for cmd in commands {
queue.enqueue_draw_triangles(cmd)
}
let flushed = queue.flush()
b.keep(flushed.length())
})
}
///|
test "bench gfx queue enqueue+flush 10000 alternating state" (b : @bench.T) {
// 10000 commands cycling through 4 distinct shader ids - merge mostly
// misses, forcing per-command output.
let commands : Array[@gfx.DrawTrianglesCommand] = []
for i in 0..<10000 {
commands.push(bench_queue_command(i, true))
}
b.bench(name="gfx_queue/flush_alt_state_10000", fn() {
let queue = @gfx.new_simple_command_queue()
for cmd in commands {
queue.enqueue_draw_triangles(cmd)
}
let flushed = queue.flush()
b.keep(flushed.length())
})
}