#pragma once #include #include "Emu/RSX/Core/RSXVertexTypes.h" #include "Emu/RSX/NV47/FW/draw_call.hpp" #include "Emu/RSX/Program/ProgramStateCache.h" #include "Emu/RSX/rsx_vertex_data.h" #include #include namespace rsx { struct rsx_state; struct context; class io_buffer; class draw_command_processor { using vertex_program_metadata_t = program_hash_util::vertex_program_utils::vertex_program_metadata; context* m_ctx = nullptr; protected: friend class thread; std::array m_vertex_push_buffers; rsx::simple_array m_element_push_buffer; public: draw_command_processor() = default; void init(context* ctx) { m_ctx = ctx; } // Analyze vertex inputs and group all interleaved blocks void analyse_inputs_interleaved(vertex_input_layout& layout, const vertex_program_metadata_t& vp_metadata); // Retrieve raw bytes for the index array (untyped) std::span get_raw_index_array(const draw_clause& draw_indexed_clause) const; // Get compiled draw command for backend rendering std::variant get_draw_command(const rsx::rsx_state& state) const; // Push-buffers for immediate rendering (begin-end scopes) void append_to_push_buffer(u32 attribute, u32 size, u32 subreg_index, vertex_base_type type, u32 value); u32 get_push_buffer_vertex_count() const; void append_array_element(u32 index); u32 get_push_buffer_index_count() const; void clear_push_buffers(); const std::span element_push_buffer() const { return m_element_push_buffer; } // Host driver helpers void fill_vertex_layout_state( const vertex_input_layout& layout, const vertex_program_metadata_t& vp_metadata, u32 first_vertex, u32 vertex_count, s32* buffer, u32 persistent_offset_base, u32 volatile_offset_base) const; void write_vertex_data_to_memory( const vertex_input_layout& layout, u32 first_vertex, u32 vertex_count, void* persistent_data, void* volatile_data) const; /** * Fill buffer with 4x4 scale offset matrix. * Vertex shader's position is to be multiplied by this matrix. * if flip_y is set, the matrix is modified to use d3d convention. */ void fill_scale_offset_data(void* buffer, bool flip_y) const; /** * Fill buffer with user clip information */ void fill_user_clip_data(void* buffer) const; /** * Fill buffer with vertex program constants. * Relocation table allows to do a partial fill with only selected registers. */ void fill_vertex_program_constants_data(void* buffer, const std::span& reloc_table) const; /** * Fill buffer with fragment rasterization state. * Fills current fog values, alpha test parameters and texture scaling parameters */ void fill_fragment_state_buffer(void* buffer, const RSXFragmentProgram& fragment_program) const; // Fill instancing buffers. A single iobuf is used for both. 256byte alignment enforced to allow global bind // Returns offsets to the index redirection lookup table and constants field array void fill_constants_instancing_buffer(rsx::io_buffer& indirection_table_buf, rsx::io_buffer& constants_data_array_buffer, const VertexProgramBase* prog) const; }; }