mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-30 21:32:50 +00:00
rsx: Fix segmented memory access for rsx::super_ptr
This commit is contained in:
parent
d283200e13
commit
fbf6581249
@ -559,6 +559,7 @@ namespace gl
|
||||
}
|
||||
}
|
||||
|
||||
flush_io();
|
||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, GL_NONE);
|
||||
|
||||
|
@ -323,6 +323,7 @@ namespace vk
|
||||
}
|
||||
}
|
||||
|
||||
flush_io();
|
||||
dma_buffer->unmap();
|
||||
reset_write_statistics();
|
||||
|
||||
|
@ -43,6 +43,8 @@ namespace rsx
|
||||
|
||||
*first = cpu_address_base + confirmed_range.first;
|
||||
*last = cpu_address_base + valid_limit - 4;
|
||||
|
||||
locked_memory_ptr.flush();
|
||||
}
|
||||
}
|
||||
|
||||
@ -319,13 +321,13 @@ namespace rsx
|
||||
}
|
||||
|
||||
template <typename T = void>
|
||||
T* get_raw_ptr(u32 offset = 0) const
|
||||
T* get_raw_ptr(u32 offset = 0)
|
||||
{
|
||||
verify(HERE), locked_memory_ptr;
|
||||
return locked_memory_ptr.get<T>(offset);
|
||||
}
|
||||
|
||||
bool test_memory_head() const
|
||||
bool test_memory_head()
|
||||
{
|
||||
if (!locked_memory_ptr)
|
||||
{
|
||||
@ -336,7 +338,7 @@ namespace rsx
|
||||
return (*first == (cpu_address_base + confirmed_range.first));
|
||||
}
|
||||
|
||||
bool test_memory_tail() const
|
||||
bool test_memory_tail()
|
||||
{
|
||||
if (!locked_memory_ptr)
|
||||
{
|
||||
@ -348,6 +350,11 @@ namespace rsx
|
||||
return (*last == (cpu_address_base + valid_limit - 4));
|
||||
}
|
||||
|
||||
void flush_io() const
|
||||
{
|
||||
locked_memory_ptr.flush();
|
||||
}
|
||||
|
||||
std::pair<u32, u32> get_confirmed_range() const
|
||||
{
|
||||
if (confirmed_range.second == 0)
|
||||
|
@ -109,14 +109,40 @@ namespace rsx
|
||||
}
|
||||
}
|
||||
|
||||
auto result = vm::get_super_ptr<u8>(addr, len - 1);
|
||||
if (!result)
|
||||
if (auto result = vm::get_super_ptr<u8>(addr, len - 1))
|
||||
{
|
||||
//Probably allocated as split blocks??
|
||||
LOG_ERROR(RSX, "Could not get super_ptr for memory block 0x%x+0x%x", addr, len);
|
||||
return { result };
|
||||
}
|
||||
|
||||
return { result };
|
||||
//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)
|
||||
{
|
||||
return { blocks };
|
||||
}
|
||||
}
|
||||
|
||||
LOG_ERROR(RSX, "Could not get super_ptr for memory block 0x%x+0x%x", addr, len);
|
||||
return {};
|
||||
}
|
||||
|
||||
/* Fast image scaling routines
|
||||
|
@ -35,21 +35,60 @@ namespace rsx
|
||||
//Weak pointer without lock semantics
|
||||
//Backed by a real shared_ptr for non-rsx memory
|
||||
//Backed by a global shared pool for rsx memory
|
||||
struct weak_ptr
|
||||
class weak_ptr
|
||||
{
|
||||
void* _ptr;
|
||||
std::shared_ptr<u8> _extern;
|
||||
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) _extern.reset((u8*)raw);
|
||||
|
||||
if (!is_rsx_mem)
|
||||
{
|
||||
_blocks.push_back({});
|
||||
_blocks.back().first.reset((u8*)raw);
|
||||
}
|
||||
}
|
||||
|
||||
weak_ptr(std::shared_ptr<u8>& block)
|
||||
{
|
||||
_extern = block;
|
||||
_ptr = _extern.get();
|
||||
_blocks.push_back({ block, 0 });
|
||||
_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()
|
||||
@ -58,14 +97,52 @@ namespace rsx
|
||||
}
|
||||
|
||||
template <typename T = void>
|
||||
T* get(u32 offset = 0) const
|
||||
T* get(u32 offset = 0)
|
||||
{
|
||||
return (T*)((u8*)_ptr + offset);
|
||||
if (contiguous)
|
||||
{
|
||||
return (T*)((u8*)_ptr + offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!synchronized)
|
||||
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() const
|
||||
{
|
||||
if (contiguous)
|
||||
return;
|
||||
|
||||
u8* src = (u8*)io_cache.data();
|
||||
for (const auto &block : _blocks)
|
||||
{
|
||||
memcpy(block.first.get(), src, block.second);
|
||||
src += block.second;
|
||||
}
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return (_ptr != nullptr);
|
||||
return (_ptr != nullptr || _blocks.size() > 1);
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user