#pragma once #include #include #include #include namespace rsx { struct host_gpu_context_t { u64 magic = 0xCAFEBABE; u64 event_counter = 0; u64 texture_load_request_event = 0; u64 texture_load_complete_event = 0; u64 last_label_acquire_event = 0; u64 last_label_release2_event = 0; u64 commands_complete_event = 0; inline u64 inc_counter() volatile { // Workaround for volatile increment warning. GPU can see this value directly, but currently we do not modify it on the device. event_counter = event_counter + 1; return event_counter; } inline bool in_flight_commands_completed() const volatile { return last_label_release2_event <= commands_complete_event; } inline bool texture_loads_completed() const volatile { // Return true if all texture load requests are done. return texture_load_complete_event == texture_load_request_event; } inline bool has_unflushed_texture_loads() const volatile { return texture_load_request_event > last_label_release2_event; } inline u64 on_texture_load_acquire() volatile { texture_load_request_event = inc_counter(); return texture_load_request_event; } inline void on_texture_load_release() volatile { // Normally released by the host device, but implemented nonetheless for software fallback texture_load_complete_event = texture_load_request_event; } inline u64 on_label_acquire() volatile { last_label_acquire_event = inc_counter(); return last_label_acquire_event; } inline void on_label_release() volatile { last_label_release2_event = last_label_acquire_event; } inline bool needs_label_release() const volatile { return last_label_acquire_event > last_label_release2_event; } }; struct host_gpu_write_op_t { int dispatch_class = 0; void* userdata = nullptr; }; struct host_dispatch_handler_t { int dispatch_class = 0; std::function handler; }; class RSXDMAWriter { public: RSXDMAWriter(void* mem) : m_host_context_ptr(new (mem) host_gpu_context_t) { } RSXDMAWriter(host_gpu_context_t* pctx) : m_host_context_ptr(pctx) { } void update(); void register_handler(host_dispatch_handler_t handler); void deregister_handler(int dispatch_class); void enqueue(const host_gpu_write_op_t& request); void drain_label_queue(); volatile host_gpu_context_t* host_ctx() const { return m_host_context_ptr; } private: std::unordered_map m_dispatch_handlers; volatile host_gpu_context_t* m_host_context_ptr = nullptr; std::deque m_job_queue; }; } // namespace rsx