mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-26 15:41:17 +00:00
Make vm::get_super_ptr return contiguous memory
Cleanup RSX code complexity
This commit is contained in:
parent
72ba062b1a
commit
da6ce80f4f
@ -136,7 +136,6 @@ namespace utils
|
|||||||
|
|
||||||
shm::shm(u32 size)
|
shm::shm(u32 size)
|
||||||
: m_size(::align(size, 0x10000))
|
: m_size(::align(size, 0x10000))
|
||||||
, m_ptr(nullptr)
|
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
m_handle = ::CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, 0, m_size, NULL);
|
m_handle = ::CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, 0, m_size, NULL);
|
||||||
@ -159,17 +158,13 @@ namespace utils
|
|||||||
verify(HERE), ::shm_unlink("/rpcs3-mem1") >= 0;
|
verify(HERE), ::shm_unlink("/rpcs3-mem1") >= 0;
|
||||||
verify(HERE), ::ftruncate(m_file, m_size) >= 0;
|
verify(HERE), ::ftruncate(m_file, m_size) >= 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_ptr = verify(HERE, this->map(nullptr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
shm::~shm()
|
shm::~shm()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
::UnmapViewOfFile(m_ptr);
|
|
||||||
::CloseHandle(m_handle);
|
::CloseHandle(m_handle);
|
||||||
#else
|
#else
|
||||||
::munmap(m_ptr, m_size);
|
|
||||||
::close(m_file);
|
::close(m_file);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,6 @@ namespace utils
|
|||||||
int m_file;
|
int m_file;
|
||||||
#endif
|
#endif
|
||||||
u32 m_size;
|
u32 m_size;
|
||||||
u8* m_ptr;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit shm(u32 size);
|
explicit shm(u32 size);
|
||||||
@ -69,17 +68,6 @@ namespace utils
|
|||||||
// Unmap shared memory, undoing map_critical
|
// Unmap shared memory, undoing map_critical
|
||||||
void unmap_critical(void* ptr);
|
void unmap_critical(void* ptr);
|
||||||
|
|
||||||
// Access memory with simple range check
|
|
||||||
u8* get(u32 offset, u32 size) const
|
|
||||||
{
|
|
||||||
if (offset >= m_size || m_size - offset < size)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_ptr + offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 size() const
|
u32 size() const
|
||||||
{
|
{
|
||||||
return m_size;
|
return m_size;
|
||||||
|
@ -33,7 +33,7 @@ error_code sys_dbg_read_process_memory(s32 pid, u32 address, u32 size, vm::ptr<v
|
|||||||
return CELL_EFAULT;
|
return CELL_EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::memcpy(data.get_ptr(), vm::get_super_ptr<u8>(address, size).get(), size);
|
std::memcpy(data.get_ptr(), vm::get_super_ptr(address), size);
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
@ -64,7 +64,7 @@ error_code sys_dbg_write_process_memory(s32 pid, u32 address, u32 size, vm::cptr
|
|||||||
return CELL_EFAULT;
|
return CELL_EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::memcpy(vm::get_super_ptr<u8>(address, size).get(), data.get_ptr(), size);
|
std::memcpy(vm::get_super_ptr(address), data.get_ptr(), size);
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
@ -31,10 +31,13 @@ namespace vm
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Emulated virtual memory
|
// Emulated virtual memory
|
||||||
u8* const g_base_addr = memory_reserve_4GiB(0);
|
u8* const g_base_addr = memory_reserve_4GiB(0x2'0000'0000);
|
||||||
|
|
||||||
|
// Unprotected virtual memory mirror
|
||||||
|
u8* const g_sudo_addr = memory_reserve_4GiB((std::uintptr_t)g_base_addr);
|
||||||
|
|
||||||
// Auxiliary virtual memory for executable areas
|
// Auxiliary virtual memory for executable areas
|
||||||
u8* const g_exec_addr = memory_reserve_4GiB((std::uintptr_t)g_base_addr);
|
u8* const g_exec_addr = memory_reserve_4GiB((std::uintptr_t)g_sudo_addr);
|
||||||
|
|
||||||
// Stats for debugging
|
// Stats for debugging
|
||||||
u8* const g_stat_addr = memory_reserve_4GiB((std::uintptr_t)g_exec_addr);
|
u8* const g_stat_addr = memory_reserve_4GiB((std::uintptr_t)g_exec_addr);
|
||||||
@ -305,7 +308,7 @@ namespace vm
|
|||||||
utils::memory_protect(g_base_addr + addr, size, utils::protection::rw);
|
utils::memory_protect(g_base_addr + addr, size, utils::protection::rw);
|
||||||
std::memset(g_base_addr + addr, 0, size);
|
std::memset(g_base_addr + addr, 0, size);
|
||||||
}
|
}
|
||||||
else if (shm->map_critical(g_base_addr + addr) != g_base_addr + addr)
|
else if (shm->map_critical(g_base_addr + addr) != g_base_addr + addr || shm->map_critical(g_sudo_addr + addr) != g_sudo_addr + addr)
|
||||||
{
|
{
|
||||||
fmt::throw_exception("Memory mapping failed - blame Windows (addr=0x%x, size=0x%x, flags=0x%x)", addr, size, flags);
|
fmt::throw_exception("Memory mapping failed - blame Windows (addr=0x%x, size=0x%x, flags=0x%x)", addr, size, flags);
|
||||||
}
|
}
|
||||||
@ -437,6 +440,7 @@ namespace vm
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
shm->unmap_critical(g_base_addr + addr);
|
shm->unmap_critical(g_base_addr + addr);
|
||||||
|
shm->unmap_critical(g_sudo_addr + addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_exec)
|
if (is_exec)
|
||||||
@ -575,6 +579,7 @@ namespace vm
|
|||||||
// Special path for 4k-aligned pages
|
// Special path for 4k-aligned pages
|
||||||
m_common = std::make_shared<utils::shm>(size);
|
m_common = std::make_shared<utils::shm>(size);
|
||||||
verify(HERE), m_common->map_critical(vm::base(addr), utils::protection::no) == vm::base(addr);
|
verify(HERE), m_common->map_critical(vm::base(addr), utils::protection::no) == vm::base(addr);
|
||||||
|
verify(HERE), m_common->map_critical(vm::get_super_ptr(addr), utils::protection::no) == vm::get_super_ptr(addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -596,6 +601,7 @@ namespace vm
|
|||||||
if (m_common)
|
if (m_common)
|
||||||
{
|
{
|
||||||
m_common->unmap_critical(vm::base(addr));
|
m_common->unmap_critical(vm::base(addr));
|
||||||
|
m_common->unmap_critical(vm::get_super_ptr(addr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ class notifier;
|
|||||||
namespace vm
|
namespace vm
|
||||||
{
|
{
|
||||||
extern u8* const g_base_addr;
|
extern u8* const g_base_addr;
|
||||||
|
extern u8* const g_sudo_addr;
|
||||||
extern u8* const g_exec_addr;
|
extern u8* const g_exec_addr;
|
||||||
extern u8* const g_stat_addr;
|
extern u8* const g_stat_addr;
|
||||||
extern u8* const g_reservations;
|
extern u8* const g_reservations;
|
||||||
@ -303,32 +304,10 @@ namespace vm
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Access memory bypassing memory protection
|
// Access memory bypassing memory protection
|
||||||
template <typename T>
|
template <typename T = u8>
|
||||||
inline std::shared_ptr<to_be_t<T>> get_super_ptr(u32 addr, u32 count = 1)
|
inline to_be_t<T>* get_super_ptr(u32 addr)
|
||||||
{
|
{
|
||||||
const auto area = vm::get(vm::any, addr);
|
return reinterpret_cast<to_be_t<T>*>(g_sudo_addr + addr);
|
||||||
|
|
||||||
if (!area || addr + u64{count} * sizeof(T) > UINT32_MAX)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto shm = area->get(addr, sizeof(T) * count);
|
|
||||||
|
|
||||||
if (!shm.second || shm.first > addr)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto ptr = reinterpret_cast<to_be_t<T>*>(shm.second->get(addr - shm.first, sizeof(T) * count));
|
|
||||||
|
|
||||||
if (!ptr)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a shared pointer using the aliasing constructor
|
|
||||||
return {shm.second, ptr};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const be_t<u16>& read16(u32 addr)
|
inline const be_t<u16>& read16(u32 addr)
|
||||||
|
@ -2583,16 +2583,13 @@ namespace rsx
|
|||||||
|
|
||||||
void tag_framebuffer(u32 texaddr)
|
void tag_framebuffer(u32 texaddr)
|
||||||
{
|
{
|
||||||
auto super_ptr = rsx::get_super_ptr(texaddr, 4);
|
auto ptr = vm::get_super_ptr<atomic_t<u32>>(texaddr);
|
||||||
volatile u32 *ptr = super_ptr.get<volatile u32>();
|
|
||||||
*ptr = texaddr;
|
*ptr = texaddr;
|
||||||
super_ptr.flush(0, 4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool test_framebuffer(u32 texaddr)
|
bool test_framebuffer(u32 texaddr)
|
||||||
{
|
{
|
||||||
auto super_ptr = rsx::get_super_ptr(texaddr, 4);
|
auto ptr = vm::get_super_ptr<atomic_t<u32>>(texaddr);
|
||||||
volatile const u32 *ptr = super_ptr.get<volatile const u32>();
|
|
||||||
return *ptr == texaddr;
|
return *ptr == texaddr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -495,7 +495,7 @@ namespace gl
|
|||||||
const u32 valid_length = valid_range.second;
|
const u32 valid_length = valid_range.second;
|
||||||
AUDIT( valid_length > 0 );
|
AUDIT( valid_length > 0 );
|
||||||
|
|
||||||
void *dst = get_ptr_by_offset(valid_range.first, true);
|
void *dst = get_ptr(get_section_base() + valid_offset);
|
||||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo_id);
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo_id);
|
||||||
void *src = glMapBufferRange(GL_PIXEL_PACK_BUFFER, valid_offset, valid_length, GL_MAP_READ_BIT);
|
void *src = glMapBufferRange(GL_PIXEL_PACK_BUFFER, valid_offset, valid_length, GL_MAP_READ_BIT);
|
||||||
|
|
||||||
@ -588,7 +588,6 @@ namespace gl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flush_ptr_by_offset(valid_offset, valid_length);
|
|
||||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, GL_NONE);
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, GL_NONE);
|
||||||
|
|
||||||
|
@ -2744,22 +2744,6 @@ namespace rsx
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
on_invalidate_memory_range(m_invalidated_memory_range);
|
on_invalidate_memory_range(m_invalidated_memory_range);
|
||||||
|
|
||||||
// Clean the main memory super_ptr cache if invalidated
|
|
||||||
for (auto It = main_super_memory_block.begin(); It != main_super_memory_block.end();)
|
|
||||||
{
|
|
||||||
const auto block_range = address_range::start_length(It->first, It->second.size());
|
|
||||||
|
|
||||||
if (m_invalidated_memory_range.overlaps(block_range))
|
|
||||||
{
|
|
||||||
It = main_super_memory_block.erase(It);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
It++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_invalidated_memory_range.invalidate();
|
m_invalidated_memory_range.invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,10 +430,6 @@ namespace rsx
|
|||||||
GcmTileInfo tiles[limits::tiles_count];
|
GcmTileInfo tiles[limits::tiles_count];
|
||||||
GcmZcullInfo zculls[limits::zculls_count];
|
GcmZcullInfo zculls[limits::zculls_count];
|
||||||
|
|
||||||
// Super memory map (mapped block with r/w permissions)
|
|
||||||
std::pair<u32, std::shared_ptr<u8>> local_super_memory_block;
|
|
||||||
std::unordered_map<u32, rsx::weak_ptr> main_super_memory_block;
|
|
||||||
|
|
||||||
bool capture_current_frame = false;
|
bool capture_current_frame = false;
|
||||||
void capture_frame(const std::string &name);
|
void capture_frame(const std::string &name);
|
||||||
|
|
||||||
|
@ -309,7 +309,7 @@ namespace vk
|
|||||||
AUDIT( valid_length > 0 );
|
AUDIT( valid_length > 0 );
|
||||||
|
|
||||||
void* pixels_src = dma_buffer->map(valid_offset, valid_length);
|
void* pixels_src = dma_buffer->map(valid_offset, valid_length);
|
||||||
void* pixels_dst = get_ptr_by_offset(valid_offset, true);
|
void* pixels_dst = get_ptr(get_section_base() + valid_offset);
|
||||||
|
|
||||||
if (real_pitch >= rsx_pitch || valid_length <= rsx_pitch)
|
if (real_pitch >= rsx_pitch || valid_length <= rsx_pitch)
|
||||||
{
|
{
|
||||||
@ -334,7 +334,6 @@ namespace vk
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flush_ptr_by_offset(valid_offset, valid_length);
|
|
||||||
dma_buffer->unmap();
|
dma_buffer->unmap();
|
||||||
reset_write_statistics();
|
reset_write_statistics();
|
||||||
|
|
||||||
|
@ -48,7 +48,6 @@ namespace rsx
|
|||||||
address_range locked_range;
|
address_range locked_range;
|
||||||
address_range cpu_range = {};
|
address_range cpu_range = {};
|
||||||
address_range confirmed_range;
|
address_range confirmed_range;
|
||||||
weak_ptr super_ptr;
|
|
||||||
|
|
||||||
utils::protection protection = utils::protection::rw;
|
utils::protection protection = utils::protection::rw;
|
||||||
|
|
||||||
@ -98,8 +97,6 @@ namespace rsx
|
|||||||
protection = utils::protection::rw;
|
protection = utils::protection::rw;
|
||||||
locked = false;
|
locked = false;
|
||||||
|
|
||||||
super_ptr = {};
|
|
||||||
|
|
||||||
init_lockable_range(cpu_range);
|
init_lockable_range(cpu_range);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,8 +134,6 @@ namespace rsx
|
|||||||
|
|
||||||
if (protection == utils::protection::no)
|
if (protection == utils::protection::no)
|
||||||
{
|
{
|
||||||
super_ptr = rsx::get_super_ptr(cpu_range);
|
|
||||||
verify(HERE), super_ptr;
|
|
||||||
tag_memory();
|
tag_memory();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -148,8 +143,6 @@ namespace rsx
|
|||||||
//Unprotect range also invalidates secured range
|
//Unprotect range also invalidates secured range
|
||||||
confirmed_range.invalidate();
|
confirmed_range.invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
super_ptr = {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -177,7 +170,7 @@ namespace rsx
|
|||||||
confirmed_range = address_range::start_length(cpu_range.start + new_confirm.first, new_confirm.second);
|
confirmed_range = address_range::start_length(cpu_range.start + new_confirm.first, new_confirm.second);
|
||||||
ASSERT(!locked || locked_range.inside(confirmed_range.to_page_range()));
|
ASSERT(!locked || locked_range.inside(confirmed_range.to_page_range()));
|
||||||
}
|
}
|
||||||
|
|
||||||
verify(HERE), confirmed_range.inside(cpu_range);
|
verify(HERE), confirmed_range.inside(cpu_range);
|
||||||
init_lockable_range(confirmed_range);
|
init_lockable_range(confirmed_range);
|
||||||
}
|
}
|
||||||
@ -200,7 +193,6 @@ namespace rsx
|
|||||||
|
|
||||||
protection = utils::protection::rw;
|
protection = utils::protection::rw;
|
||||||
confirmed_range.invalidate();
|
confirmed_range.invalidate();
|
||||||
super_ptr = {};
|
|
||||||
locked = false;
|
locked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,44 +316,11 @@ namespace rsx
|
|||||||
* Super Pointer
|
* Super Pointer
|
||||||
*/
|
*/
|
||||||
template <typename T = void>
|
template <typename T = void>
|
||||||
inline T* get_ptr_by_offset(u32 offset = 0, bool no_sync = false)
|
inline T* get_ptr(u32 address)
|
||||||
{
|
{
|
||||||
verify(HERE), super_ptr && cpu_range.length() >= (offset + sizeof(T));
|
return reinterpret_cast<T*>(vm::g_sudo_addr + address);
|
||||||
return super_ptr.get<T>(offset, no_sync);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// specialization due to sizeof(void) being illegal
|
|
||||||
inline void* get_ptr_by_offset(u32 offset, bool no_sync)
|
|
||||||
{
|
|
||||||
verify(HERE), super_ptr && cpu_range.length() >= (offset + 1);
|
|
||||||
return super_ptr.get<void>(offset, no_sync);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T = void>
|
|
||||||
inline T* get_ptr(u32 address, bool no_sync = false)
|
|
||||||
{
|
|
||||||
verify(HERE), cpu_range.start <= address; // super_ptr & sizeof(T) tests are done by get_ptr_by_offset
|
|
||||||
return get_ptr_by_offset<T>(address - cpu_range.start, no_sync);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void flush_ptr_by_offset(u32 offset = 0, u32 len = 0) const
|
|
||||||
{
|
|
||||||
verify(HERE), super_ptr && cpu_range.length() >= (offset + len);
|
|
||||||
super_ptr.flush(offset, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void flush_ptr(u32 address, u32 len = 0) const
|
|
||||||
{
|
|
||||||
verify(HERE), cpu_range.start <= address; // super_ptr & length tests are done by flush_ptr_by_offset
|
|
||||||
return flush_ptr_by_offset(address - cpu_range.start, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void flush_ptr(const address_range &range) const
|
|
||||||
{
|
|
||||||
return flush_ptr(range.start, range.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Memory tagging
|
* Memory tagging
|
||||||
*/
|
*/
|
||||||
@ -372,18 +331,15 @@ namespace rsx
|
|||||||
if (guard_policy == protect_policy_full_range)
|
if (guard_policy == protect_policy_full_range)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
AUDIT(locked && super_ptr);
|
AUDIT(locked);
|
||||||
|
|
||||||
const address_range& range = get_confirmed_range();
|
const address_range& range = get_confirmed_range();
|
||||||
|
|
||||||
volatile u32* first = get_ptr<volatile u32>(range.start, true);
|
volatile u32* first = get_ptr<volatile u32>(range.start);
|
||||||
volatile u32* last = get_ptr<volatile u32>(range.end - 3, true);
|
volatile u32* last = get_ptr<volatile u32>(range.end - 3);
|
||||||
|
|
||||||
*first = range.start;
|
*first = range.start;
|
||||||
*last = range.end;
|
*last = range.end;
|
||||||
|
|
||||||
flush_ptr(range.start, 4);
|
|
||||||
flush_ptr(range.end - 3, 4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -392,7 +348,7 @@ namespace rsx
|
|||||||
if (guard_policy == protect_policy_full_range)
|
if (guard_policy == protect_policy_full_range)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
AUDIT(locked && super_ptr);
|
AUDIT(locked);
|
||||||
|
|
||||||
const auto& range = get_confirmed_range();
|
const auto& range = get_confirmed_range();
|
||||||
volatile const u32* first = get_ptr<volatile const u32>(range.start);
|
volatile const u32* first = get_ptr<volatile const u32>(range.start);
|
||||||
@ -404,7 +360,7 @@ namespace rsx
|
|||||||
if (guard_policy == protect_policy_full_range)
|
if (guard_policy == protect_policy_full_range)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
AUDIT(locked && super_ptr);
|
AUDIT(locked);
|
||||||
|
|
||||||
const auto& range = get_confirmed_range();
|
const auto& range = get_confirmed_range();
|
||||||
volatile const u32* last = get_ptr<volatile const u32>(range.end-3);
|
volatile const u32* last = get_ptr<volatile const u32>(range.end-3);
|
||||||
@ -510,7 +466,7 @@ namespace rsx
|
|||||||
ref_cnt--;
|
ref_cnt--;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void set_limit(u32 index, u32 limit)
|
virtual void set_limit(u32 index, u32 limit)
|
||||||
{
|
{
|
||||||
ref_cnt++;
|
ref_cnt++;
|
||||||
|
@ -76,94 +76,6 @@ namespace rsx
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
weak_ptr get_super_ptr(const address_range &range)
|
|
||||||
{
|
|
||||||
return get_super_ptr(range.start, range.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
weak_ptr get_super_ptr(u32 addr, u32 len)
|
|
||||||
{
|
|
||||||
verify(HERE), g_current_renderer;
|
|
||||||
|
|
||||||
if (!g_current_renderer->local_super_memory_block.first)
|
|
||||||
{
|
|
||||||
auto block = vm::get(vm::any, 0xC0000000);
|
|
||||||
if (block)
|
|
||||||
{
|
|
||||||
g_current_renderer->local_super_memory_block.first = block->used();
|
|
||||||
g_current_renderer->local_super_memory_block.second = vm::get_super_ptr<u8>(0xC0000000, g_current_renderer->local_super_memory_block.first - 1);
|
|
||||||
|
|
||||||
if (!g_current_renderer->local_super_memory_block.second)
|
|
||||||
{
|
|
||||||
//Disjoint allocation?
|
|
||||||
LOG_ERROR(RSX, "Could not initialize contiguous RSX super-memory");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fmt::throw_exception("RSX memory not mapped!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_current_renderer->local_super_memory_block.second)
|
|
||||||
{
|
|
||||||
if (addr >= 0xC0000000 && (addr + len) <= (0xC0000000 + g_current_renderer->local_super_memory_block.first))
|
|
||||||
{
|
|
||||||
//RSX local
|
|
||||||
return { g_current_renderer->local_super_memory_block.second.get() + (addr - 0xC0000000) };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto cached = g_current_renderer->main_super_memory_block.find(addr);
|
|
||||||
if (cached != g_current_renderer->main_super_memory_block.end())
|
|
||||||
{
|
|
||||||
const auto& _ptr = cached->second;
|
|
||||||
if (_ptr.size() >= len)
|
|
||||||
{
|
|
||||||
return _ptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto result = vm::get_super_ptr<u8>(addr, len - 1))
|
|
||||||
{
|
|
||||||
weak_ptr _ptr = { result, len };
|
|
||||||
auto &ret = g_current_renderer->main_super_memory_block[addr] = std::move(_ptr);
|
|
||||||
return _ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Probably allocated as split blocks. Try to grab separate chunks
|
|
||||||
std::vector<weak_ptr::memory_block_t> blocks;
|
|
||||||
const u32 limit = addr + len;
|
|
||||||
u32 next = addr;
|
|
||||||
u32 remaining = len;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
auto region = vm::get(vm::any, next)->get(next, 1);
|
|
||||||
if (!region.second)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const u32 block_offset = next - region.first;
|
|
||||||
const u32 block_length = std::min(remaining, region.second->size() - block_offset);
|
|
||||||
std::shared_ptr<u8> _ptr = { region.second, region.second->get(block_offset, block_length) };
|
|
||||||
blocks.push_back({_ptr, block_length});
|
|
||||||
|
|
||||||
remaining -= block_length;
|
|
||||||
next = region.first + region.second->size();
|
|
||||||
if (next >= limit)
|
|
||||||
{
|
|
||||||
weak_ptr _ptr = { blocks };
|
|
||||||
auto &ret = g_current_renderer->main_super_memory_block[addr] = std::move(_ptr);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_ERROR(RSX, "Could not get super_ptr for memory block 0x%x+0x%x", addr, len);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fast image scaling routines
|
/* Fast image scaling routines
|
||||||
* Only uses fast nearest scaling and integral scaling factors
|
* Only uses fast nearest scaling and integral scaling factors
|
||||||
* T - Dst type
|
* T - Dst type
|
||||||
|
@ -39,184 +39,6 @@ namespace rsx
|
|||||||
void reset_refs() { deref_count = 0; }
|
void reset_refs() { deref_count = 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
//Weak pointer without lock semantics
|
|
||||||
//Backed by a real shared_ptr for non-rsx memory
|
|
||||||
//Backed by a global shared pool for rsx memory
|
|
||||||
class weak_ptr
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using memory_block_t = std::pair<std::shared_ptr<u8>, u32>;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void* _ptr = nullptr;
|
|
||||||
std::vector<memory_block_t> _blocks;
|
|
||||||
std::vector<u8> io_cache;
|
|
||||||
bool contiguous = true;
|
|
||||||
bool synchronized = true;
|
|
||||||
|
|
||||||
public:
|
|
||||||
weak_ptr(void* raw, bool is_rsx_mem = true)
|
|
||||||
{
|
|
||||||
_ptr = raw;
|
|
||||||
|
|
||||||
if (!is_rsx_mem)
|
|
||||||
{
|
|
||||||
_blocks.push_back({});
|
|
||||||
_blocks.back().first.reset((u8*)raw);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
weak_ptr(std::shared_ptr<u8>& block, u32 size)
|
|
||||||
{
|
|
||||||
_blocks.push_back({ block, size });
|
|
||||||
_ptr = block.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
weak_ptr(std::vector<memory_block_t>& blocks)
|
|
||||||
{
|
|
||||||
verify(HERE), blocks.size() > 0;
|
|
||||||
|
|
||||||
_blocks = std::move(blocks);
|
|
||||||
_ptr = nullptr;
|
|
||||||
|
|
||||||
if (blocks.size() == 1)
|
|
||||||
{
|
|
||||||
_ptr = _blocks[0].first.get();
|
|
||||||
contiguous = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
u32 block_length = 0;
|
|
||||||
for (const auto &block : _blocks)
|
|
||||||
{
|
|
||||||
block_length += block.second;
|
|
||||||
}
|
|
||||||
|
|
||||||
io_cache.resize(block_length);
|
|
||||||
contiguous = false;
|
|
||||||
synchronized = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
weak_ptr()
|
|
||||||
{
|
|
||||||
_ptr = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T = void>
|
|
||||||
T* get(u32 offset = 0, bool no_sync = false)
|
|
||||||
{
|
|
||||||
if (contiguous)
|
|
||||||
{
|
|
||||||
return (T*)((u8*)_ptr + offset);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!synchronized && !no_sync)
|
|
||||||
sync();
|
|
||||||
|
|
||||||
return (T*)(io_cache.data() + offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void sync()
|
|
||||||
{
|
|
||||||
if (synchronized)
|
|
||||||
return;
|
|
||||||
|
|
||||||
u8* dst = (u8*)io_cache.data();
|
|
||||||
for (const auto &block : _blocks)
|
|
||||||
{
|
|
||||||
memcpy(dst, block.first.get(), block.second);
|
|
||||||
dst += block.second;
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void flush(u32 offset = 0, u32 len = 0) const
|
|
||||||
{
|
|
||||||
if (contiguous)
|
|
||||||
return;
|
|
||||||
|
|
||||||
u8* src = (u8*)io_cache.data();
|
|
||||||
|
|
||||||
if (!offset && (!len || len == io_cache.size()))
|
|
||||||
{
|
|
||||||
for (const auto &block : _blocks)
|
|
||||||
{
|
|
||||||
memcpy(block.first.get(), src, block.second);
|
|
||||||
src += block.second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto remaining_bytes = len? len : io_cache.size() - offset;
|
|
||||||
const auto write_end = remaining_bytes + offset;
|
|
||||||
|
|
||||||
u32 write_offset;
|
|
||||||
u32 write_length;
|
|
||||||
u32 base_offset = 0;
|
|
||||||
|
|
||||||
for (const auto &block : _blocks)
|
|
||||||
{
|
|
||||||
const u32 block_end = base_offset + block.second;
|
|
||||||
|
|
||||||
if (offset >= base_offset && offset < block_end)
|
|
||||||
{
|
|
||||||
// Head
|
|
||||||
write_offset = (offset - base_offset);
|
|
||||||
write_length = std::min<u32>(block.second - write_offset, (u32)remaining_bytes);
|
|
||||||
}
|
|
||||||
else if (base_offset > offset && block_end <= write_end)
|
|
||||||
{
|
|
||||||
// Completely spanned
|
|
||||||
write_offset = 0;
|
|
||||||
write_length = block.second;
|
|
||||||
}
|
|
||||||
else if (base_offset > offset && write_end < block_end)
|
|
||||||
{
|
|
||||||
// Tail
|
|
||||||
write_offset = 0;
|
|
||||||
write_length = (u32)remaining_bytes;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// No overlap; skip
|
|
||||||
write_length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (write_length)
|
|
||||||
{
|
|
||||||
memcpy(block.first.get() + write_offset, src + (base_offset + write_offset), write_length);
|
|
||||||
|
|
||||||
verify(HERE), write_length <= remaining_bytes;
|
|
||||||
remaining_bytes -= write_length;
|
|
||||||
if (!remaining_bytes)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
base_offset += block.second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 size() const
|
|
||||||
{
|
|
||||||
return contiguous ? _blocks[0].second : (u32)io_cache.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
operator bool() const
|
|
||||||
{
|
|
||||||
return (_ptr != nullptr || _blocks.size() > 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Acquire memory mirror with r/w permissions
|
|
||||||
weak_ptr get_super_ptr(const address_range &range);
|
|
||||||
weak_ptr get_super_ptr(u32 addr, u32 size);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds information about a framebuffer
|
* Holds information about a framebuffer
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user