/* * v3d_runner — minimal Vulkan compute plumbing for V3D 7.1 on Pi 5. * * Factored out of tests/bench_vulkan_dispatch.c so successive kernel * benches can reuse the device/queue/buffer/pipeline machinery * without copy-paste. Kept deliberately small and concrete — no * generality beyond what daedalus-fourier needs. * * License: BSD-2-Clause. */ #ifndef DAEDALUS_V3D_RUNNER_H #define DAEDALUS_V3D_RUNNER_H #include #include #include typedef struct v3d_runner v3d_runner; /* Host-visible SSBO. .mapped is a CPU-side pointer to .size bytes. */ typedef struct { VkBuffer buffer; VkDeviceMemory memory; void *mapped; size_t size; } v3d_buffer; /* Compute pipeline + its descriptor set (one set per pipeline). */ typedef struct { VkPipeline pipeline; VkPipelineLayout layout; VkDescriptorSetLayout ds_layout; VkDescriptorPool pool; VkDescriptorSet desc_set; uint32_t n_ssbos; uint32_t push_const_size; } v3d_pipeline; /* * Create runner: Vulkan instance, V3D physical device, logical * device with storageBuffer{8,16}BitAccess features enabled, * compute queue, command pool. * * Returns NULL on failure (writes errors to stderr). */ v3d_runner *v3d_runner_create(void); void v3d_runner_destroy(v3d_runner *r); /* Expose a few internals for code that wants direct vkCmd*. */ VkDevice v3d_runner_device(v3d_runner *r); VkQueue v3d_runner_queue(v3d_runner *r); uint32_t v3d_runner_queue_family(v3d_runner *r); VkCommandPool v3d_runner_cmd_pool(v3d_runner *r); const char *v3d_runner_device_name(v3d_runner *r); /* Storage buffer, HOST_VISIBLE | HOST_COHERENT, mapped on the * host side. The mapping persists for the lifetime of the buffer. * * Returns 0 on success, non-zero on failure. */ int v3d_runner_create_buffer(v3d_runner *r, size_t size, v3d_buffer *out); void v3d_runner_destroy_buffer(v3d_runner *r, v3d_buffer *buf); /* Compute pipeline from a SPIR-V file path. The descriptor-set * layout exposes `n_ssbos` storage buffer bindings at binding * indices 0..n_ssbos-1, all visible to the compute stage. A push * constant range of `push_const_size` bytes is added if non-zero. * * The single descriptor set is pre-allocated; bind buffers via * v3d_runner_bind_buffers(). */ int v3d_runner_create_pipeline(v3d_runner *r, const char *spv_path, uint32_t n_ssbos, uint32_t push_const_size, v3d_pipeline *out); void v3d_runner_destroy_pipeline(v3d_runner *r, v3d_pipeline *p); /* Bind SSBOs to the pipeline's descriptor set. `bufs` must have * exactly `p->n_ssbos` entries, in binding order. Idempotent — * rebind freely between dispatches if buffers change. */ int v3d_runner_bind_buffers(v3d_runner *r, v3d_pipeline *p, const v3d_buffer *bufs, uint32_t n); /* Allocate a primary command buffer from the runner's pool. */ VkCommandBuffer v3d_runner_alloc_cmdbuf(v3d_runner *r); /* Submit `cb` to the queue and wait for completion. The classic * timed operation. Returns 0 on success. */ int v3d_runner_submit_wait(v3d_runner *r, VkCommandBuffer cb); #endif /* DAEDALUS_V3D_RUNNER_H */