mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-22 18:15:14 +00:00
Fix segfault with clear mask
This commit is contained in:
parent
a6cdf2eac7
commit
2849e970cb
@ -3,23 +3,43 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <tuple>
|
||||
|
||||
namespace Common {
|
||||
|
||||
template <class Func>
|
||||
struct FuncTraits {};
|
||||
template <class Func, class Enable = void>
|
||||
struct FuncTraits;
|
||||
|
||||
// Function type
|
||||
template <class ReturnType_, class... Args>
|
||||
struct FuncTraits<ReturnType_ (*)(Args...)> {
|
||||
struct FuncTraits<ReturnType_(Args...), void> {
|
||||
using ReturnType = ReturnType_;
|
||||
|
||||
static constexpr size_t NUM_ARGS = sizeof...(Args);
|
||||
|
||||
template <size_t I>
|
||||
using ArgType = std::tuple_element_t<I, std::tuple<Args...>>;
|
||||
};
|
||||
|
||||
// Function pointer
|
||||
template <class ReturnType_, class... Args>
|
||||
struct FuncTraits<ReturnType_ (*)(Args...), void> : FuncTraits<ReturnType_(Args...)> {};
|
||||
|
||||
// Member function pointer
|
||||
template <class ClassType, class ReturnType_, class... Args>
|
||||
struct FuncTraits<ReturnType_ (ClassType::*)(Args...), void> : FuncTraits<ReturnType_(Args...)> {};
|
||||
|
||||
template <class ClassType, class ReturnType_, class... Args>
|
||||
struct FuncTraits<ReturnType_ (ClassType::*)(Args...) const, void>
|
||||
: FuncTraits<ReturnType_(Args...)> {};
|
||||
|
||||
// Catch-all for callables
|
||||
template <class Func>
|
||||
struct FuncTraits<Func, std::void_t<decltype(&std::remove_reference_t<Func>::operator())>>
|
||||
: FuncTraits<decltype(&std::remove_reference_t<Func>::operator())> {};
|
||||
|
||||
|
||||
// For lambdas: for compat (may be removed)
|
||||
template <typename Func>
|
||||
struct LambdaTraits : LambdaTraits<decltype(&std::remove_reference_t<Func>::operator())> {};
|
||||
|
||||
|
@ -1064,8 +1064,11 @@ void BufferCache::SynchronizeBuffersForDma() {
|
||||
copies.clear();
|
||||
};
|
||||
mapped_ranges.ForEach([&](VAddr device_addr, u64 size) {
|
||||
memory_tracker->ForEachUploadRange(device_addr, size, false, [&](u64 device_addr_out, u64 range_size) {
|
||||
RENDERER_TRACE;
|
||||
memory_tracker->ForEachUploadRange(device_addr, size, false, [&](u64 device_addr_out, u64 range_size, RegionBits& clear_mask) {
|
||||
RENDERER_TRACE;
|
||||
ForEachBufferInRange(device_addr_out, range_size, [&](BufferId buffer_id, Buffer& buffer) {
|
||||
RENDERER_TRACE;
|
||||
if (last_buffer_id != buffer_id) {
|
||||
upload_pending();
|
||||
last_buffer_id = buffer_id;
|
||||
@ -1082,6 +1085,14 @@ void BufferCache::SynchronizeBuffersForDma() {
|
||||
.dstOffset = copy_start - buffer.CpuAddr(),
|
||||
.size = copy_size,
|
||||
});
|
||||
|
||||
// We need to use tracker page size here, we are marking the clear mask
|
||||
const u64 page_start = (copy_start & TRACKER_HIGHER_PAGE_MASK) >> TRACKER_PAGE_BITS;
|
||||
const u64 page_end =
|
||||
Common::DivCeil((copy_end - 1) & TRACKER_HIGHER_PAGE_MASK, TRACKER_BYTES_PER_PAGE);
|
||||
ASSERT(page_start < page_end);
|
||||
LOG_WARNING(Render_Vulkan, "Page start {:#x}, end {:#x}", page_start, page_end);
|
||||
clear_mask.SetRange(page_start, page_end);
|
||||
});
|
||||
}, upload_pending);
|
||||
});
|
||||
|
@ -18,11 +18,10 @@ constexpr u64 TRACKER_HIGHER_PAGE_MASK = TRACKER_HIGHER_PAGE_SIZE - 1ULL;
|
||||
constexpr u64 NUM_PAGES_PER_REGION = TRACKER_HIGHER_PAGE_SIZE / TRACKER_BYTES_PER_PAGE;
|
||||
|
||||
enum class Type {
|
||||
None = 0,
|
||||
CPU = 1 << 0,
|
||||
GPU = 1 << 1,
|
||||
None,
|
||||
CPU,
|
||||
GPU,
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(Type)
|
||||
|
||||
|
||||
using RegionBits = Common::BitArray<NUM_PAGES_PER_REGION>;
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "common/config.h"
|
||||
#include "common/div_ceil.h"
|
||||
#include "common/func_traits.h"
|
||||
|
||||
#ifdef __linux__
|
||||
#include "common/adaptive_mutex.h"
|
||||
@ -69,20 +70,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
template <Type type, bool enable>
|
||||
void PerformDeferredProtections() {
|
||||
bool was_deferred = True(deferred_protection & type);
|
||||
if (!was_deferred) {
|
||||
return;
|
||||
}
|
||||
deferred_protection &= ~type;
|
||||
if constexpr (type == Type::CPU) {
|
||||
UpdateProtection<!enable, false>();
|
||||
} else if constexpr (type == Type::GPU) {
|
||||
UpdateProtection<enable, true>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the state of a range of pages
|
||||
*
|
||||
@ -121,9 +108,11 @@ public:
|
||||
* @param size Size in bytes of the CPU range to loop over
|
||||
* @param func Function to call for each turned off region
|
||||
*/
|
||||
template <Type type, bool clear>
|
||||
void ForEachModifiedRange(VAddr query_cpu_range, s64 size, auto&& func) {
|
||||
template <Type type, bool clear, typename F>
|
||||
void ForEachModifiedRange(VAddr query_cpu_range, s64 size, F&& func) {
|
||||
RENDERER_TRACE;
|
||||
using FuncTraits = Common::FuncTraits<F>;
|
||||
constexpr bool uses_clear_mask = FuncTraits::NUM_ARGS == 3;
|
||||
const size_t offset = query_cpu_range - cpu_addr;
|
||||
const size_t start_page = SanitizeAddress(offset) / TRACKER_BYTES_PER_PAGE;
|
||||
const size_t end_page =
|
||||
@ -135,18 +124,31 @@ public:
|
||||
RegionBits& bits = GetRegionBits<type>();
|
||||
RegionBits mask(bits, start_page, end_page);
|
||||
|
||||
if constexpr (uses_clear_mask) {
|
||||
static_assert(clear, "Function must not use clear mask when not clearing");
|
||||
RegionBits clear_mask;
|
||||
for (const auto& [start, end] : mask) {
|
||||
func(cpu_addr + start * TRACKER_BYTES_PER_PAGE,
|
||||
(end - start) * TRACKER_BYTES_PER_PAGE, clear_mask);
|
||||
}
|
||||
bits &= ~clear_mask;
|
||||
} else {
|
||||
for (const auto& [start, end] : mask) {
|
||||
func(cpu_addr + start * TRACKER_BYTES_PER_PAGE,
|
||||
(end - start) * TRACKER_BYTES_PER_PAGE);
|
||||
}
|
||||
if constexpr (clear) {
|
||||
bits &= ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (clear) {
|
||||
bits.UnsetRange(start_page, end_page);
|
||||
if constexpr (type == Type::CPU) {
|
||||
UpdateProtection<true, false>();
|
||||
} else if (Config::readbacks()) {
|
||||
UpdateProtection<false, true>();
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& [start, end] : mask) {
|
||||
func(cpu_addr + start * TRACKER_BYTES_PER_PAGE, (end - start) * TRACKER_BYTES_PER_PAGE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user