diff options
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 7 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 2 | ||||
| -rw-r--r-- | src/video_core/macro/macro_hle.cpp | 20 | ||||
| -rw-r--r-- | src/video_core/memory_manager.cpp | 53 | ||||
| -rw-r--r-- | src/video_core/memory_manager.h | 2 |
5 files changed, 74 insertions, 10 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index b998a8e69..a0dd7400d 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -179,6 +179,13 @@ u32 Maxwell3D::GetMaxCurrentVertices() { | |||
| 179 | return num_vertices; | 179 | return num_vertices; |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | size_t Maxwell3D::EstimateIndexBufferSize() { | ||
| 183 | GPUVAddr start_address = regs.index_buffer.StartAddress(); | ||
| 184 | GPUVAddr end_address = regs.index_buffer.EndAddress(); | ||
| 185 | return std::min<size_t>(memory_manager.GetMemoryLayoutSize(start_address), | ||
| 186 | static_cast<size_t>(end_address - start_address)); | ||
| 187 | } | ||
| 188 | |||
| 182 | u32 Maxwell3D::ProcessShadowRam(u32 method, u32 argument) { | 189 | u32 Maxwell3D::ProcessShadowRam(u32 method, u32 argument) { |
| 183 | // Keep track of the register value in shadow_state when requested. | 190 | // Keep track of the register value in shadow_state when requested. |
| 184 | const auto control = shadow_state.shadow_ram_control; | 191 | const auto control = shadow_state.shadow_ram_control; |
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index e2256594d..cfe1e4883 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -3077,6 +3077,8 @@ public: | |||
| 3077 | 3077 | ||
| 3078 | u32 GetMaxCurrentVertices(); | 3078 | u32 GetMaxCurrentVertices(); |
| 3079 | 3079 | ||
| 3080 | size_t EstimateIndexBufferSize(); | ||
| 3081 | |||
| 3080 | /// Handles a write to the CLEAR_BUFFERS register. | 3082 | /// Handles a write to the CLEAR_BUFFERS register. |
| 3081 | void ProcessClearBuffers(u32 layer_count); | 3083 | void ProcessClearBuffers(u32 layer_count); |
| 3082 | 3084 | ||
diff --git a/src/video_core/macro/macro_hle.cpp b/src/video_core/macro/macro_hle.cpp index 79fab96e1..93b6d42a4 100644 --- a/src/video_core/macro/macro_hle.cpp +++ b/src/video_core/macro/macro_hle.cpp | |||
| @@ -163,12 +163,16 @@ public: | |||
| 163 | maxwell3d.RefreshParameters(); | 163 | maxwell3d.RefreshParameters(); |
| 164 | minimum_limit = std::max(parameters[3], minimum_limit); | 164 | minimum_limit = std::max(parameters[3], minimum_limit); |
| 165 | } | 165 | } |
| 166 | 166 | const u32 estimate = static_cast<u32>(maxwell3d.EstimateIndexBufferSize()); | |
| 167 | const u32 base_vertex = parameters[8]; | 167 | const u32 base_size = std::max(minimum_limit, estimate); |
| 168 | const u32 base_instance = parameters[9]; | 168 | const u32 element_base = parameters[4]; |
| 169 | maxwell3d.regs.vertex_id_base = base_vertex; | 169 | const u32 base_instance = parameters[5]; |
| 170 | maxwell3d.regs.index_buffer.first = 0; | ||
| 171 | maxwell3d.regs.index_buffer.count = base_size; // Use a fixed size, just for mapping | ||
| 172 | maxwell3d.regs.draw.topology.Assign(topology); | ||
| 173 | maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | ||
| 170 | maxwell3d.CallMethod(0x8e3, 0x640, true); | 174 | maxwell3d.CallMethod(0x8e3, 0x640, true); |
| 171 | maxwell3d.CallMethod(0x8e4, base_vertex, true); | 175 | maxwell3d.CallMethod(0x8e4, element_base, true); |
| 172 | maxwell3d.CallMethod(0x8e5, base_instance, true); | 176 | maxwell3d.CallMethod(0x8e5, base_instance, true); |
| 173 | auto& params = maxwell3d.draw_manager->GetIndirectParams(); | 177 | auto& params = maxwell3d.draw_manager->GetIndirectParams(); |
| 174 | params.is_indexed = true; | 178 | params.is_indexed = true; |
| @@ -179,7 +183,7 @@ public: | |||
| 179 | params.max_draw_counts = 1; | 183 | params.max_draw_counts = 1; |
| 180 | params.stride = 0; | 184 | params.stride = 0; |
| 181 | maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | 185 | maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; |
| 182 | maxwell3d.draw_manager->DrawIndexedIndirect(topology, 0, minimum_limit); | 186 | maxwell3d.draw_manager->DrawIndexedIndirect(topology, 0, base_size); |
| 183 | maxwell3d.CallMethod(0x8e3, 0x640, true); | 187 | maxwell3d.CallMethod(0x8e3, 0x640, true); |
| 184 | maxwell3d.CallMethod(0x8e4, 0x0, true); | 188 | maxwell3d.CallMethod(0x8e4, 0x0, true); |
| 185 | maxwell3d.CallMethod(0x8e5, 0x0, true); | 189 | maxwell3d.CallMethod(0x8e5, 0x0, true); |
| @@ -271,9 +275,11 @@ public: | |||
| 271 | if (check_limit) { | 275 | if (check_limit) { |
| 272 | minimum_limit = std::max(highest_limit, minimum_limit); | 276 | minimum_limit = std::max(highest_limit, minimum_limit); |
| 273 | } | 277 | } |
| 278 | const u32 estimate = static_cast<u32>(maxwell3d.EstimateIndexBufferSize()); | ||
| 279 | const u32 base_size = std::max(minimum_limit, estimate); | ||
| 274 | 280 | ||
| 275 | maxwell3d.regs.index_buffer.first = 0; | 281 | maxwell3d.regs.index_buffer.first = 0; |
| 276 | maxwell3d.regs.index_buffer.count = std::max(highest_limit, minimum_limit); | 282 | maxwell3d.regs.index_buffer.count = std::max(highest_limit, base_size); |
| 277 | maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | 283 | maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; |
| 278 | auto& params = maxwell3d.draw_manager->GetIndirectParams(); | 284 | auto& params = maxwell3d.draw_manager->GetIndirectParams(); |
| 279 | params.is_indexed = true; | 285 | params.is_indexed = true; |
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp index 8c8dfcca6..8f6c51045 100644 --- a/src/video_core/memory_manager.cpp +++ b/src/video_core/memory_manager.cpp | |||
| @@ -325,9 +325,15 @@ template <bool is_big_pages, typename FuncMapped, typename FuncReserved, typenam | |||
| 325 | inline void MemoryManager::MemoryOperation(GPUVAddr gpu_src_addr, std::size_t size, | 325 | inline void MemoryManager::MemoryOperation(GPUVAddr gpu_src_addr, std::size_t size, |
| 326 | FuncMapped&& func_mapped, FuncReserved&& func_reserved, | 326 | FuncMapped&& func_mapped, FuncReserved&& func_reserved, |
| 327 | FuncUnmapped&& func_unmapped) const { | 327 | FuncUnmapped&& func_unmapped) const { |
| 328 | static constexpr bool BOOL_BREAK_MAPPED = std::is_same_v<FuncMapped, bool>; | 328 | using FuncMappedReturn = |
| 329 | static constexpr bool BOOL_BREAK_RESERVED = std::is_same_v<FuncReserved, bool>; | 329 | typename std::invoke_result<FuncMapped, std::size_t, std::size_t, std::size_t>::type; |
| 330 | static constexpr bool BOOL_BREAK_UNMAPPED = std::is_same_v<FuncUnmapped, bool>; | 330 | using FuncReservedReturn = |
| 331 | typename std::invoke_result<FuncReserved, std::size_t, std::size_t, std::size_t>::type; | ||
| 332 | using FuncUnmappedReturn = | ||
| 333 | typename std::invoke_result<FuncUnmapped, std::size_t, std::size_t, std::size_t>::type; | ||
| 334 | static constexpr bool BOOL_BREAK_MAPPED = std::is_same_v<FuncMappedReturn, bool>; | ||
| 335 | static constexpr bool BOOL_BREAK_RESERVED = std::is_same_v<FuncReservedReturn, bool>; | ||
| 336 | static constexpr bool BOOL_BREAK_UNMAPPED = std::is_same_v<FuncUnmappedReturn, bool>; | ||
| 331 | u64 used_page_size; | 337 | u64 used_page_size; |
| 332 | u64 used_page_mask; | 338 | u64 used_page_mask; |
| 333 | u64 used_page_bits; | 339 | u64 used_page_bits; |
| @@ -571,6 +577,47 @@ size_t MemoryManager::MaxContinousRange(GPUVAddr gpu_addr, size_t size) const { | |||
| 571 | return range_so_far; | 577 | return range_so_far; |
| 572 | } | 578 | } |
| 573 | 579 | ||
| 580 | size_t MemoryManager::GetMemoryLayoutSize(GPUVAddr gpu_addr) const { | ||
| 581 | PTEKind base_kind = GetPageKind(gpu_addr); | ||
| 582 | if (base_kind == PTEKind::INVALID) { | ||
| 583 | return 0; | ||
| 584 | } | ||
| 585 | size_t range_so_far = 0; | ||
| 586 | bool result{false}; | ||
| 587 | auto fail = [&]([[maybe_unused]] std::size_t page_index, [[maybe_unused]] std::size_t offset, | ||
| 588 | std::size_t copy_amount) { | ||
| 589 | result = true; | ||
| 590 | return true; | ||
| 591 | }; | ||
| 592 | auto short_check = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { | ||
| 593 | PTEKind base_kind_other = GetKind<false>((page_index << page_bits) + offset); | ||
| 594 | if (base_kind != base_kind_other) { | ||
| 595 | result = true; | ||
| 596 | return true; | ||
| 597 | } | ||
| 598 | range_so_far += copy_amount; | ||
| 599 | return false; | ||
| 600 | }; | ||
| 601 | auto big_check = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { | ||
| 602 | PTEKind base_kind_other = GetKind<true>((page_index << big_page_bits) + offset); | ||
| 603 | if (base_kind != base_kind_other) { | ||
| 604 | result = true; | ||
| 605 | return true; | ||
| 606 | } | ||
| 607 | range_so_far += copy_amount; | ||
| 608 | return false; | ||
| 609 | }; | ||
| 610 | auto check_short_pages = [&](std::size_t page_index, std::size_t offset, | ||
| 611 | std::size_t copy_amount) { | ||
| 612 | GPUVAddr base = (page_index << big_page_bits) + offset; | ||
| 613 | MemoryOperation<false>(base, copy_amount, short_check, fail, fail); | ||
| 614 | return result; | ||
| 615 | }; | ||
| 616 | MemoryOperation<true>(gpu_addr, address_space_size - gpu_addr, big_check, fail, | ||
| 617 | check_short_pages); | ||
| 618 | return range_so_far; | ||
| 619 | } | ||
| 620 | |||
| 574 | void MemoryManager::InvalidateRegion(GPUVAddr gpu_addr, size_t size) const { | 621 | void MemoryManager::InvalidateRegion(GPUVAddr gpu_addr, size_t size) const { |
| 575 | auto do_nothing = [&]([[maybe_unused]] std::size_t page_index, | 622 | auto do_nothing = [&]([[maybe_unused]] std::size_t page_index, |
| 576 | [[maybe_unused]] std::size_t offset, | 623 | [[maybe_unused]] std::size_t offset, |
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h index ab4bc9ec6..65f6e8134 100644 --- a/src/video_core/memory_manager.h +++ b/src/video_core/memory_manager.h | |||
| @@ -118,6 +118,8 @@ public: | |||
| 118 | 118 | ||
| 119 | PTEKind GetPageKind(GPUVAddr gpu_addr) const; | 119 | PTEKind GetPageKind(GPUVAddr gpu_addr) const; |
| 120 | 120 | ||
| 121 | size_t GetMemoryLayoutSize(GPUVAddr gpu_addr) const; | ||
| 122 | |||
| 121 | private: | 123 | private: |
| 122 | template <bool is_big_pages, typename FuncMapped, typename FuncReserved, typename FuncUnmapped> | 124 | template <bool is_big_pages, typename FuncMapped, typename FuncReserved, typename FuncUnmapped> |
| 123 | inline void MemoryOperation(GPUVAddr gpu_src_addr, std::size_t size, FuncMapped&& func_mapped, | 125 | inline void MemoryOperation(GPUVAddr gpu_src_addr, std::size_t size, FuncMapped&& func_mapped, |