#pragma once #include "vkutils/commands.h" #include "vkutils/sync.h" #include "Utilities/Thread.h" #define VK_MAX_ASYNC_COMPUTE_QUEUES 256 namespace vk { enum class xqueue_event_type { label, barrier }; struct xqueue_event { // Type xqueue_event_type type; // Payload std::unique_ptr queue1_signal; std::unique_ptr queue2_signal; // Identifiers u64 completion_eid; u64 uid; xqueue_event(u64 eid, u64 _uid) : type(xqueue_event_type::barrier), completion_eid(eid), uid(_uid) {} xqueue_event(std::unique_ptr& trigger, std::unique_ptr& payload, u64 eid, u64 _uid) : type(xqueue_event_type::label), queue1_signal(std::move(trigger)), queue2_signal(std::move(payload)), completion_eid(eid), uid(_uid) {} }; class AsyncTaskScheduler : private rsx::ref_counted { // Vulkan resources std::vector m_async_command_queue; command_pool m_command_pool; // Running state command_buffer* m_last_used_cb = nullptr; command_buffer* m_current_cb = nullptr; usz m_next_cb_index = 0; std::vector m_barriers_pool; atomic_t m_submit_count = 0; // Scheduler shared_mutex m_config_mutex; bool m_options_initialized = false; bool m_use_host_scheduler = false; // Sync event* m_sync_label = nullptr; atomic_t m_sync_required = false; u64 m_sync_label_debug_uid = 0; static constexpr u32 events_pool_size = 16384; std::vector m_events_pool; atomic_t m_next_event_id = 0; lf_queue m_event_queue; shared_mutex m_submit_mutex; void init_config_options(); void delayed_init(); void insert_sync_event(); public: AsyncTaskScheduler() = default; ~AsyncTaskScheduler(); command_buffer* get_current(); event* get_primary_sync_label(); u64 get_primary_sync_label_debug_uid(); void flush(VkBool32 force_flush, VkSemaphore wait_semaphore = VK_NULL_HANDLE, VkPipelineStageFlags wait_dst_stage_mask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); void kill(); // Thread entry-point void operator()(); static constexpr auto thread_name = "Vulkan Async Scheduler"sv; }; using async_scheduler_thread = named_thread; }