Compare commits
2 Commits
civa
...
dynarm7345
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0490529a01 | ||
|
|
c7a7fe15e5 |
@@ -10,7 +10,6 @@
|
||||
#include <mutex>
|
||||
#include <span>
|
||||
#include <thread>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "common/assert.h"
|
||||
@@ -682,17 +681,22 @@ struct Memory::Impl {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename F, typename G>
|
||||
[[nodiscard]] u8* GetPointerImpl(u64 vaddr, F&& on_unmapped, G&& on_rasterizer) const {
|
||||
[[nodiscard]] u8* GetPointerImpl(u64 vaddr, auto on_unmapped, auto on_rasterizer) const {
|
||||
// AARCH64 masks the upper 16 bit of all memory accesses
|
||||
vaddr &= 0xffffffffffffULL;
|
||||
if (AddressSpaceContains(*current_page_table, vaddr, 1)) [[likely]] {
|
||||
vaddr = vaddr & 0xffffffffffffULL;
|
||||
if (!AddressSpaceContains(*current_page_table, vaddr, 1)) [[unlikely]] {
|
||||
on_unmapped();
|
||||
return nullptr;
|
||||
} else {
|
||||
// Avoid adding any extra logic to this fast-path block
|
||||
const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Raw();
|
||||
if (const uintptr_t pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) [[likely]] {
|
||||
if (const uintptr_t pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) {
|
||||
return reinterpret_cast<u8*>(pointer + vaddr);
|
||||
} else {
|
||||
switch (Common::PageTable::PageInfo::ExtractType(raw_pointer)) {
|
||||
case Common::PageType::Unmapped:
|
||||
on_unmapped();
|
||||
return nullptr;
|
||||
case Common::PageType::Memory:
|
||||
ASSERT_MSG(false, "Mapped memory page without a pointer @ 0x{:016X}", vaddr);
|
||||
return nullptr;
|
||||
@@ -703,18 +707,11 @@ struct Memory::Impl {
|
||||
on_rasterizer();
|
||||
return host_ptr;
|
||||
}
|
||||
case Common::PageType::Unmapped: [[unlikely]] {
|
||||
on_unmapped();
|
||||
return nullptr;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
on_unmapped();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -732,38 +729,172 @@ struct Memory::Impl {
|
||||
GetInteger(vaddr), []() {}, []() {});
|
||||
}
|
||||
|
||||
/// @brief Reads a particular data type out of memory at the given virtual address.
|
||||
/// @param vaddr The virtual address to read the data type from.
|
||||
/// @tparam T The data type to read out of memory.
|
||||
/// @returns The instance of T read from the specified virtual address.
|
||||
/**
|
||||
* Reads a particular data type out of memory at the given virtual address.
|
||||
*
|
||||
* @param vaddr The virtual address to read the data type from.
|
||||
*
|
||||
* @tparam T The data type to read out of memory. This type *must* be
|
||||
* trivially copyable, otherwise the behavior of this function
|
||||
* is undefined.
|
||||
*
|
||||
* @returns The instance of T read from the specified virtual address.
|
||||
*/
|
||||
template <typename T>
|
||||
inline T Read(Common::ProcessAddress vaddr) noexcept requires(std::is_trivially_copyable_v<T>) {
|
||||
T Read(Common::ProcessAddress vaddr) {
|
||||
// Fast path for aligned reads of common sizes
|
||||
const u64 addr = GetInteger(vaddr);
|
||||
if (auto const ptr = GetPointerImpl(addr, [addr]() {
|
||||
LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:016X}", sizeof(T) * 8, addr);
|
||||
}, [&]() {
|
||||
HandleRasterizerDownload(addr, sizeof(T));
|
||||
}); ptr) [[likely]] {
|
||||
// It may be tempting to rewrite this particular section to use "reinterpret_cast";
|
||||
// afterall, it's trivially copyable so surely it can be copied ov- Alignment.
|
||||
// Remember, alignment. memcpy() will deal with all the alignment extremely fast.
|
||||
T result{};
|
||||
std::memcpy(&result, ptr, sizeof(T));
|
||||
return result;
|
||||
if constexpr (std::is_same_v<T, u8> || std::is_same_v<T, s8>) {
|
||||
// 8-bit reads are always aligned
|
||||
const u8* const ptr = GetPointerImpl(
|
||||
addr,
|
||||
[addr]() {
|
||||
LOG_ERROR(HW_Memory, "Unmapped Read8 @ 0x{:016X}", addr);
|
||||
},
|
||||
[&]() { HandleRasterizerDownload(addr, sizeof(T)); });
|
||||
if (ptr) {
|
||||
return static_cast<T>(*ptr);
|
||||
}
|
||||
return 0;
|
||||
} else if constexpr (std::is_same_v<T, u16_le> || std::is_same_v<T, s16_le>) {
|
||||
// Check alignment for 16-bit reads
|
||||
if ((addr & 1) == 0) {
|
||||
const u8* const ptr = GetPointerImpl(
|
||||
addr,
|
||||
[addr]() {
|
||||
LOG_ERROR(HW_Memory, "Unmapped Read16 @ 0x{:016X}", addr);
|
||||
},
|
||||
[&]() { HandleRasterizerDownload(addr, sizeof(T)); });
|
||||
if (ptr) {
|
||||
return static_cast<T>(*reinterpret_cast<const u16*>(ptr));
|
||||
}
|
||||
}
|
||||
} else if constexpr (std::is_same_v<T, u32_le> || std::is_same_v<T, s32_le>) {
|
||||
// Check alignment for 32-bit reads
|
||||
if ((addr & 3) == 0) {
|
||||
const u8* const ptr = GetPointerImpl(
|
||||
addr,
|
||||
[addr]() {
|
||||
LOG_ERROR(HW_Memory, "Unmapped Read32 @ 0x{:016X}", addr);
|
||||
},
|
||||
[&]() { HandleRasterizerDownload(addr, sizeof(T)); });
|
||||
if (ptr) {
|
||||
return static_cast<T>(*reinterpret_cast<const u32*>(ptr));
|
||||
}
|
||||
}
|
||||
} else if constexpr (std::is_same_v<T, u64_le> || std::is_same_v<T, s64_le>) {
|
||||
// Check alignment for 64-bit reads
|
||||
if ((addr & 7) == 0) {
|
||||
const u8* const ptr = GetPointerImpl(
|
||||
addr,
|
||||
[addr]() {
|
||||
LOG_ERROR(HW_Memory, "Unmapped Read64 @ 0x{:016X}", addr);
|
||||
},
|
||||
[&]() { HandleRasterizerDownload(addr, sizeof(T)); });
|
||||
if (ptr) {
|
||||
return static_cast<T>(*reinterpret_cast<const u64*>(ptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
return T{};
|
||||
|
||||
// Fall back to the general case for other types or unaligned access
|
||||
T result = 0;
|
||||
const u8* const ptr = GetPointerImpl(
|
||||
addr,
|
||||
[addr]() {
|
||||
LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:016X}", sizeof(T) * 8, addr);
|
||||
},
|
||||
[&]() { HandleRasterizerDownload(addr, sizeof(T)); });
|
||||
if (ptr) {
|
||||
std::memcpy(&result, ptr, sizeof(T));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// @brief Writes a particular data type to memory at the given virtual address.
|
||||
/// @param vaddr The virtual address to write the data type to.
|
||||
/// @tparam T The data type to write to memory.
|
||||
/**
|
||||
* Writes a particular data type to memory at the given virtual address.
|
||||
*
|
||||
* @param vaddr The virtual address to write the data type to.
|
||||
*
|
||||
* @tparam T The data type to write to memory. This type *must* be
|
||||
* trivially copyable, otherwise the behavior of this function
|
||||
* is undefined.
|
||||
*/
|
||||
template <typename T>
|
||||
inline void Write(Common::ProcessAddress vaddr, const T data) noexcept requires(std::is_trivially_copyable_v<T>) {
|
||||
void Write(Common::ProcessAddress vaddr, const T data) {
|
||||
// Fast path for aligned writes of common sizes
|
||||
const u64 addr = GetInteger(vaddr);
|
||||
if (auto const ptr = GetPointerImpl(addr, [addr, data]() {
|
||||
LOG_ERROR(HW_Memory, "Unmapped Write{} @ 0x{:016X} = 0x{:016X}", sizeof(T) * 8, addr, u64(data));
|
||||
}, [&]() { HandleRasterizerWrite(addr, sizeof(T)); }); ptr) [[likely]]
|
||||
if constexpr (std::is_same_v<T, u8> || std::is_same_v<T, s8>) {
|
||||
// 8-bit writes are always aligned
|
||||
u8* const ptr = GetPointerImpl(
|
||||
addr,
|
||||
[addr, data]() {
|
||||
LOG_ERROR(HW_Memory, "Unmapped Write8 @ 0x{:016X} = 0x{:02X}", addr,
|
||||
static_cast<u8>(data));
|
||||
},
|
||||
[&]() { HandleRasterizerWrite(addr, sizeof(T)); });
|
||||
if (ptr) {
|
||||
*ptr = static_cast<u8>(data);
|
||||
}
|
||||
return;
|
||||
} else if constexpr (std::is_same_v<T, u16_le> || std::is_same_v<T, s16_le>) {
|
||||
// Check alignment for 16-bit writes
|
||||
if ((addr & 1) == 0) {
|
||||
u8* const ptr = GetPointerImpl(
|
||||
addr,
|
||||
[addr, data]() {
|
||||
LOG_ERROR(HW_Memory, "Unmapped Write16 @ 0x{:016X} = 0x{:04X}", addr,
|
||||
static_cast<u16>(data));
|
||||
},
|
||||
[&]() { HandleRasterizerWrite(addr, sizeof(T)); });
|
||||
if (ptr) {
|
||||
*reinterpret_cast<u16*>(ptr) = static_cast<u16>(data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if constexpr (std::is_same_v<T, u32_le> || std::is_same_v<T, s32_le>) {
|
||||
// Check alignment for 32-bit writes
|
||||
if ((addr & 3) == 0) {
|
||||
u8* const ptr = GetPointerImpl(
|
||||
addr,
|
||||
[addr, data]() {
|
||||
LOG_ERROR(HW_Memory, "Unmapped Write32 @ 0x{:016X} = 0x{:08X}", addr,
|
||||
static_cast<u32>(data));
|
||||
},
|
||||
[&]() { HandleRasterizerWrite(addr, sizeof(T)); });
|
||||
if (ptr) {
|
||||
*reinterpret_cast<u32*>(ptr) = static_cast<u32>(data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if constexpr (std::is_same_v<T, u64_le> || std::is_same_v<T, s64_le>) {
|
||||
// Check alignment for 64-bit writes
|
||||
if ((addr & 7) == 0) {
|
||||
u8* const ptr = GetPointerImpl(
|
||||
addr,
|
||||
[addr, data]() {
|
||||
LOG_ERROR(HW_Memory, "Unmapped Write64 @ 0x{:016X} = 0x{:016X}", addr,
|
||||
static_cast<u64>(data));
|
||||
},
|
||||
[&]() { HandleRasterizerWrite(addr, sizeof(T)); });
|
||||
if (ptr) {
|
||||
*reinterpret_cast<u64*>(ptr) = static_cast<u64>(data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to the general case for other types or unaligned access
|
||||
u8* const ptr = GetPointerImpl(
|
||||
addr,
|
||||
[addr, data]() {
|
||||
LOG_ERROR(HW_Memory, "Unmapped Write{} @ 0x{:016X} = 0x{:016X}", sizeof(T) * 8,
|
||||
addr, static_cast<u64>(data));
|
||||
},
|
||||
[&]() { HandleRasterizerWrite(addr, sizeof(T)); });
|
||||
if (ptr) {
|
||||
std::memcpy(ptr, &data, sizeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
||||
@@ -57,7 +57,7 @@ class SigHandler {
|
||||
public:
|
||||
SigHandler() noexcept {
|
||||
signal_stack_size = std::max<size_t>(SIGSTKSZ, 2 * 1024 * 1024);
|
||||
signal_stack_memory = mmap(nullptr, signal_stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
signal_stack_memory = std::malloc(signal_stack_size);
|
||||
|
||||
stack_t signal_stack{};
|
||||
signal_stack.ss_sp = signal_stack_memory;
|
||||
@@ -89,7 +89,7 @@ public:
|
||||
}
|
||||
|
||||
~SigHandler() noexcept {
|
||||
munmap(signal_stack_memory, signal_stack_size);
|
||||
std::free(signal_stack_memory);
|
||||
}
|
||||
|
||||
void AddCodeBlock(u64 offset, CodeBlockInfo cbi) noexcept {
|
||||
|
||||
@@ -82,7 +82,8 @@ FP::FPCR A32EmitContext::FPCR(bool fpcr_controlled) const {
|
||||
|
||||
A32EmitX64::A32EmitX64(BlockOfCode& code, A32::UserConfig conf, A32::Jit* jit_interface)
|
||||
: EmitX64(code), conf(std::move(conf)), jit_interface(jit_interface) {
|
||||
GenFastmemFallbacks();
|
||||
if (conf.fastmem_pointer.has_value())
|
||||
GenFastmemFallbacks();
|
||||
GenTerminalHandlers();
|
||||
code.PreludeComplete();
|
||||
ClearFastDispatchTable();
|
||||
|
||||
@@ -56,7 +56,8 @@ FP::FPCR A64EmitContext::FPCR(bool fpcr_controlled) const {
|
||||
A64EmitX64::A64EmitX64(BlockOfCode& code, A64::UserConfig conf, A64::Jit* jit_interface)
|
||||
: EmitX64(code), conf(conf), jit_interface{jit_interface} {
|
||||
GenMemory128Accessors();
|
||||
GenFastmemFallbacks();
|
||||
if (conf.fastmem_pointer.has_value())
|
||||
GenFastmemFallbacks();
|
||||
GenTerminalHandlers();
|
||||
code.PreludeComplete();
|
||||
ClearFastDispatchTable();
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "input_common/drivers/mouse.h"
|
||||
|
||||
namespace InputCommon {
|
||||
constexpr int update_time = 10;
|
||||
constexpr int update_time = 250; // 4 TPS
|
||||
constexpr float default_panning_sensitivity = 0.0010f;
|
||||
constexpr float default_stick_sensitivity = 0.0006f;
|
||||
constexpr float default_deadzone_counterweight = 0.01f;
|
||||
|
||||
@@ -1497,13 +1497,11 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src,
|
||||
|
||||
void TextureCacheRuntime::CopyImageMSAA(Image& dst, Image& src,
|
||||
std::span<const VideoCommon::ImageCopy> copies) {
|
||||
const bool msaa_to_non_msaa = src.info.num_samples > 1 && dst.info.num_samples == 1;
|
||||
if (msaa_copy_pass) {
|
||||
msaa_copy_pass->CopyImage(dst, src, copies,
|
||||
src.info.num_samples > 1 && dst.info.num_samples == 1);
|
||||
return;
|
||||
return msaa_copy_pass->CopyImage(dst, src, copies, msaa_to_non_msaa);
|
||||
}
|
||||
|
||||
CopyImage(dst, src, copies);
|
||||
UNIMPLEMENTED_MSG("Copying images with different samples is not supported.");
|
||||
}
|
||||
|
||||
u64 TextureCacheRuntime::GetDeviceLocalMemory() const {
|
||||
|
||||
Reference in New Issue
Block a user