mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-21 12:05:23 +00:00
commit
a114dbcd76
7 changed files with 123 additions and 42 deletions
|
@ -765,6 +765,14 @@ size_t get_x64_access_size(x64_context* context, x64_op_t op, x64_reg_t reg, siz
|
|||
return d_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback that can be customised by GSRender backends to track memory access.
|
||||
* Backends can protect memory pages and get this callback called when an access
|
||||
* violation is met.
|
||||
* Should return true if the backend handles the access violation.
|
||||
*/
|
||||
std::function<bool(u32 addr)> gfxHandler = [](u32) { return false; };
|
||||
|
||||
bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
|
||||
{
|
||||
auto code = (const u8*)RIP(context);
|
||||
|
@ -774,6 +782,9 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
|
|||
size_t d_size;
|
||||
size_t i_size;
|
||||
|
||||
if (gfxHandler(addr))
|
||||
return true;
|
||||
|
||||
// decode single x64 instruction that causes memory access
|
||||
decode_x64_reg_op(code, op, reg, d_size, i_size);
|
||||
|
||||
|
|
|
@ -425,10 +425,10 @@ namespace vm
|
|||
DWORD old;
|
||||
|
||||
auto protection = f2 & page_writable ? PAGE_READWRITE : (f2 & page_readable ? PAGE_READONLY : PAGE_NOACCESS);
|
||||
if (!VirtualProtect(real_addr, size, protection, &old))
|
||||
if (!VirtualProtect(real_addr, 4096, protection, &old))
|
||||
#else
|
||||
auto protection = f2 & page_writable ? PROT_WRITE | PROT_READ : (f2 & page_readable ? PROT_READ : PROT_NONE);
|
||||
if (mprotect(real_addr, size, protection))
|
||||
if (mprotect(real_addr, 4096, protection))
|
||||
#endif
|
||||
{
|
||||
throw fmt::format("vm::page_protect(addr=0x%x, size=0x%x, flags_test=0x%x, flags_set=0x%x, flags_clear=0x%x) failed (API)", addr, size, flags_test, flags_set, flags_clear);
|
||||
|
|
|
@ -1599,7 +1599,7 @@ void GLGSRender::InitDrawBuffers()
|
|||
}
|
||||
}
|
||||
|
||||
void GLGSRender::ExecCMD(u32 cmd)
|
||||
void GLGSRender::Clear(u32 cmd)
|
||||
{
|
||||
assert(cmd == NV4097_CLEAR_SURFACE);
|
||||
|
||||
|
@ -1653,7 +1653,7 @@ void GLGSRender::ExecCMD(u32 cmd)
|
|||
WriteBuffers();
|
||||
}
|
||||
|
||||
void GLGSRender::ExecCMD()
|
||||
void GLGSRender::Draw()
|
||||
{
|
||||
//return;
|
||||
if (!LoadProgram())
|
||||
|
@ -1966,9 +1966,9 @@ void GLGSRender::ExecCMD()
|
|||
m_vao.Bind();
|
||||
|
||||
if (m_indexed_array.m_count)
|
||||
{
|
||||
LoadVertexData(m_indexed_array.index_min, m_indexed_array.index_max - m_indexed_array.index_min + 1);
|
||||
}
|
||||
else
|
||||
LoadVertexData(m_draw_array_first, m_draw_array_count);
|
||||
|
||||
if (m_indexed_array.m_count || m_draw_array_count)
|
||||
{
|
||||
|
@ -2143,6 +2143,21 @@ void GLGSRender::Flip()
|
|||
|
||||
}
|
||||
|
||||
void GLGSRender::semaphorePGRAPHTextureReadRelease(u32 offset, u32 value)
|
||||
{
|
||||
vm::write32(m_label_addr + offset, value);
|
||||
}
|
||||
|
||||
void GLGSRender::semaphorePGRAPHBackendRelease(u32 offset, u32 value)
|
||||
{
|
||||
vm::write32(m_label_addr + offset, value);
|
||||
}
|
||||
|
||||
void GLGSRender::semaphorePFIFOAcquire(u32 offset, u32 value)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
u32 LinearToSwizzleAddress(u32 x, u32 y, u32 z, u32 log2_width, u32 log2_height, u32 log2_depth)
|
||||
{
|
||||
u32 offset = 0;
|
||||
|
|
|
@ -194,7 +194,11 @@ protected:
|
|||
virtual void OnInitThread();
|
||||
virtual void OnExitThread();
|
||||
virtual void OnReset();
|
||||
virtual void ExecCMD(u32 cmd);
|
||||
virtual void ExecCMD();
|
||||
virtual void Clear(u32 cmd) override;
|
||||
virtual void Draw() override;
|
||||
virtual void Flip();
|
||||
|
||||
virtual void semaphorePGRAPHTextureReadRelease(u32 offset, u32 value) override;
|
||||
virtual void semaphorePGRAPHBackendRelease(u32 offset, u32 value) override;
|
||||
virtual void semaphorePFIFOAcquire(u32 offset, u32 value) override;
|
||||
};
|
||||
|
|
|
@ -31,11 +31,11 @@ private:
|
|||
{
|
||||
}
|
||||
|
||||
virtual void ExecCMD(u32 cmd)
|
||||
virtual void Clear(u32 cmd) override
|
||||
{
|
||||
}
|
||||
|
||||
virtual void ExecCMD()
|
||||
virtual void Draw() override
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -46,4 +46,16 @@ private:
|
|||
virtual void Close()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void semaphorePGRAPHTextureReadRelease(u32 offset, u32 value) override
|
||||
{
|
||||
}
|
||||
|
||||
virtual void semaphorePGRAPHBackendRelease(u32 offset, u32 value) override
|
||||
{
|
||||
}
|
||||
|
||||
virtual void semaphorePFIFOAcquire(u32 offset, u32 value) override
|
||||
{
|
||||
}
|
||||
};
|
|
@ -201,43 +201,40 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
}
|
||||
|
||||
case NV4097_SET_SEMAPHORE_OFFSET:
|
||||
{
|
||||
m_PGRAPH_semaphore_offset = ARGS(0);
|
||||
break;
|
||||
}
|
||||
|
||||
case NV406E_SEMAPHORE_OFFSET:
|
||||
{
|
||||
m_set_semaphore_offset = true;
|
||||
m_semaphore_offset = ARGS(0);
|
||||
m_PFIFO_semaphore_offset = ARGS(0);
|
||||
break;
|
||||
}
|
||||
|
||||
case NV406E_SEMAPHORE_ACQUIRE:
|
||||
{
|
||||
if (ARGS(0))
|
||||
{
|
||||
LOG_WARNING(RSX, "TODO: NV406E_SEMAPHORE_ACQUIRE: 0x%x", ARGS(0));
|
||||
}
|
||||
semaphorePFIFOAcquire(m_PFIFO_semaphore_offset, ARGS(0));
|
||||
break;
|
||||
}
|
||||
|
||||
case NV406E_SEMAPHORE_RELEASE:
|
||||
{
|
||||
m_PFIFO_semaphore_release_value = ARGS(0);
|
||||
break;
|
||||
}
|
||||
|
||||
case NV4097_TEXTURE_READ_SEMAPHORE_RELEASE:
|
||||
{
|
||||
if (m_set_semaphore_offset)
|
||||
{
|
||||
m_set_semaphore_offset = false;
|
||||
vm::write32(m_label_addr + m_semaphore_offset, ARGS(0));
|
||||
}
|
||||
semaphorePGRAPHTextureReadRelease(m_PGRAPH_semaphore_offset, ARGS(0));
|
||||
break;
|
||||
}
|
||||
|
||||
case NV4097_BACK_END_WRITE_SEMAPHORE_RELEASE:
|
||||
{
|
||||
if (m_set_semaphore_offset)
|
||||
{
|
||||
m_set_semaphore_offset = false;
|
||||
u32 value = ARGS(0);
|
||||
value = (value & 0xff00ff00) | ((value & 0xff) << 16) | ((value >> 16) & 0xff);
|
||||
|
||||
vm::write32(m_label_addr + m_semaphore_offset, value);
|
||||
}
|
||||
u32 value = ARGS(0);
|
||||
value = (value & 0xff00ff00) | ((value & 0xff) << 16) | ((value >> 16) & 0xff);
|
||||
semaphorePGRAPHBackendRelease(m_PGRAPH_semaphore_offset, value);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -850,7 +847,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
if (a0 & 0x80) m_clear_surface_color_a = m_clear_color_a;
|
||||
|
||||
m_clear_surface_mask = a0;
|
||||
ExecCMD(NV4097_CLEAR_SURFACE);
|
||||
Clear(NV4097_CLEAR_SURFACE);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -910,8 +907,6 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
|
||||
//LOG_WARNING(RSX, "NV4097_DRAW_ARRAYS: %d - %d", first, _count);
|
||||
|
||||
LoadVertexData(first, _count);
|
||||
|
||||
if (first < m_draw_array_first)
|
||||
{
|
||||
m_draw_array_first = first;
|
||||
|
@ -942,10 +937,10 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
|
||||
switch (m_indexed_array.m_type)
|
||||
{
|
||||
case 0:
|
||||
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32:
|
||||
m_indexed_array.m_data.resize(pos + 4 * _count);
|
||||
break;
|
||||
case 1:
|
||||
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
|
||||
m_indexed_array.m_data.resize(pos + 2 * _count);
|
||||
break;
|
||||
}
|
||||
|
@ -955,12 +950,12 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
u32 index;
|
||||
switch(m_indexed_array.m_type)
|
||||
{
|
||||
case 0:
|
||||
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32:
|
||||
index = vm::read32(m_indexed_array.m_addr + i * 4);
|
||||
*(u32*)&m_indexed_array.m_data[i * 4] = index;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
|
||||
index = vm::read16(m_indexed_array.m_addr + i * 2);
|
||||
*(u16*)&m_indexed_array.m_data[i * 2] = index;
|
||||
break;
|
||||
|
@ -1177,6 +1172,12 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
break;
|
||||
}
|
||||
|
||||
case NV4097_SET_NO_PARANOID_TEXTURE_FETCHES:
|
||||
{
|
||||
// Nothing to do here
|
||||
break;
|
||||
}
|
||||
|
||||
case NV4097_INVALIDATE_VERTEX_CACHE_FILE:
|
||||
{
|
||||
// Nothing to do here
|
||||
|
@ -2415,7 +2416,7 @@ void RSXThread::Begin(u32 draw_mode)
|
|||
|
||||
void RSXThread::End()
|
||||
{
|
||||
ExecCMD();
|
||||
Draw();
|
||||
|
||||
for (auto &vdata : m_vertex_data)
|
||||
{
|
||||
|
|
|
@ -343,8 +343,11 @@ public:
|
|||
s32 m_color_conv_dtdy;
|
||||
|
||||
// Semaphore
|
||||
bool m_set_semaphore_offset;
|
||||
u32 m_semaphore_offset;
|
||||
// PGRAPH
|
||||
u32 m_PGRAPH_semaphore_offset;
|
||||
//PFIFO
|
||||
u32 m_PFIFO_semaphore_offset;
|
||||
u32 m_PFIFO_semaphore_release_value;
|
||||
|
||||
// Fog
|
||||
bool m_set_fog_mode;
|
||||
|
@ -597,7 +600,6 @@ protected:
|
|||
m_set_line_width = false;
|
||||
m_set_line_smooth = false;
|
||||
m_set_shade_mode = false;
|
||||
m_set_semaphore_offset = false;
|
||||
m_set_fog_mode = false;
|
||||
m_set_fog_params = false;
|
||||
m_set_clip_plane = false;
|
||||
|
@ -644,10 +646,46 @@ protected:
|
|||
virtual void OnInitThread() = 0;
|
||||
virtual void OnExitThread() = 0;
|
||||
virtual void OnReset() = 0;
|
||||
virtual void ExecCMD() = 0;
|
||||
virtual void ExecCMD(u32 cmd) = 0;
|
||||
|
||||
/**
|
||||
* This member is called when the backend is expected to render a draw call, either
|
||||
* indexed or not.
|
||||
*/
|
||||
virtual void Draw() = 0;
|
||||
|
||||
/**
|
||||
* This member is called when the backend is expected to clear a target surface.
|
||||
*/
|
||||
virtual void Clear(u32 cmd) = 0;
|
||||
|
||||
/**
|
||||
* This member is called when the backend is expected to present a target surface in
|
||||
* either local or main memory.
|
||||
*/
|
||||
virtual void Flip() = 0;
|
||||
|
||||
/**
|
||||
* This member is called when RSXThread parse a TEXTURE_READ_SEMAPHORE_RELEASE
|
||||
* command.
|
||||
* Backend is expected to write value at offset when current draw textures aren't
|
||||
* needed anymore by the GPU and can be modified.
|
||||
*/
|
||||
virtual void semaphorePGRAPHTextureReadRelease(u32 offset, u32 value) = 0;
|
||||
/**
|
||||
* This member is called when RSXThread parse a BACK_END_WRITE_SEMAPHORE_RELEASE
|
||||
* command.
|
||||
* Backend is expected to write value at offset when current draw call has completed
|
||||
* and render surface can be used.
|
||||
*/
|
||||
virtual void semaphorePGRAPHBackendRelease(u32 offset, u32 value) = 0;
|
||||
/**
|
||||
* This member is called when RSXThread parse a SEMAPHORE_ACQUIRE command.
|
||||
* Backend and associated GPU is expected to wait that memory at offset is the same
|
||||
* as value. In particular buffer/texture buffers value can change while backend is
|
||||
* waiting.
|
||||
*/
|
||||
virtual void semaphorePFIFOAcquire(u32 offset, u32 value) = 0;
|
||||
|
||||
void LoadVertexData(u32 first, u32 count)
|
||||
{
|
||||
for (u32 i = 0; i < m_vertex_count; ++i)
|
||||
|
|
Loading…
Add table
Reference in a new issue