33class TOAST_API AsyncComputeTask {
35 using BufferId = uint32_t;
38 enum class Copy : uint8_t {
46 std::string shader_uri;
47 std::vector<std::string> entries {
"computeMain"};
48 std::string debug_name =
"AsyncComputeTask";
52 class TOAST_API StepContext {
54 template<
typename Push>
55 void dispatch(uint32_t groups_x,
const Push& push, uint32_t entry = 0, uint32_t groups_y = 1, uint32_t groups_z = 1) {
56 dispatchRaw(entry, {groups_x, groups_y, groups_z}, &push,
sizeof(Push));
59 void dispatch(uint32_t groups_x, uint32_t entry = 0, uint32_t groups_y = 1, uint32_t groups_z = 1) {
60 dispatchRaw(entry, {groups_x, groups_y, groups_z},
nullptr, 0);
70 auto hostData(BufferId
id)
const -> std::span<std::byte>;
74 auto hostData(BufferId
id)
const -> std::span<T> {
75 const std::span<std::byte> bytes = hostData(
id);
76 return {
reinterpret_cast<T*
>(bytes.data()), bytes.size() /
sizeof(T)};
80 friend class AsyncComputeTask;
82 StepContext(AsyncComputeTask& task, vk::CommandBuffer cmd, uint32_t slot) : m_task(task), m_cmd(cmd), m_slot(slot) { }
84 void dispatchRaw(uint32_t entry, std::array<uint32_t, 3> groups,
const void* push, uint32_t push_size);
86 AsyncComputeTask& m_task;
87 vk::CommandBuffer m_cmd;
89 bool m_dispatched =
false;
96 explicit operator bool()
const {
97 return m_task !=
nullptr;
102 auto buffer(BufferId
id)
const -> vk::Buffer;
106 auto step() const -> uint64_t {
111 friend class AsyncComputeTask;
112 const AsyncComputeTask* m_task =
nullptr;
126 auto acquireForFrame(vk::CommandBuffer cmd, uint32_t frame_index,
sync::Usage next) -> FrameView;
129 auto read(BufferId
id, std::span<std::byte> out) -> bool;
132 auto read(BufferId
id, std::span<T> out) ->
bool {
133 return read(
id, std::as_writable_bytes(out));
138 auto finishedStep() const -> uint64_t;
141 auto isReady() const ->
bool {
146 explicit AsyncComputeTask(Config config);
149 auto addRingBuffer(vk::DeviceSize size,
bool cpu_readback =
false) -> BufferId;
150 auto addPersistentBuffer(vk::DeviceSize size) -> BufferId;
151 auto addHostBuffer(vk::DeviceSize size) -> BufferId;
152 void bind(uint32_t binding, BufferId
id, Copy copy = Copy::current);
153 void bindExternal(uint32_t set, uint32_t binding, std::function<vk::Buffer()> source);
154 void setAcquireUsage(BufferId
id, sync::Usage usage);
157 void upload(BufferId
id, std::span<const std::byte> data);
160 void upload(BufferId
id, std::span<const T> data) {
161 upload(
id, std::as_bytes(data));
166 const std::function<
void(StepContext&)>& record, std::string_view debug_name = {},
167 std::shared_ptr<const void> keep_alive = {}
172 static constexpr uint32_t k_slot_count = VulkanRenderer::k_frames_in_flight + 3;
177 bool cpu_readback =
false;
178 vk::DeviceSize size = 0;
180 std::vector<vma::raii::Buffer> copies;
181 std::vector<vma::raii::Buffer> readbacks;
182 std::optional<sync::Usage> acquire_usage;
186 uint32_t binding = 0;
188 Copy copy = Copy::current;
191 struct ExternalBinding {
193 uint32_t binding = 0;
194 std::function<vk::Buffer()> source;
198 std::vector<vk::raii::DescriptorSet> sets;
199 AsyncCompute::Ticket ticket = AsyncCompute::k_no_ticket;
204 std::shared_ptr<const void> keep_alive;
207 void createDescriptors();
208 void writeDescriptors(uint32_t slot);
209 auto claimFreeSlot() -> uint32_t;
210 void publish(uint32_t slot, AsyncCompute::Ticket ticket);
212 auto newestFinishedLocked() const -> int32_t;
215 const VulkanCore* m_core =
nullptr;
216 bool m_ready = false;
218 ShaderLayout m_layout;
219 std::vector<std::unique_ptr<VulkanPipeline>> m_pipelines;
220 vk::raii::DescriptorPool m_pool =
nullptr;
222 std::vector<Buffer> m_buffers;
223 std::vector<Binding> m_bindings;
224 std::vector<ExternalBinding> m_externals;
225 vma::raii::Buffer m_placeholder =
nullptr;
227 mutable std::mutex m_mutex;
228 std::array<Slot, k_slot_count> m_slots;
229 uint64_t m_step_counter = 0;
230 int32_t m_last_written = -1;
233 std::array<int32_t, VulkanRenderer::k_frames_in_flight> m_frame_slot {};
234 std::array<uint64_t, k_slot_count> m_acquired_step {};
auto commandBuffer() const -> vk::CommandBuffer
For anything the helpers do not cover.
Definition async_compute_task.hpp:65