diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp index 4e44fd18f4..c53b8c0f67 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp @@ -59,6 +59,19 @@ namespace return vertex_buffer_view; } + D3D12_SHADER_RESOURCE_VIEW_DESC get_vertex_attribute_srv(const rsx::vertex_base_type type, u8 size, UINT64 offset_in_vertex_buffers_buffer, UINT buffer_size) + { + u32 element_size = rsx::get_vertex_type_size_on_host(type, size); + D3D12_SHADER_RESOURCE_VIEW_DESC vertex_buffer_view = { + get_vertex_attribute_format(type, size), + D3D12_SRV_DIMENSION_BUFFER, + get_component_mapping_from_vector_size(size) + }; + vertex_buffer_view.Buffer.FirstElement = offset_in_vertex_buffers_buffer / element_size; + vertex_buffer_view.Buffer.NumElements = buffer_size / element_size; + return vertex_buffer_view; + } + template UINT64 get_next_multiple_of(UINT64 val) { @@ -120,20 +133,19 @@ std::vector D3D12GSRender::upload_vertex_attrib else if (rsx::method_registers.register_vertex_info[index].size > 0) { // In register vertex attribute - const rsx::data_array_format_info &info = rsx::method_registers.register_vertex_info[index]; - const std::vector &data = rsx::method_registers.register_vertex_data[index]; + const rsx::register_vertex_data_info &info = rsx::method_registers.register_vertex_info[index]; u32 element_size = rsx::get_vertex_type_size_on_host(info.type, info.size); - UINT buffer_size = gsl::narrow(data.size()); + UINT buffer_size = element_size; size_t heap_offset = m_buffer_data.alloc(buffer_size); void *mapped_buffer = m_buffer_data.map(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size)); - memcpy(mapped_buffer, data.data(), data.size()); + memcpy(mapped_buffer, info.data.data(), buffer_size); m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size)); command_list->CopyBufferRegion(m_vertex_buffer_data.Get(), offset_in_vertex_buffers_buffer, m_buffer_data.get_heap(), heap_offset, buffer_size); - vertex_buffer_views.emplace_back(get_vertex_attribute_srv(info, offset_in_vertex_buffers_buffer, buffer_size)); + vertex_buffer_views.emplace_back(get_vertex_attribute_srv(info.type, info.size, offset_in_vertex_buffers_buffer, buffer_size)); offset_in_vertex_buffers_buffer = get_next_multiple_of<48>(offset_in_vertex_buffers_buffer + buffer_size); // 48 is multiple of 2, 4, 6, 8, 12, 16 } } diff --git a/rpcs3/Emu/RSX/GL/vertex_buffer.cpp b/rpcs3/Emu/RSX/GL/vertex_buffer.cpp index 2d8c9840d3..0f6c5f83b5 100644 --- a/rpcs3/Emu/RSX/GL/vertex_buffer.cpp +++ b/rpcs3/Emu/RSX/GL/vertex_buffer.cpp @@ -388,7 +388,6 @@ u32 GLGSRender::set_vertex_buffer() } else if (rsx::method_registers.register_vertex_info[index].size > 0) { - auto &vertex_data = rsx::method_registers.register_vertex_data[index]; auto &vertex_info = rsx::method_registers.register_vertex_info[index]; switch (vertex_info.type) @@ -397,14 +396,14 @@ u32 GLGSRender::set_vertex_buffer() { const u32 element_size = rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size); const u32 gl_type = to_gl_internal_type(vertex_info.type, vertex_info.size); - const size_t data_size = vertex_data.size(); + const size_t data_size = element_size; auto &texture = m_gl_attrib_buffers[index]; auto mapping = m_attrib_ring_buffer.alloc_from_reserve(data_size, m_min_texbuffer_alignment); u8 *dst = static_cast(mapping.first); - memcpy(dst, vertex_data.data(), data_size); + memcpy(dst, vertex_info.data.data(), element_size); texture.copy_from(m_attrib_ring_buffer, gl_type, mapping.second, data_size); //Link texture to uniform diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 17c93f50fe..cee265b43c 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -354,7 +354,6 @@ namespace rsx for (u8 index = 0; index < rsx::limits::vertex_count; ++index) { rsx::method_registers.register_vertex_info[index].size = 0; - rsx::method_registers.register_vertex_data[index].clear(); } if (capture_current_frame) diff --git a/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp b/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp index cedf1200aa..94555ff16a 100644 --- a/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp +++ b/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp @@ -508,18 +508,17 @@ VKGSRender::upload_vertex_data() else if (rsx::method_registers.register_vertex_info[index].size > 0) { //Untested! - auto &vertex_data = rsx::method_registers.register_vertex_data[index]; auto &vertex_info = rsx::method_registers.register_vertex_info[index]; switch (vertex_info.type) { case rsx::vertex_base_type::f: { - size_t data_size = vertex_data.size(); + size_t data_size = rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size); const VkFormat format = vk::get_suitable_vk_format(vertex_info.type, vertex_info.size); u32 offset_in_attrib_buffer = 0; - void *data_ptr = vertex_data.data(); + void *data_ptr = vertex_info.data.data(); if (vk::requires_component_expansion(vertex_info.type, vertex_info.size)) { @@ -530,14 +529,14 @@ VKGSRender::upload_vertex_data() offset_in_attrib_buffer = m_attrib_ring_info.alloc<256>(data_size); void *dst = m_attrib_ring_info.map(offset_in_attrib_buffer, data_size); - vk::expand_array_components(reinterpret_cast(vertex_data.data()), dst, num_stored_verts); + vk::expand_array_components(reinterpret_cast(vertex_info.data.data()), dst, num_stored_verts); m_attrib_ring_info.unmap(); } else { offset_in_attrib_buffer = m_attrib_ring_info.alloc<256>(data_size); void *dst = m_attrib_ring_info.map(offset_in_attrib_buffer, data_size); - memcpy(dst, vertex_data.data(), data_size); + memcpy(dst, vertex_info.data.data(), data_size); m_attrib_ring_info.unmap(); } diff --git a/rpcs3/Emu/RSX/rsx_decode.h b/rpcs3/Emu/RSX/rsx_decode.h index 4f68909204..aafc5606fb 100644 --- a/rpcs3/Emu/RSX/rsx_decode.h +++ b/rpcs3/Emu/RSX/rsx_decode.h @@ -85,6 +85,21 @@ namespace subreg == 2 ? "z" : "w"; } + + std::string print_vertex_attribute_format(rsx::vertex_base_type type) + { + switch (type) + { + case rsx::vertex_base_type::s1: return "Signed short normalized"; + case rsx::vertex_base_type::f: return "Float"; + case rsx::vertex_base_type::sf: return "Half float"; + case rsx::vertex_base_type::ub: return "Unsigned byte normalized"; + case rsx::vertex_base_type::s32k: return "Signed short unormalized"; + case rsx::vertex_base_type::cmp: return "CMP"; + case rsx::vertex_base_type::ub256: return "Unsigned byte unormalized"; + } + throw; + } } namespace rsx @@ -2318,6 +2333,172 @@ struct registers_decoder #define DECLARE_TRANSFORM_PROGRAM(index) NV4097_SET_TRANSFORM_PROGRAM + index, EXPAND_RANGE_512(0, TRANSFORM_PROGRAM) +template +struct vertex_array_helper +{ + static auto decode(u32 value) + { + u16 frequency = value >> 16; + u8 stride = (value >> 8) & 0xff; + u8 size = (value >> 4) & 0xf; + rsx::vertex_base_type type = rsx::to_vertex_base_type(value & 0xf); + return std::make_tuple(frequency, stride, size, type); + } + + static void commit_rsx_state(rsx::rsx_state &state, std::tuple &&decoded_values) + { + state.vertex_arrays_info[index].frequency = std::get<0>(decoded_values); + state.vertex_arrays_info[index].stride = std::get<1>(decoded_values); + state.vertex_arrays_info[index].size = std::get<2>(decoded_values); + state.vertex_arrays_info[index].type = std::get<3>(decoded_values); + } + + static std::string dump(std::tuple &&decoded_values) + { + if (std::get<2>(decoded_values) == 0) + return "(disabled)"; + + return "Vertex array " + std::to_string(index) + ": Type = " + print_vertex_attribute_format(std::get<3>(decoded_values)) + + " size = " + std::to_string(std::get<2>(decoded_values)) + + " stride = " + std::to_string(std::get<1>(decoded_values)) + + " frequency = " + std::to_string(std::get<0>(decoded_values)); + } +}; + +#define VERTEX_DATA_ARRAY_FORMAT(index) template<> struct registers_decoder : public vertex_array_helper {}; +#define DECLARE_VERTEX_DATA_ARRAY_FORMAT(index) NV4097_SET_VERTEX_DATA_ARRAY_FORMAT + index, + +EXPAND_RANGE_16(0, VERTEX_DATA_ARRAY_FORMAT) + +template +struct vertex_array_offset_helper +{ + static auto decode(u32 value) + { + return value; + } + + static void commit_rsx_state(rsx::rsx_state &state, u32 &&decoded_values) + { + state.vertex_arrays_info[index].m_offset = decoded_values; + } + + static std::string dump(u32 &&decoded_values) + { + return "Vertex array " + std::to_string(index) + ": Offset = " + std::to_string(decoded_values); + } +}; + +#define VERTEX_DATA_ARRAY_OFFSET(index) template<> struct registers_decoder : public vertex_array_offset_helper {}; +#define DECLARE_VERTEX_DATA_ARRAY_OFFSET(index) NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + index, + +EXPAND_RANGE_16(0, VERTEX_DATA_ARRAY_OFFSET) + +template struct vertex_data_type_from_element_type; +template<> struct vertex_data_type_from_element_type { static constexpr rsx::vertex_base_type type = rsx::vertex_base_type::f; }; +template<> struct vertex_data_type_from_element_type { static constexpr rsx::vertex_base_type type = rsx::vertex_base_type::sf; }; +template<> struct vertex_data_type_from_element_type { static constexpr rsx::vertex_base_type type = rsx::vertex_base_type::ub; }; +template<> struct vertex_data_type_from_element_type { static constexpr rsx::vertex_base_type type = rsx::vertex_base_type::s1; }; + +template +struct vertex_type_namer; + +template +struct vertex_type_namer +{ + static std::string get() + { + return "float" + std::to_string(count); + } +}; + +template +struct vertex_type_namer +{ + static std::string get() + { + return "short" + std::to_string(count); + } +}; + +template<> +struct vertex_type_namer +{ + static std::string get() + { + return "uchar4"; + } +}; + +template +struct register_vertex_helper +{ + static auto decode(u32 value) + { + return value; + } + + static const size_t increment_per_array_index = (count * sizeof(type)) / sizeof(u32); + + static const size_t attribute_index = index / increment_per_array_index; + static const size_t vertex_subreg = index % increment_per_array_index; + + static void commit_rsx_state(rsx::rsx_state &state, u32 &&decoded_values) + { + auto& info = state.register_vertex_info[attribute_index]; + + info.type = vertex_data_type_from_element_type::type; + info.size = count; + info.frequency = 0; + info.stride = 0; + state.register_vertex_info[attribute_index].data[vertex_subreg] = decoded_values; + } + + static std::string dump(u32&& decoded_values) + { + return "register vertex " + std::to_string(attribute_index) + " as " + vertex_type_namer::get() + ": " + + std::to_string(decoded_values); + } +}; + +#define VERTEX_DATA4UB(index) \ + template<> struct registers_decoder : public register_vertex_helper {}; +#define VERTEX_DATA1F(index) \ + template<> struct registers_decoder : public register_vertex_helper {}; +#define VERTEX_DATA2F(index) \ + template<> struct registers_decoder : public register_vertex_helper {}; +#define VERTEX_DATA3F(index) \ + template<> struct registers_decoder : public register_vertex_helper {}; +#define VERTEX_DATA4F(index) \ + template<> struct registers_decoder : public register_vertex_helper {}; +#define VERTEX_DATA2S(index) \ + template<> struct registers_decoder : public register_vertex_helper {}; +#define VERTEX_DATA4S(index) \ + template<> struct registers_decoder : public register_vertex_helper {}; + +#define DECLARE_VERTEX_DATA4UB(index) \ + NV4097_SET_VERTEX_DATA4UB_M + index, +#define DECLARE_VERTEX_DATA1F(index) \ + NV4097_SET_VERTEX_DATA1F_M + index, +#define DECLARE_VERTEX_DATA2F(index) \ + NV4097_SET_VERTEX_DATA2F_M + index, +#define DECLARE_VERTEX_DATA3F(index) \ + NV4097_SET_VERTEX_DATA3F_M + index, +#define DECLARE_VERTEX_DATA4F(index) \ + NV4097_SET_VERTEX_DATA4F_M + index, +#define DECLARE_VERTEX_DATA2S(index) \ + NV4097_SET_VERTEX_DATA2S_M + index, +#define DECLARE_VERTEX_DATA4S(index) \ + NV4097_SET_VERTEX_DATA4S_M + index, + +EXPAND_RANGE_16(0, VERTEX_DATA4UB) +EXPAND_RANGE_16(0, VERTEX_DATA1F) +EXPAND_RANGE_16(0, VERTEX_DATA2F) +EXPAND_RANGE_16(0, VERTEX_DATA3F) +EXPAND_RANGE_16(0, VERTEX_DATA4F) +EXPAND_RANGE_16(0, VERTEX_DATA2S) +EXPAND_RANGE_16(0, VERTEX_DATA4S) + constexpr std::integer_sequence opcode_list{}; - } // end namespace rsx diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index 353f6f3a17..b611e9e132 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -26,12 +26,6 @@ namespace rsx rsx_state method_registers; rsx_method_t methods[0x10000 >> 2]{}; - 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::s1; }; - namespace nv406e { force_inline void set_reference(thread* rsx, u32 arg) @@ -73,104 +67,6 @@ namespace rsx (arg & 0xff00ff00) | ((arg & 0xff) << 16) | ((arg >> 16) & 0xff)); } - //fire only when all data passed to rsx cmd buffer - template - force_inline void set_vertex_data_impl(thread* rsx, u32 arg) - { - static const size_t element_size = (count * sizeof(type)); - static const size_t element_size_in_words = element_size / sizeof(u32); - - auto& info = rsx::method_registers.register_vertex_info[index]; - - info.type = vertex_data_type_from_element_type::type; - info.size = count; - info.frequency = 0; - info.stride = 0; - - auto& entry = rsx::method_registers.register_vertex_data[index]; - - //find begin of data - size_t begin = id + index * element_size_in_words; - - size_t position = entry.size(); - entry.resize(position + element_size); - - memcpy(entry.data() + position, &method_registers[begin], element_size); - } - - template - struct set_vertex_data4ub_m - { - force_inline static void impl(thread* rsx, u32 arg) - { - set_vertex_data_impl(rsx, arg); - } - }; - - template - struct set_vertex_data1f_m - { - force_inline static void impl(thread* rsx, u32 arg) - { - set_vertex_data_impl(rsx, arg); - } - }; - - template - struct set_vertex_data2f_m - { - force_inline static void impl(thread* rsx, u32 arg) - { - set_vertex_data_impl(rsx, arg); - } - }; - - template - struct set_vertex_data3f_m - { - force_inline static void impl(thread* rsx, u32 arg) - { - set_vertex_data_impl(rsx, arg); - } - }; - - template - struct set_vertex_data4f_m - { - force_inline static void impl(thread* rsx, u32 arg) - { - set_vertex_data_impl(rsx, arg); - } - }; - - template - struct set_vertex_data2s_m - { - force_inline static void impl(thread* rsx, u32 arg) - { - set_vertex_data_impl(rsx, arg); - } - }; - - template - struct set_vertex_data4s_m - { - force_inline static void impl(thread* rsx, u32 arg) - { - set_vertex_data_impl(rsx, arg); - } - }; - - template - struct set_vertex_data_array_format - { - force_inline static void impl(thread* rsx, u32 arg) - { - auto& info = rsx::method_registers.vertex_arrays_info[index]; - info.unpack_array(arg); - } - }; - force_inline void draw_arrays(thread* rsx, u32 arg) { rsx->draw_command = rsx::draw_command::array; @@ -221,10 +117,8 @@ namespace rsx if (vertex_info.size > 0) { - auto &vertex_data = rsx::method_registers.register_vertex_data[index]; - u32 element_size = rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size); - u32 element_count = vertex_data.size() / element_size; + u32 element_count = vertex_info.size; vertex_info.frequency = element_count; @@ -763,9 +657,7 @@ namespace rsx rsx_state::rsx_state() : fragment_textures(fill_array(registers, std::make_index_sequence<16>())), - vertex_textures(fill_array(registers, std::make_index_sequence<4>())), - register_vertex_info(fill_array(registers, std::make_index_sequence<16>())), - vertex_arrays_info(fill_array(registers, std::make_index_sequence<16>())) + vertex_textures(fill_array(registers, std::make_index_sequence<4>())) { } @@ -1033,14 +925,6 @@ namespace bind(); bind(); bind(); - bind_range(); - bind_range(); - bind_range(); - bind_range(); - bind_range(); - bind_range(); - bind_range(); - bind_range(); bind_range(); bind_cpu_only(); bind_cpu_only(); diff --git a/rpcs3/Emu/RSX/rsx_methods.h b/rpcs3/Emu/RSX/rsx_methods.h index 4d44f2e563..b27c733091 100644 --- a/rpcs3/Emu/RSX/rsx_methods.h +++ b/rpcs3/Emu/RSX/rsx_methods.h @@ -101,23 +101,12 @@ namespace rsx * Note that behavior when both vertex array and immediate value system are disabled but vertex attrib mask * request inputs is unknown. */ - std::array register_vertex_info; - std::array, 16> register_vertex_data; + std::array register_vertex_info; std::array vertex_arrays_info; rsx_state(); ~rsx_state(); - u32& operator[](size_t idx) - { - return registers[idx]; - } - - const u32& operator[](size_t idx) const - { - return registers[idx]; - } - void decode(u32 reg, u32 value); void reset(); diff --git a/rpcs3/Emu/RSX/rsx_vertex_data.h b/rpcs3/Emu/RSX/rsx_vertex_data.h index 2b6cf55e07..62598327cc 100644 --- a/rpcs3/Emu/RSX/rsx_vertex_data.h +++ b/rpcs3/Emu/RSX/rsx_vertex_data.h @@ -8,33 +8,30 @@ namespace rsx struct data_array_format_info { -private: - u8 index; - std::array ®isters; -public: + u16 frequency = 0; + u8 stride = 0; + u8 size = 0; + vertex_base_type type = vertex_base_type::f; + u32 m_offset; + + data_array_format_info() {} + + u32 offset() const + { + return m_offset; + } +}; + +struct register_vertex_data_info +{ u16 frequency = 0; u8 stride = 0; u8 size = 0; vertex_base_type type = vertex_base_type::f; + register_vertex_data_info() {} + std::array data; - data_array_format_info(u8 idx, std::array &r) : index(idx), registers(r) - {} - - data_array_format_info() = delete; - - void unpack_array(u32 data_array_format) - { - frequency = data_array_format >> 16; - stride = (data_array_format >> 8) & 0xff; - size = (data_array_format >> 4) & 0xf; - type = to_vertex_base_type(data_array_format & 0xf); - } - - u32 offset() const - { - return registers[NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + index]; - } }; }