diff --git a/rpcs3/Emu/RSX/GL/GLDraw.cpp b/rpcs3/Emu/RSX/GL/GLDraw.cpp index fce7c2a650..8061f5a180 100644 --- a/rpcs3/Emu/RSX/GL/GLDraw.cpp +++ b/rpcs3/Emu/RSX/GL/GLDraw.cpp @@ -509,7 +509,7 @@ void GLGSRender::emit_geometry(u32 sub_index) auto& draw_call = rsx::method_registers.current_draw_clause; const rsx::flags32_t vertex_state_mask = rsx::vertex_base_changed | rsx::vertex_arrays_changed; - const rsx::flags32_t vertex_state = (sub_index == 0) ? rsx::vertex_arrays_changed : draw_call.execute_pipeline_dependencies() & vertex_state_mask; + const rsx::flags32_t vertex_state = (sub_index == 0) ? rsx::vertex_arrays_changed : draw_call.execute_pipeline_dependencies(m_ctx) & vertex_state_mask; if (vertex_state & rsx::vertex_arrays_changed) { @@ -540,7 +540,7 @@ void GLGSRender::emit_geometry(u32 sub_index) // Execute remainining pipeline barriers with NOP draw do { - draw_call.execute_pipeline_dependencies(); + draw_call.execute_pipeline_dependencies(m_ctx); } while (draw_call.next()); draw_call.end(); diff --git a/rpcs3/Emu/RSX/NV47/FW/draw_call.hpp b/rpcs3/Emu/RSX/NV47/FW/draw_call.hpp new file mode 100644 index 0000000000..94c6291ad6 --- /dev/null +++ b/rpcs3/Emu/RSX/NV47/FW/draw_call.hpp @@ -0,0 +1,310 @@ +#pragma once + +#include "draw_call.inc.h" + +#include "Emu/RSX/Common/simple_array.hpp" +#include "Emu/RSX/gcm_enums.h" + +namespace rsx +{ + class draw_clause + { + // Stores the first and count argument from draw/draw indexed parameters between begin/end clauses. + simple_array draw_command_ranges{}; + + // Stores rasterization barriers for primitive types sensitive to adjacency + simple_array draw_command_barriers{}; + + // Counter used to parse the commands in order + u32 current_range_index{}; + + // Location of last execution barrier + u32 last_execution_barrier_index{}; + + // Helper functions + // Add a new draw command + void append_draw_command(const draw_range_t& range) + { + current_range_index = draw_command_ranges.size(); + draw_command_ranges.push_back(range); + } + + // Insert a new draw command within the others + void insert_draw_command(u32 index, const draw_range_t& range) + { + auto range_It = draw_command_ranges.begin(); + std::advance(range_It, index); + + current_range_index = index; + draw_command_ranges.insert(range_It, range); + + // Update all barrier draw ids after this one + for (auto& barrier : draw_command_barriers) + { + if (barrier.draw_id >= index) + { + barrier.draw_id++; + } + } + } + + public: + primitive_type primitive{}; + draw_command command{}; + + bool is_immediate_draw{}; // Set if part of the draw is submitted via push registers + bool is_disjoint_primitive{}; // Set if primitive type does not rely on adjacency information + bool primitive_barrier_enable{}; // Set once to signal that a primitive restart barrier can be inserted + + simple_array inline_vertex_array{}; + + void operator()(utils::serial& ar); + + void insert_command_barrier(command_barrier_type type, u32 arg, u32 register_index = 0); + + /** + * Optimize commands for rendering + */ + void compile() + { + // End draw call append mode + current_range_index = ~0u; + + // TODO + } + + /** + * Insert one command range + */ + + void append(u32 first, u32 count) + { + const bool barrier_enable_flag = primitive_barrier_enable; + primitive_barrier_enable = false; + + if (!draw_command_ranges.empty()) + { + auto& last = draw_command_ranges[current_range_index]; + + if (last.count == 0) + { + // Special case, usually indicates an execution barrier + last.first = first; + last.count = count; + return; + } + + if (last.first + last.count == first) + { + if (!is_disjoint_primitive && barrier_enable_flag) + { + // Insert barrier + insert_command_barrier(primitive_restart_barrier, 0); + } + + last.count += count; + return; + } + + for (auto index = last_execution_barrier_index; index < draw_command_ranges.size(); ++index) + { + if (draw_command_ranges[index].first == first && + draw_command_ranges[index].count == count) + { + // Duplicate entry? WTF! + return; + } + + if (draw_command_ranges[index].first > first) + { + insert_draw_command(index, { 0, first, count }); + return; + } + } + } + + append_draw_command({ 0, first, count }); + } + + /** + * Returns how many vertex or index will be consumed by the draw clause. + */ + u32 get_elements_count() const + { + if (draw_command_ranges.empty()) + { + ensure(command == rsx::draw_command::inlined_array); + return 0; + } + + return get_range().count; + } + + u32 min_index() const + { + if (draw_command_ranges.empty()) + { + ensure(command == rsx::draw_command::inlined_array); + return 0; + } + + return get_range().first; + } + + bool is_single_draw() const + { + if (is_disjoint_primitive) + return true; + + if (draw_command_ranges.empty()) + { + ensure(!inline_vertex_array.empty()); + return true; + } + + ensure(current_range_index != ~0u); + for (const auto& barrier : draw_command_barriers) + { + if (barrier.draw_id != current_range_index) + continue; + + if (barrier.type == primitive_restart_barrier) + return false; + } + + return true; + } + + bool empty() const + { + return (command == rsx::draw_command::inlined_array) ? inline_vertex_array.empty() : draw_command_ranges.empty(); + } + + u32 pass_count() const + { + if (draw_command_ranges.empty()) + { + ensure(!inline_vertex_array.empty()); + return 1u; + } + + u32 count = ::size32(draw_command_ranges); + if (draw_command_ranges.back().count == 0) + { + // Dangling barrier + ensure(count > 1); + count--; + } + + return count; + } + + primitive_class classify_mode() const + { + return primitive >= rsx::primitive_type::triangles + ? primitive_class::polygon + : primitive_class::non_polygon; + } + + + void reset(rsx::primitive_type type); + + void begin() + { + current_range_index = 0; + } + + void end() + { + current_range_index = draw_command_ranges.size() - 1; + } + + bool next() + { + current_range_index++; + if (current_range_index >= draw_command_ranges.size()) + { + current_range_index = 0; + return false; + } + + if (draw_command_ranges[current_range_index].count == 0) + { + // Dangling execution barrier + ensure(current_range_index > 0 && (current_range_index + 1) == draw_command_ranges.size()); + current_range_index = 0; + return false; + } + + return true; + } + + /** + * Only call this once after the draw clause has been fully consumed to reconcile any conflicts + */ + void post_execute_cleanup(struct context* ctx) + { + ensure(current_range_index == 0); + + if (draw_command_ranges.size() > 1) + { + if (draw_command_ranges.back().count == 0) + { + // Dangling execution barrier + current_range_index = draw_command_ranges.size() - 1; + execute_pipeline_dependencies(ctx); + current_range_index = 0; + } + } + } + + /** + * Executes commands reqiured to make the current draw state valid + */ + u32 execute_pipeline_dependencies(struct context* ctx) const; + + const draw_range_t& get_range() const + { + ensure(current_range_index < draw_command_ranges.size()); + return draw_command_ranges[current_range_index]; + } + + simple_array get_subranges() const + { + ensure(!is_single_draw()); + + const auto range = get_range(); + const auto limit = range.first + range.count; + + simple_array ret; + u32 previous_barrier = range.first; + u32 vertex_counter = 0; + + for (const auto& barrier : draw_command_barriers) + { + if (barrier.draw_id != current_range_index) + continue; + + if (barrier.type != primitive_restart_barrier) + continue; + + if (barrier.address <= range.first) + continue; + + if (barrier.address >= limit) + break; + + const u32 count = barrier.address - previous_barrier; + ret.push_back({ 0, vertex_counter, count }); + previous_barrier = barrier.address; + vertex_counter += count; + } + + ensure(!ret.empty()); + ensure(previous_barrier < limit); + ret.push_back({ 0, vertex_counter, limit - previous_barrier }); + + return ret; + } + }; +} diff --git a/rpcs3/Emu/RSX/NV47/FW/draw_call.inc.h b/rpcs3/Emu/RSX/NV47/FW/draw_call.inc.h new file mode 100644 index 0000000000..a29915ead2 --- /dev/null +++ b/rpcs3/Emu/RSX/NV47/FW/draw_call.inc.h @@ -0,0 +1,68 @@ +#pragma once + +#include + +namespace rsx +{ + enum class draw_command + { + none, + array, + inlined_array, + indexed, + }; + + enum command_barrier_type : u32 + { + primitive_restart_barrier, + vertex_base_modifier_barrier, + index_base_modifier_barrier, + vertex_array_offset_modifier_barrier + }; + + enum command_execution_flags : u32 + { + vertex_base_changed = (1 << 0), + index_base_changed = (1 << 1), + vertex_arrays_changed = (1 << 2), + }; + + enum class primitive_class + { + polygon, + non_polygon + }; + + struct barrier_t + { + u32 draw_id; + u64 timestamp; + + u32 address; + u32 index; + u32 arg; + u32 flags; + command_barrier_type type; + + bool operator < (const barrier_t& other) const + { + if (address != ~0u) + { + return address < other.address; + } + + return timestamp < other.timestamp; + } + + ENABLE_BITWISE_SERIALIZATION; + }; + + struct draw_range_t + { + u32 command_data_offset = 0; + u32 first = 0; + u32 count = 0; + + ENABLE_BITWISE_SERIALIZATION; + }; +} diff --git a/rpcs3/Emu/RSX/NV47/FW/reg_context.cpp b/rpcs3/Emu/RSX/NV47/FW/reg_context.cpp new file mode 100644 index 0000000000..a27b824da7 --- /dev/null +++ b/rpcs3/Emu/RSX/NV47/FW/reg_context.cpp @@ -0,0 +1 @@ +#include "stdafx.h" diff --git a/rpcs3/Emu/RSX/NV47/FW/reg_context.h b/rpcs3/Emu/RSX/NV47/FW/reg_context.h new file mode 100644 index 0000000000..8f0477022f --- /dev/null +++ b/rpcs3/Emu/RSX/NV47/FW/reg_context.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +namespace rsx +{ + // TODO: Basically replaces parts of the current "rsx_state" object + struct reg_context + { + u32 registers[1]; + }; +} diff --git a/rpcs3/Emu/RSX/NV47/common.cpp b/rpcs3/Emu/RSX/NV47/HW/common.cpp similarity index 75% rename from rpcs3/Emu/RSX/NV47/common.cpp rename to rpcs3/Emu/RSX/NV47/HW/common.cpp index 319a7c41bf..3c7d38104d 100644 --- a/rpcs3/Emu/RSX/NV47/common.cpp +++ b/rpcs3/Emu/RSX/NV47/HW/common.cpp @@ -62,5 +62,25 @@ namespace rsx return vm::cast(get_address(offset, location)); } + + void set_fragment_texture_dirty_bit(rsx::context* ctx, u32 index) + { + RSX(ctx)->m_textures_dirty[index] = true; + + if (RSX(ctx)->current_fp_metadata.referenced_textures_mask & (1 << index)) + { + RSX(ctx)->m_graphics_state |= rsx::pipeline_state::fragment_program_state_dirty; + } + } + + void set_vertex_texture_dirty_bit(rsx::context* ctx, u32 index) + { + RSX(ctx)->m_vertex_textures_dirty[index] = true; + + if (RSX(ctx)->current_vp_metadata.referenced_textures_mask & (1 << index)) + { + RSX(ctx)->m_graphics_state |= rsx::pipeline_state::vertex_program_state_dirty; + } + } } } \ No newline at end of file diff --git a/rpcs3/Emu/RSX/NV47/HW/common.h b/rpcs3/Emu/RSX/NV47/HW/common.h new file mode 100644 index 0000000000..04589d651e --- /dev/null +++ b/rpcs3/Emu/RSX/NV47/HW/common.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include "context.h" +#include "context_accessors.define.h" + +namespace rsx +{ + enum command_barrier_type : u32; + enum class vertex_base_type : u8; + + namespace util + { + u32 get_report_data_impl(rsx::context* ctx, u32 offset); + + void push_vertex_data(rsx::context* ctx, u32 attrib_index, u32 channel_select, int count, rsx::vertex_base_type vtype, u32 value); + + void push_draw_parameter_change(rsx::context* ctx, rsx::command_barrier_type type, u32 reg, u32 arg); + + void set_fragment_texture_dirty_bit(rsx::context* ctx, u32 index); + + void set_vertex_texture_dirty_bit(rsx::context* ctx, u32 index); + } +} + +#include "context_accessors.undef.h" diff --git a/rpcs3/Emu/RSX/NV47/context.h b/rpcs3/Emu/RSX/NV47/HW/context.h similarity index 89% rename from rpcs3/Emu/RSX/NV47/context.h rename to rpcs3/Emu/RSX/NV47/HW/context.h index 24f67bdfae..761ad2be5f 100644 --- a/rpcs3/Emu/RSX/NV47/context.h +++ b/rpcs3/Emu/RSX/NV47/HW/context.h @@ -5,6 +5,7 @@ namespace rsx { class thread; + struct rsx_state; #if 0 // TODO: Separate GRAPH context from RSX state diff --git a/rpcs3/Emu/RSX/NV47/context_accessors.define.h b/rpcs3/Emu/RSX/NV47/HW/context_accessors.define.h similarity index 100% rename from rpcs3/Emu/RSX/NV47/context_accessors.define.h rename to rpcs3/Emu/RSX/NV47/HW/context_accessors.define.h diff --git a/rpcs3/Emu/RSX/NV47/context_accessors.undef.h b/rpcs3/Emu/RSX/NV47/HW/context_accessors.undef.h similarity index 100% rename from rpcs3/Emu/RSX/NV47/context_accessors.undef.h rename to rpcs3/Emu/RSX/NV47/HW/context_accessors.undef.h diff --git a/rpcs3/Emu/RSX/NV47/HW/nv0039.cpp b/rpcs3/Emu/RSX/NV47/HW/nv0039.cpp new file mode 100644 index 0000000000..fb20d93a69 --- /dev/null +++ b/rpcs3/Emu/RSX/NV47/HW/nv0039.cpp @@ -0,0 +1,140 @@ +#include "stdafx.h" +#include "nv0039.h" + +#include "Emu/RSX/RSXThread.h" +#include "Emu/RSX/Core/RSXReservationLock.hpp" + +#include "context_accessors.define.h" + +namespace rsx +{ + namespace nv0039 + { + void buffer_notify(context* ctx, u32, u32 arg) + { + s32 in_pitch = REGS(ctx)->nv0039_input_pitch(); + s32 out_pitch = REGS(ctx)->nv0039_output_pitch(); + const u32 line_length = REGS(ctx)->nv0039_line_length(); + const u32 line_count = REGS(ctx)->nv0039_line_count(); + const u8 out_format = REGS(ctx)->nv0039_output_format(); + const u8 in_format = REGS(ctx)->nv0039_input_format(); + const u32 notify = arg; + + if (!line_count || !line_length) + { + rsx_log.warning("NV0039_BUFFER_NOTIFY NOPed out: pitch(in=0x%x, out=0x%x), line(len=0x%x, cnt=0x%x), fmt(in=0x%x, out=0x%x), notify=0x%x", + in_pitch, out_pitch, line_length, line_count, in_format, out_format, notify); + return; + } + + rsx_log.trace("NV0039_BUFFER_NOTIFY: pitch(in=0x%x, out=0x%x), line(len=0x%x, cnt=0x%x), fmt(in=0x%x, out=0x%x), notify=0x%x", + in_pitch, out_pitch, line_length, line_count, in_format, out_format, notify); + + u32 src_offset = REGS(ctx)->nv0039_input_offset(); + u32 src_dma = REGS(ctx)->nv0039_input_location(); + + u32 dst_offset = REGS(ctx)->nv0039_output_offset(); + u32 dst_dma = REGS(ctx)->nv0039_output_location(); + + const bool is_block_transfer = (in_pitch == out_pitch && out_pitch + 0u == line_length); + const auto read_address = get_address(src_offset, src_dma); + const auto write_address = get_address(dst_offset, dst_dma); + const auto read_length = in_pitch * (line_count - 1) + line_length; + const auto write_length = out_pitch * (line_count - 1) + line_length; + + RSX(ctx)->invalidate_fragment_program(dst_dma, dst_offset, write_length); + + if (const auto result = RSX(ctx)->read_barrier(read_address, read_length, !is_block_transfer); + result == rsx::result_zcull_intr) + { + // This transfer overlaps will zcull data pool + if (RSX(ctx)->copy_zcull_stats(read_address, read_length, write_address) == write_length) + { + // All writes deferred + return; + } + } + + auto res = ::rsx::reservation_lock(write_address, write_length, read_address, read_length); + + u8 *dst = vm::_ptr(write_address); + const u8 *src = vm::_ptr(read_address); + + const bool is_overlapping = dst_dma == src_dma && [&]() -> bool + { + const u32 src_max = src_offset + read_length; + const u32 dst_max = dst_offset + (out_pitch * (line_count - 1) + line_length); + return (src_offset >= dst_offset && src_offset < dst_max) || + (dst_offset >= src_offset && dst_offset < src_max); + }(); + + if (in_format > 1 || out_format > 1) [[ unlikely ]] + { + // The formats are just input channel strides. You can use this to do cool tricks like gathering channels + // Very rare, only seen in use by Destiny + // TODO: Hw accel + for (u32 row = 0; row < line_count; ++row) + { + auto dst_ptr = dst; + auto src_ptr = src; + while (src_ptr < src + line_length) + { + *dst_ptr = *src_ptr; + + src_ptr += in_format; + dst_ptr += out_format; + } + + dst += out_pitch; + src += in_pitch; + } + } + else if (is_overlapping) [[ unlikely ]] + { + if (is_block_transfer) + { + std::memmove(dst, src, read_length); + } + else + { + std::vector temp(line_length * line_count); + u8* buf = temp.data(); + + for (u32 y = 0; y < line_count; ++y) + { + std::memcpy(buf, src, line_length); + buf += line_length; + src += in_pitch; + } + + buf = temp.data(); + + for (u32 y = 0; y < line_count; ++y) + { + std::memcpy(dst, buf, line_length); + buf += line_length; + dst += out_pitch; + } + } + } + else + { + if (is_block_transfer) + { + std::memcpy(dst, src, read_length); + } + else + { + for (u32 i = 0; i < line_count; ++i) + { + std::memcpy(dst, src, line_length); + dst += out_pitch; + src += in_pitch; + } + } + } + + //res->release(0); + } + } +} diff --git a/rpcs3/Emu/RSX/NV47/HW/nv0039.h b/rpcs3/Emu/RSX/NV47/HW/nv0039.h new file mode 100644 index 0000000000..9168f76ede --- /dev/null +++ b/rpcs3/Emu/RSX/NV47/HW/nv0039.h @@ -0,0 +1,12 @@ +// NV47 Buffer Management +#pragma once + +#include "context.h" + +namespace rsx +{ + namespace nv0039 + { + void buffer_notify(context* ctx, u32 reg, u32 arg); + } +} diff --git a/rpcs3/Emu/RSX/NV47/nv3089.cpp b/rpcs3/Emu/RSX/NV47/HW/nv3089.cpp similarity index 96% rename from rpcs3/Emu/RSX/NV47/nv3089.cpp rename to rpcs3/Emu/RSX/NV47/HW/nv3089.cpp index 97f837ecf8..4498b7e0ac 100644 --- a/rpcs3/Emu/RSX/NV47/nv3089.cpp +++ b/rpcs3/Emu/RSX/NV47/HW/nv3089.cpp @@ -2,6 +2,8 @@ #include "nv3089.h" #include "Emu/RSX/RSXThread.h" +#include "Emu/RSX/Core/RSXReservationLock.hpp" +#include "Emu/RSX/Common/tiled_dma_copy.hpp" #include "context_accessors.define.h" diff --git a/rpcs3/Emu/RSX/NV47/nv3089.h b/rpcs3/Emu/RSX/NV47/HW/nv3089.h similarity index 77% rename from rpcs3/Emu/RSX/NV47/nv3089.h rename to rpcs3/Emu/RSX/NV47/HW/nv3089.h index e54b4a48c5..89b526b9d4 100644 --- a/rpcs3/Emu/RSX/NV47/nv3089.h +++ b/rpcs3/Emu/RSX/NV47/HW/nv3089.h @@ -1,4 +1,6 @@ +// NV47 2D Blit Engine #pragma once + #include "context.h" namespace rsx diff --git a/rpcs3/Emu/RSX/NV47/nv308a.cpp b/rpcs3/Emu/RSX/NV47/HW/nv308a.cpp similarity index 95% rename from rpcs3/Emu/RSX/NV47/nv308a.cpp rename to rpcs3/Emu/RSX/NV47/HW/nv308a.cpp index 049f39d192..6a783f26ea 100644 --- a/rpcs3/Emu/RSX/NV47/nv308a.cpp +++ b/rpcs3/Emu/RSX/NV47/HW/nv308a.cpp @@ -2,6 +2,7 @@ #include "nv308a.h" #include "Emu/RSX/RSXThread.h" +#include "Emu/RSX/Core/RSXReservationLock.hpp" #include "context_accessors.define.h" diff --git a/rpcs3/Emu/RSX/NV47/nv308a.h b/rpcs3/Emu/RSX/NV47/HW/nv308a.h similarity index 79% rename from rpcs3/Emu/RSX/NV47/nv308a.h rename to rpcs3/Emu/RSX/NV47/HW/nv308a.h index eb28063c2b..5b14e6d3a5 100644 --- a/rpcs3/Emu/RSX/NV47/nv308a.h +++ b/rpcs3/Emu/RSX/NV47/HW/nv308a.h @@ -1,3 +1,4 @@ +// NV47 Format Conversion #pragma once #include "context.h" diff --git a/rpcs3/Emu/RSX/NV47/nv406e.cpp b/rpcs3/Emu/RSX/NV47/HW/nv406e.cpp similarity index 95% rename from rpcs3/Emu/RSX/NV47/nv406e.cpp rename to rpcs3/Emu/RSX/NV47/HW/nv406e.cpp index 3c28acfcef..4d43dcd37d 100644 --- a/rpcs3/Emu/RSX/NV47/nv406e.cpp +++ b/rpcs3/Emu/RSX/NV47/HW/nv406e.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #include "nv406e.h" #include "common.h" +#include "nv47_sync.hpp" #include "Emu/RSX/RSXThread.h" diff --git a/rpcs3/Emu/RSX/NV47/nv406e.h b/rpcs3/Emu/RSX/NV47/HW/nv406e.h similarity index 87% rename from rpcs3/Emu/RSX/NV47/nv406e.h rename to rpcs3/Emu/RSX/NV47/HW/nv406e.h index 426228741c..4fd7200f32 100644 --- a/rpcs3/Emu/RSX/NV47/nv406e.h +++ b/rpcs3/Emu/RSX/NV47/HW/nv406e.h @@ -1,3 +1,4 @@ +// NV47 Sync Objects #pragma once #include "context.h" diff --git a/rpcs3/Emu/RSX/NV47/nv4097.cpp b/rpcs3/Emu/RSX/NV47/HW/nv4097.cpp similarity index 92% rename from rpcs3/Emu/RSX/NV47/nv4097.cpp rename to rpcs3/Emu/RSX/NV47/HW/nv4097.cpp index c9155f5dbc..74a76fea71 100644 --- a/rpcs3/Emu/RSX/NV47/nv4097.cpp +++ b/rpcs3/Emu/RSX/NV47/HW/nv4097.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "nv4097.h" +#include "nv47_sync.hpp" #include "Emu/RSX/RSXThread.h" #include "Emu/RSX/Common/BufferUtils.h" @@ -10,13 +11,6 @@ namespace rsx { - template struct vertex_data_type_from_element_type; - template<> struct vertex_data_type_from_element_type { static const vertex_base_type type = vertex_base_type::f; }; - template<> struct vertex_data_type_from_element_type { static const vertex_base_type type = vertex_base_type::sf; }; - template<> struct vertex_data_type_from_element_type { static const vertex_base_type type = vertex_base_type::ub; }; - template<> struct vertex_data_type_from_element_type { static const vertex_base_type type = vertex_base_type::s32k; }; - template<> struct vertex_data_type_from_element_type { static const vertex_base_type type = vertex_base_type::s1; }; - namespace nv4097 { ///// Program management diff --git a/rpcs3/Emu/RSX/NV47/nv4097.h b/rpcs3/Emu/RSX/NV47/HW/nv4097.h similarity index 81% rename from rpcs3/Emu/RSX/NV47/nv4097.h rename to rpcs3/Emu/RSX/NV47/HW/nv4097.h index 6007563434..670f898eef 100644 --- a/rpcs3/Emu/RSX/NV47/nv4097.h +++ b/rpcs3/Emu/RSX/NV47/HW/nv4097.h @@ -3,13 +3,22 @@ #include "common.h" +#include "Emu/RSX/gcm_enums.h" +#include "Emu/RSX/NV47/FW/draw_call.inc.h" + namespace rsx { - enum command_barrier_type; - enum vertex_base_type; + enum command_barrier_type : u32; namespace nv4097 { + template struct vertex_data_type_from_element_type; + template<> struct vertex_data_type_from_element_type { static const vertex_base_type type = vertex_base_type::f; }; + template<> struct vertex_data_type_from_element_type { static const vertex_base_type type = vertex_base_type::sf; }; + template<> struct vertex_data_type_from_element_type { static const vertex_base_type type = vertex_base_type::ub; }; + template<> struct vertex_data_type_from_element_type { static const vertex_base_type type = vertex_base_type::s32k; }; + template<> struct vertex_data_type_from_element_type { static const vertex_base_type type = vertex_base_type::s1; }; + void clear(context* ctx, u32 reg, u32 arg); void clear_zcull(context* ctx, u32 reg, u32 arg); @@ -109,7 +118,7 @@ namespace rsx arg = (be_data << 16) | (be_data >> 16); } - util::push_vertex_data(attribute_index, vertex_subreg, count, vtype); + util::push_vertex_data(ctx, attribute_index, vertex_subreg, count, vtype, arg); } template @@ -207,14 +216,9 @@ namespace rsx template struct set_texture_dirty_bit { - static void impl(context* ctx, u32 reg, u32 arg) + static void impl(context* ctx, u32 /*reg*/, u32 /*arg*/) { - RSX(ctx)->m_textures_dirty[index] = true; - - if (RSX(ctx)->current_fp_metadata.referenced_textures_mask & (1 << index)) - { - RSX(ctx)->m_graphics_state |= rsx::pipeline_state::fragment_program_state_dirty; - } + util::set_fragment_texture_dirty_bit(ctx, index); } }; @@ -223,12 +227,7 @@ namespace rsx { static void impl(context* ctx, u32 reg, u32 arg) { - RSX(ctx)->m_vertex_textures_dirty[index] = true; - if (RSX(ctx)->current_vp_metadata.referenced_textures_mask & (1 << index)) - { - RSX(ctx)->m_graphics_state |= rsx::pipeline_state::vertex_program_state_dirty; - } } }; diff --git a/rpcs3/Emu/RSX/NV47/HW/nv47.h b/rpcs3/Emu/RSX/NV47/HW/nv47.h new file mode 100644 index 0000000000..56395f6c28 --- /dev/null +++ b/rpcs3/Emu/RSX/NV47/HW/nv47.h @@ -0,0 +1,8 @@ +// RSX Hardware definitions +#pragma once + +#include "nv0039.h" // Buffer objects +#include "nv3089.h" // Blit engine (2D) +#include "nv308a.h" // Format conversion +#include "nv406e.h" // Sync objects +#include "nv4097.h" // 3D engine (GRAPH) diff --git a/rpcs3/Emu/RSX/NV47/common.h b/rpcs3/Emu/RSX/NV47/HW/nv47_sync.hpp similarity index 72% rename from rpcs3/Emu/RSX/NV47/common.h rename to rpcs3/Emu/RSX/NV47/HW/nv47_sync.hpp index 6fc50edbd1..fe6dc21ba5 100644 --- a/rpcs3/Emu/RSX/NV47/common.h +++ b/rpcs3/Emu/RSX/NV47/HW/nv47_sync.hpp @@ -1,24 +1,16 @@ #pragma once #include -#include "context.h" +#include "Emu/RSX/RSXThread.h" + #include "context_accessors.define.h" namespace rsx { - enum command_barrier_type : u32; - enum vertex_base_type; - namespace util { - u32 get_report_data_impl(rsx::context* ctx, u32 offset); - - void push_vertex_data(rsx::context* ctx, u32 attrib_index, u32 channel_select, int count, rsx::vertex_base_type vtype, u32 value); - - void push_draw_parameter_change(rsx::context* ctx, rsx::command_barrier_type type, u32 reg, u32 arg); - template - void write_gcm_label(context* ctx, u32 address, u32 data) + static void write_gcm_label(context* ctx, u32 address, u32 data) { const bool is_flip_sema = (address == (RSX(ctx)->label_addr + 0x10) || address == (RSX(ctx)->device_addr + 0x30)); if (!is_flip_sema) @@ -56,5 +48,5 @@ namespace rsx } } } - + #include "context_accessors.undef.h" diff --git a/rpcs3/Emu/RSX/NV47/nv47.h b/rpcs3/Emu/RSX/NV47/nv47.h deleted file mode 100644 index 8a27f4d14c..0000000000 --- a/rpcs3/Emu/RSX/NV47/nv47.h +++ /dev/null @@ -1,7 +0,0 @@ -// 3D Engine definitions -#pragma once - -#include "nv3089.h" -#include "nv308a.h" -#include "nv406e.h" -#include "nv4097.h" diff --git a/rpcs3/Emu/RSX/RSXFIFO.cpp b/rpcs3/Emu/RSX/RSXFIFO.cpp index 825bf88e5f..6761124872 100644 --- a/rpcs3/Emu/RSX/RSXFIFO.cpp +++ b/rpcs3/Emu/RSX/RSXFIFO.cpp @@ -7,7 +7,7 @@ #include "Core/RSXReservationLock.hpp" #include "Emu/Memory/vm_reservation.h" #include "Emu/Cell/lv2/sys_rsx.h" -#include "NV47/context.h" +#include "NV47/HW/context.h" #include "util/asm.hpp" @@ -810,9 +810,6 @@ namespace rsx } } - // FIXME: This should be properly managed - rsx::context ctx{ .rsxthr = this, .register_state = &method_registers }; - if (m_flattener.is_enabled()) [[unlikely]] { switch(m_flattener.test(command)) @@ -825,14 +822,14 @@ namespace rsx { // Emit end command to close existing scope AUDIT(in_begin_end); - methods[NV4097_SET_BEGIN_END](&ctx, NV4097_SET_BEGIN_END, 0); + methods[NV4097_SET_BEGIN_END](m_ctx, NV4097_SET_BEGIN_END, 0); break; } case FIFO::EMIT_BARRIER: { AUDIT(in_begin_end); - methods[NV4097_SET_BEGIN_END](&ctx, NV4097_SET_BEGIN_END, 0); - methods[NV4097_SET_BEGIN_END](&ctx, NV4097_SET_BEGIN_END, m_flattener.get_primitive()); + methods[NV4097_SET_BEGIN_END](m_ctx, NV4097_SET_BEGIN_END, 0); + methods[NV4097_SET_BEGIN_END](m_ctx, NV4097_SET_BEGIN_END, m_flattener.get_primitive()); break; } default: @@ -851,19 +848,19 @@ namespace rsx const u32 reg = (command.reg & 0xffff) >> 2; const u32 value = command.value; - ctx.register_state->decode(reg, value); + m_ctx->register_state->decode(reg, value); if (auto method = methods[reg]) { - method(&ctx, reg, value); + method(m_ctx, reg, value); if (state & cpu_flag::again) { - ctx.register_state->decode(reg, ctx.register_state->latch); + m_ctx->register_state->decode(reg, m_ctx->register_state->latch); break; } } - else if (ctx.register_state->latch != value) + else if (m_ctx->register_state->latch != value) { // Something changed, set signal flags if any specified m_graphics_state |= state_signals[reg]; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 0d195a18f2..6b5b984e82 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -27,6 +27,7 @@ #include "Utilities/date_time.h" #include "Utilities/StrUtil.h" #include "Crypto/unzip.h" +#include "NV47/HW/context.h" #include "util/asm.hpp" @@ -122,6 +123,9 @@ namespace rsx { std::function g_access_violation_handler; + // TODO: Proper context manager + static rsx::context s_ctx{ .rsxthr = nullptr, .register_state = &method_registers }; + rsx_iomap_table::rsx_iomap_table() noexcept : ea(fill_array(-1)) , io(fill_array(-1)) @@ -675,6 +679,10 @@ namespace rsx g_user_asked_for_frame_capture = false; + // TODO: Proper context management in the driver + s_ctx.rsxthr = this; + m_ctx = &s_ctx; + if (g_cfg.misc.use_native_interface && (g_cfg.video.renderer == video_renderer::opengl || g_cfg.video.renderer == video_renderer::vulkan)) { m_overlay_manager = g_fxo->init(0); @@ -813,7 +821,7 @@ namespace rsx in_begin_end = false; m_frame_stats.draw_calls++; - method_registers.current_draw_clause.post_execute_cleanup(); + method_registers.current_draw_clause.post_execute_cleanup(m_ctx); m_graphics_state |= rsx::pipeline_state::framebuffer_reads_dirty; m_eng_interrupt_mask |= rsx::backend_interrupt; @@ -848,7 +856,7 @@ namespace rsx method_registers.current_draw_clause.begin(); do { - method_registers.current_draw_clause.execute_pipeline_dependencies(); + method_registers.current_draw_clause.execute_pipeline_dependencies(m_ctx); } while (method_registers.current_draw_clause.next()); } @@ -918,7 +926,7 @@ namespace rsx namespace nv4097 { - void set_render_mode(thread* rsx, u32, u32 arg); + void set_render_mode(context* rsx, u32, u32 arg); } void thread::on_task() @@ -958,7 +966,7 @@ namespace rsx } check_zcull_status(false); - nv4097::set_render_mode(this, 0, method_registers.registers[NV4097_SET_RENDER_ENABLE]); + nv4097::set_render_mode(m_ctx, 0, method_registers.registers[NV4097_SET_RENDER_ENABLE]); performance_counters.state = FIFO::state::empty; @@ -2674,7 +2682,7 @@ namespace rsx { rsx::method_registers.reset(); check_zcull_status(false); - nv4097::set_render_mode(this, 0, method_registers.registers[NV4097_SET_RENDER_ENABLE]); + nv4097::set_render_mode(m_ctx, 0, method_registers.registers[NV4097_SET_RENDER_ENABLE]); m_graphics_state |= pipeline_state::all_dirty; } diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 739c9df5c2..bb8784734a 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -40,6 +40,8 @@ extern rsx::frame_capture_data frame_capture; namespace rsx { + struct context; + namespace overlays { class display_manager; @@ -204,6 +206,9 @@ namespace rsx // Savestates related u32 m_pause_after_x_flips = 0; + // Context + context* m_ctx = nullptr; + public: atomic_t new_get_put = u64{umax}; u32 restore_point = 0; diff --git a/rpcs3/Emu/RSX/VK/VKDraw.cpp b/rpcs3/Emu/RSX/VK/VKDraw.cpp index 164e62e300..0f3a11b794 100644 --- a/rpcs3/Emu/RSX/VK/VKDraw.cpp +++ b/rpcs3/Emu/RSX/VK/VKDraw.cpp @@ -707,7 +707,7 @@ void VKGSRender::emit_geometry(u32 sub_index) m_profiler.start(); const rsx::flags32_t vertex_state_mask = rsx::vertex_base_changed | rsx::vertex_arrays_changed; - const rsx::flags32_t vertex_state = (sub_index == 0) ? rsx::vertex_arrays_changed : draw_call.execute_pipeline_dependencies() & vertex_state_mask; + const rsx::flags32_t vertex_state = (sub_index == 0) ? rsx::vertex_arrays_changed : draw_call.execute_pipeline_dependencies(m_ctx) & vertex_state_mask; if (vertex_state & rsx::vertex_arrays_changed) { @@ -738,7 +738,7 @@ void VKGSRender::emit_geometry(u32 sub_index) // Execute remainining pipeline barriers with NOP draw do { - draw_call.execute_pipeline_dependencies(); + draw_call.execute_pipeline_dependencies(m_ctx); } while (draw_call.next()); diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index 706d07219a..4566a0418f 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -4,14 +4,13 @@ #include "rsx_utils.h" #include "rsx_decode.h" #include "Common/time.hpp" -#include "Common/tiled_dma_copy.hpp" -#include "Core/RSXReservationLock.hpp" #include "Emu/Cell/PPUCallback.h" #include "Emu/Cell/lv2/sys_rsx.h" #include "Emu/RSX/Common/BufferUtils.h" -#include "Emu/RSX/NV47/nv47.h" -#include "Emu/RSX/NV47/context_accessors.define.h" +#include "Emu/RSX/NV47/HW/nv47.h" +#include "Emu/RSX/NV47/HW/nv47_sync.hpp" +#include "Emu/RSX/NV47/HW/context_accessors.define.h" // TODO: Context objects belong in FW not HW namespace rsx { @@ -42,132 +41,7 @@ namespace rsx namespace nv0039 { - void buffer_notify(context* ctx, u32, u32 arg) - { - s32 in_pitch = REGS(ctx)->nv0039_input_pitch(); - s32 out_pitch = REGS(ctx)->nv0039_output_pitch(); - const u32 line_length = REGS(ctx)->nv0039_line_length(); - const u32 line_count = REGS(ctx)->nv0039_line_count(); - const u8 out_format = REGS(ctx)->nv0039_output_format(); - const u8 in_format = REGS(ctx)->nv0039_input_format(); - const u32 notify = arg; - - if (!line_count || !line_length) - { - rsx_log.warning("NV0039_BUFFER_NOTIFY NOPed out: pitch(in=0x%x, out=0x%x), line(len=0x%x, cnt=0x%x), fmt(in=0x%x, out=0x%x), notify=0x%x", - in_pitch, out_pitch, line_length, line_count, in_format, out_format, notify); - return; - } - - rsx_log.trace("NV0039_BUFFER_NOTIFY: pitch(in=0x%x, out=0x%x), line(len=0x%x, cnt=0x%x), fmt(in=0x%x, out=0x%x), notify=0x%x", - in_pitch, out_pitch, line_length, line_count, in_format, out_format, notify); - - u32 src_offset = REGS(ctx)->nv0039_input_offset(); - u32 src_dma = REGS(ctx)->nv0039_input_location(); - - u32 dst_offset = REGS(ctx)->nv0039_output_offset(); - u32 dst_dma = REGS(ctx)->nv0039_output_location(); - - const bool is_block_transfer = (in_pitch == out_pitch && out_pitch + 0u == line_length); - const auto read_address = get_address(src_offset, src_dma); - const auto write_address = get_address(dst_offset, dst_dma); - const auto read_length = in_pitch * (line_count - 1) + line_length; - const auto write_length = out_pitch * (line_count - 1) + line_length; - - RSX(ctx)->invalidate_fragment_program(dst_dma, dst_offset, write_length); - - if (const auto result = RSX(ctx)->read_barrier(read_address, read_length, !is_block_transfer); - result == rsx::result_zcull_intr) - { - // This transfer overlaps will zcull data pool - if (RSX(ctx)->copy_zcull_stats(read_address, read_length, write_address) == write_length) - { - // All writes deferred - return; - } - } - - auto res = ::rsx::reservation_lock(write_address, write_length, read_address, read_length); - - u8 *dst = vm::_ptr(write_address); - const u8 *src = vm::_ptr(read_address); - - const bool is_overlapping = dst_dma == src_dma && [&]() -> bool - { - const u32 src_max = src_offset + read_length; - const u32 dst_max = dst_offset + (out_pitch * (line_count - 1) + line_length); - return (src_offset >= dst_offset && src_offset < dst_max) || - (dst_offset >= src_offset && dst_offset < src_max); - }(); - - if (in_format > 1 || out_format > 1) [[ unlikely ]] - { - // The formats are just input channel strides. You can use this to do cool tricks like gathering channels - // Very rare, only seen in use by Destiny - // TODO: Hw accel - for (u32 row = 0; row < line_count; ++row) - { - auto dst_ptr = dst; - auto src_ptr = src; - while (src_ptr < src + line_length) - { - *dst_ptr = *src_ptr; - - src_ptr += in_format; - dst_ptr += out_format; - } - - dst += out_pitch; - src += in_pitch; - } - } - else if (is_overlapping) [[ unlikely ]] - { - if (is_block_transfer) - { - std::memmove(dst, src, read_length); - } - else - { - std::vector temp(line_length * line_count); - u8* buf = temp.data(); - - for (u32 y = 0; y < line_count; ++y) - { - std::memcpy(buf, src, line_length); - buf += line_length; - src += in_pitch; - } - - buf = temp.data(); - - for (u32 y = 0; y < line_count; ++y) - { - std::memcpy(dst, buf, line_length); - buf += line_length; - dst += out_pitch; - } - } - } - else - { - if (is_block_transfer) - { - std::memcpy(dst, src, read_length); - } - else - { - for (u32 i = 0; i < line_count; ++i) - { - std::memcpy(dst, src, line_length); - dst += out_pitch; - src += in_pitch; - } - } - } - - //res->release(0); - } + } void flip_command(context* ctx, u32, u32 arg) @@ -1414,7 +1288,7 @@ namespace rsx is_disjoint_primitive = is_primitive_disjointed(primitive); } - u32 draw_clause::execute_pipeline_dependencies() const + u32 draw_clause::execute_pipeline_dependencies(context* ctx) const { u32 result = 0; @@ -1974,7 +1848,8 @@ namespace rsx // FIFO bind(FIFO::FIFO_DRAW_BARRIER >> 2, fifo::draw_barrier); - REGS(ctx)->init(); + // REGS(ctx)->init(); + method_registers.init(); return true; }(); diff --git a/rpcs3/Emu/RSX/rsx_methods.h b/rpcs3/Emu/RSX/rsx_methods.h index fd3db6dcfc..d245a443e3 100644 --- a/rpcs3/Emu/RSX/rsx_methods.h +++ b/rpcs3/Emu/RSX/rsx_methods.h @@ -10,372 +10,11 @@ #include "Emu/Cell/timers.hpp" #include "Program/program_util.h" +#include "NV47/FW/draw_call.hpp" + namespace rsx { - enum class draw_command - { - none, - array, - inlined_array, - indexed, - }; - - enum command_barrier_type : u32 - { - primitive_restart_barrier, - vertex_base_modifier_barrier, - index_base_modifier_barrier, - vertex_array_offset_modifier_barrier - }; - - enum command_execution_flags : u32 - { - vertex_base_changed = (1 << 0), - index_base_changed = (1 << 1), - vertex_arrays_changed = (1 << 2), - }; - - enum class primitive_class - { - polygon, - non_polygon - }; - - struct barrier_t - { - u32 draw_id; - u64 timestamp; - - u32 address; - u32 index; - u32 arg; - u32 flags; - command_barrier_type type; - - bool operator < (const barrier_t& other) const - { - if (address != ~0u) - { - return address < other.address; - } - - return timestamp < other.timestamp; - } - - ENABLE_BITWISE_SERIALIZATION; - }; - - struct draw_range_t - { - u32 command_data_offset = 0; - u32 first = 0; - u32 count = 0; - - ENABLE_BITWISE_SERIALIZATION; - }; - - class draw_clause - { - // Stores the first and count argument from draw/draw indexed parameters between begin/end clauses. - simple_array draw_command_ranges{}; - - // Stores rasterization barriers for primitive types sensitive to adjacency - simple_array draw_command_barriers{}; - - // Counter used to parse the commands in order - u32 current_range_index{}; - - // Location of last execution barrier - u32 last_execution_barrier_index{}; - - // Helper functions - // Add a new draw command - void append_draw_command(const draw_range_t& range) - { - current_range_index = draw_command_ranges.size(); - draw_command_ranges.push_back(range); - } - - // Insert a new draw command within the others - void insert_draw_command(u32 index, const draw_range_t& range) - { - auto range_It = draw_command_ranges.begin(); - std::advance(range_It, index); - - current_range_index = index; - draw_command_ranges.insert(range_It, range); - - // Update all barrier draw ids after this one - for (auto &barrier : draw_command_barriers) - { - if (barrier.draw_id >= index) - { - barrier.draw_id++; - } - } - } - - public: - primitive_type primitive{}; - draw_command command{}; - - bool is_immediate_draw{}; // Set if part of the draw is submitted via push registers - bool is_disjoint_primitive{}; // Set if primitive type does not rely on adjacency information - bool primitive_barrier_enable{}; // Set once to signal that a primitive restart barrier can be inserted - - simple_array inline_vertex_array{}; - - void operator()(utils::serial& ar); - - void insert_command_barrier(command_barrier_type type, u32 arg, u32 register_index = 0); - - /** - * Optimize commands for rendering - */ - void compile() - { - // End draw call append mode - current_range_index = ~0u; - - // TODO - } - - /** - * Insert one command range - */ - - void append(u32 first, u32 count) - { - const bool barrier_enable_flag = primitive_barrier_enable; - primitive_barrier_enable = false; - - if (!draw_command_ranges.empty()) - { - auto& last = draw_command_ranges[current_range_index]; - - if (last.count == 0) - { - // Special case, usually indicates an execution barrier - last.first = first; - last.count = count; - return; - } - - if (last.first + last.count == first) - { - if (!is_disjoint_primitive && barrier_enable_flag) - { - // Insert barrier - insert_command_barrier(primitive_restart_barrier, 0); - } - - last.count += count; - return; - } - - for (auto index = last_execution_barrier_index; index < draw_command_ranges.size(); ++index) - { - if (draw_command_ranges[index].first == first && - draw_command_ranges[index].count == count) - { - // Duplicate entry? WTF! - return; - } - - if (draw_command_ranges[index].first > first) - { - insert_draw_command(index, { 0, first, count }); - return; - } - } - } - - append_draw_command({ 0, first, count }); - } - - /** - * Returns how many vertex or index will be consumed by the draw clause. - */ - u32 get_elements_count() const - { - if (draw_command_ranges.empty()) - { - ensure(command == rsx::draw_command::inlined_array); - return 0; - } - - return get_range().count; - } - - u32 min_index() const - { - if (draw_command_ranges.empty()) - { - ensure(command == rsx::draw_command::inlined_array); - return 0; - } - - return get_range().first; - } - - bool is_single_draw() const - { - if (is_disjoint_primitive) - return true; - - if (draw_command_ranges.empty()) - { - ensure(!inline_vertex_array.empty()); - return true; - } - - ensure(current_range_index != ~0u); - for (const auto &barrier : draw_command_barriers) - { - if (barrier.draw_id != current_range_index) - continue; - - if (barrier.type == primitive_restart_barrier) - return false; - } - - return true; - } - - bool empty() const - { - return (command == rsx::draw_command::inlined_array) ? inline_vertex_array.empty() : draw_command_ranges.empty(); - } - - u32 pass_count() const - { - if (draw_command_ranges.empty()) - { - ensure(!inline_vertex_array.empty()); - return 1u; - } - - u32 count = ::size32(draw_command_ranges); - if (draw_command_ranges.back().count == 0) - { - // Dangling barrier - ensure(count > 1); - count--; - } - - return count; - } - - primitive_class classify_mode() const - { - return primitive >= rsx::primitive_type::triangles - ? primitive_class::polygon - : primitive_class::non_polygon; - } - - - void reset(rsx::primitive_type type); - - void begin() - { - current_range_index = 0; - } - - void end() - { - current_range_index = draw_command_ranges.size() - 1; - } - - bool next() - { - current_range_index++; - if (current_range_index >= draw_command_ranges.size()) - { - current_range_index = 0; - return false; - } - - if (draw_command_ranges[current_range_index].count == 0) - { - // Dangling execution barrier - ensure(current_range_index > 0 && (current_range_index + 1) == draw_command_ranges.size()); - current_range_index = 0; - return false; - } - - return true; - } - - /** - * Only call this once after the draw clause has been fully consumed to reconcile any conflicts - */ - void post_execute_cleanup() - { - ensure(current_range_index == 0); - - if (draw_command_ranges.size() > 1) - { - if (draw_command_ranges.back().count == 0) - { - // Dangling execution barrier - current_range_index = draw_command_ranges.size() - 1; - execute_pipeline_dependencies(); - current_range_index = 0; - } - } - } - - /** - * Executes commands reqiured to make the current draw state valid - */ - u32 execute_pipeline_dependencies() const; - - const draw_range_t& get_range() const - { - ensure(current_range_index < draw_command_ranges.size()); - return draw_command_ranges[current_range_index]; - } - - simple_array get_subranges() const - { - ensure(!is_single_draw()); - - const auto range = get_range(); - const auto limit = range.first + range.count; - - simple_array ret; - u32 previous_barrier = range.first; - u32 vertex_counter = 0; - - for (const auto &barrier : draw_command_barriers) - { - if (barrier.draw_id != current_range_index) - continue; - - if (barrier.type != primitive_restart_barrier) - continue; - - if (barrier.address <= range.first) - continue; - - if (barrier.address >= limit) - break; - - const u32 count = barrier.address - previous_barrier; - ret.push_back({ 0, vertex_counter, count }); - previous_barrier = barrier.address; - vertex_counter += count; - } - - ensure(!ret.empty()); - ensure(previous_barrier < limit); - ret.push_back({ 0, vertex_counter, limit - previous_barrier }); - - return ret; - } - }; - - using rsx_method_t = void(*)(class context*, u32 reg, u32 arg); + using rsx_method_t = void(*)(struct context*, u32 reg, u32 arg); //TODO union alignas(4) method_registers_t diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 20d40bc3a2..600b076202 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -95,11 +95,13 @@ - - - - - + + + + + + + @@ -589,15 +591,20 @@ - - - - - - - - - + + + + + + + + + + + + + + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 12889ce92d..2c817b8acf 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -100,6 +100,12 @@ {213387bd-09c5-4247-8fb0-b3cae06ba34b} + + {24fc03a5-0469-4b6e-89df-44459e51855f} + + + {fdb8ff8f-5a03-45a2-8c0a-16a89b7a574b} + @@ -1213,20 +1219,26 @@ Emu\GPU\RSX\Program - - Emu\GPU\RSX\NV47 + + Emu\GPU\RSX\NV47\HW - - Emu\GPU\RSX\NV47 + + Emu\GPU\RSX\NV47\HW - - Emu\GPU\RSX\NV47 + + Emu\GPU\RSX\NV47\HW - - Emu\GPU\RSX\NV47 + + Emu\GPU\RSX\NV47\HW - - Emu\GPU\RSX\NV47 + + Emu\GPU\RSX\NV47\HW + + + Emu\GPU\RSX\NV47\HW + + + Emu\GPU\RSX\NV47\FW @@ -2467,32 +2479,47 @@ Emu\GPU\RSX\Program - - Emu\GPU\RSX\NV47 + + Emu\GPU\RSX\NV47\HW - - Emu\GPU\RSX\NV47 + + Emu\GPU\RSX\NV47\HW - - Emu\GPU\RSX\NV47 + + Emu\GPU\RSX\NV47\HW - - Emu\GPU\RSX\NV47 + + Emu\GPU\RSX\NV47\HW - - Emu\GPU\RSX\NV47 + + Emu\GPU\RSX\NV47\HW - - Emu\GPU\RSX\NV47 + + Emu\GPU\RSX\NV47\HW - - Emu\GPU\RSX\NV47 + + Emu\GPU\RSX\NV47\HW - - Emu\GPU\RSX\NV47 + + Emu\GPU\RSX\NV47\HW - - Emu\GPU\RSX\NV47 + + Emu\GPU\RSX\NV47\HW + + + Emu\GPU\RSX\NV47\HW + + + Emu\GPU\RSX\NV47\HW + + + Emu\GPU\RSX\NV47\FW + + + Emu\GPU\RSX\NV47\FW + + + Emu\GPU\RSX\NV47\FW