summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/video_core/engines/maxwell_3d.cpp7
-rw-r--r--src/video_core/engines/maxwell_3d.h2
-rw-r--r--src/video_core/macro/macro_hle.cpp20
-rw-r--r--src/video_core/memory_manager.cpp53
-rw-r--r--src/video_core/memory_manager.h2
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
182size_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
182u32 Maxwell3D::ProcessShadowRam(u32 method, u32 argument) { 189u32 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
325inline void MemoryManager::MemoryOperation(GPUVAddr gpu_src_addr, std::size_t size, 325inline 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
580size_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
574void MemoryManager::InvalidateRegion(GPUVAddr gpu_addr, size_t size) const { 621void 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
121private: 123private:
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,