mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-09 08:21:29 +12: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;
|
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)
|
bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
|
||||||
{
|
{
|
||||||
auto code = (const u8*)RIP(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 d_size;
|
||||||
size_t i_size;
|
size_t i_size;
|
||||||
|
|
||||||
|
if (gfxHandler(addr))
|
||||||
|
return true;
|
||||||
|
|
||||||
// decode single x64 instruction that causes memory access
|
// decode single x64 instruction that causes memory access
|
||||||
decode_x64_reg_op(code, op, reg, d_size, i_size);
|
decode_x64_reg_op(code, op, reg, d_size, i_size);
|
||||||
|
|
||||||
|
|
|
@ -425,10 +425,10 @@ namespace vm
|
||||||
DWORD old;
|
DWORD old;
|
||||||
|
|
||||||
auto protection = f2 & page_writable ? PAGE_READWRITE : (f2 & page_readable ? PAGE_READONLY : PAGE_NOACCESS);
|
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
|
#else
|
||||||
auto protection = f2 & page_writable ? PROT_WRITE | PROT_READ : (f2 & page_readable ? PROT_READ : PROT_NONE);
|
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
|
#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);
|
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);
|
assert(cmd == NV4097_CLEAR_SURFACE);
|
||||||
|
|
||||||
|
@ -1653,7 +1653,7 @@ void GLGSRender::ExecCMD(u32 cmd)
|
||||||
WriteBuffers();
|
WriteBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGSRender::ExecCMD()
|
void GLGSRender::Draw()
|
||||||
{
|
{
|
||||||
//return;
|
//return;
|
||||||
if (!LoadProgram())
|
if (!LoadProgram())
|
||||||
|
@ -1966,9 +1966,9 @@ void GLGSRender::ExecCMD()
|
||||||
m_vao.Bind();
|
m_vao.Bind();
|
||||||
|
|
||||||
if (m_indexed_array.m_count)
|
if (m_indexed_array.m_count)
|
||||||
{
|
|
||||||
LoadVertexData(m_indexed_array.index_min, m_indexed_array.index_max - m_indexed_array.index_min + 1);
|
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)
|
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 LinearToSwizzleAddress(u32 x, u32 y, u32 z, u32 log2_width, u32 log2_height, u32 log2_depth)
|
||||||
{
|
{
|
||||||
u32 offset = 0;
|
u32 offset = 0;
|
||||||
|
|
|
@ -194,7 +194,11 @@ protected:
|
||||||
virtual void OnInitThread();
|
virtual void OnInitThread();
|
||||||
virtual void OnExitThread();
|
virtual void OnExitThread();
|
||||||
virtual void OnReset();
|
virtual void OnReset();
|
||||||
virtual void ExecCMD(u32 cmd);
|
virtual void Clear(u32 cmd) override;
|
||||||
virtual void ExecCMD();
|
virtual void Draw() override;
|
||||||
virtual void Flip();
|
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 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:
|
case NV4097_SET_SEMAPHORE_OFFSET:
|
||||||
|
{
|
||||||
|
m_PGRAPH_semaphore_offset = ARGS(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case NV406E_SEMAPHORE_OFFSET:
|
case NV406E_SEMAPHORE_OFFSET:
|
||||||
{
|
{
|
||||||
m_set_semaphore_offset = true;
|
m_PFIFO_semaphore_offset = ARGS(0);
|
||||||
m_semaphore_offset = ARGS(0);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case NV406E_SEMAPHORE_ACQUIRE:
|
case NV406E_SEMAPHORE_ACQUIRE:
|
||||||
{
|
{
|
||||||
if (ARGS(0))
|
semaphorePFIFOAcquire(m_PFIFO_semaphore_offset, ARGS(0));
|
||||||
{
|
|
||||||
LOG_WARNING(RSX, "TODO: NV406E_SEMAPHORE_ACQUIRE: 0x%x", ARGS(0));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case NV406E_SEMAPHORE_RELEASE:
|
case NV406E_SEMAPHORE_RELEASE:
|
||||||
|
{
|
||||||
|
m_PFIFO_semaphore_release_value = ARGS(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case NV4097_TEXTURE_READ_SEMAPHORE_RELEASE:
|
case NV4097_TEXTURE_READ_SEMAPHORE_RELEASE:
|
||||||
{
|
{
|
||||||
if (m_set_semaphore_offset)
|
semaphorePGRAPHTextureReadRelease(m_PGRAPH_semaphore_offset, ARGS(0));
|
||||||
{
|
|
||||||
m_set_semaphore_offset = false;
|
|
||||||
vm::write32(m_label_addr + m_semaphore_offset, ARGS(0));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case NV4097_BACK_END_WRITE_SEMAPHORE_RELEASE:
|
case NV4097_BACK_END_WRITE_SEMAPHORE_RELEASE:
|
||||||
{
|
{
|
||||||
if (m_set_semaphore_offset)
|
u32 value = ARGS(0);
|
||||||
{
|
value = (value & 0xff00ff00) | ((value & 0xff) << 16) | ((value >> 16) & 0xff);
|
||||||
m_set_semaphore_offset = false;
|
semaphorePGRAPHBackendRelease(m_PGRAPH_semaphore_offset, value);
|
||||||
u32 value = ARGS(0);
|
|
||||||
value = (value & 0xff00ff00) | ((value & 0xff) << 16) | ((value >> 16) & 0xff);
|
|
||||||
|
|
||||||
vm::write32(m_label_addr + m_semaphore_offset, value);
|
|
||||||
}
|
|
||||||
break;
|
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;
|
if (a0 & 0x80) m_clear_surface_color_a = m_clear_color_a;
|
||||||
|
|
||||||
m_clear_surface_mask = a0;
|
m_clear_surface_mask = a0;
|
||||||
ExecCMD(NV4097_CLEAR_SURFACE);
|
Clear(NV4097_CLEAR_SURFACE);
|
||||||
break;
|
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);
|
//LOG_WARNING(RSX, "NV4097_DRAW_ARRAYS: %d - %d", first, _count);
|
||||||
|
|
||||||
LoadVertexData(first, _count);
|
|
||||||
|
|
||||||
if (first < m_draw_array_first)
|
if (first < m_draw_array_first)
|
||||||
{
|
{
|
||||||
m_draw_array_first = 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)
|
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);
|
m_indexed_array.m_data.resize(pos + 4 * _count);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
|
||||||
m_indexed_array.m_data.resize(pos + 2 * _count);
|
m_indexed_array.m_data.resize(pos + 2 * _count);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -955,12 +950,12 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
||||||
u32 index;
|
u32 index;
|
||||||
switch(m_indexed_array.m_type)
|
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);
|
index = vm::read32(m_indexed_array.m_addr + i * 4);
|
||||||
*(u32*)&m_indexed_array.m_data[i * 4] = index;
|
*(u32*)&m_indexed_array.m_data[i * 4] = index;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
|
||||||
index = vm::read16(m_indexed_array.m_addr + i * 2);
|
index = vm::read16(m_indexed_array.m_addr + i * 2);
|
||||||
*(u16*)&m_indexed_array.m_data[i * 2] = index;
|
*(u16*)&m_indexed_array.m_data[i * 2] = index;
|
||||||
break;
|
break;
|
||||||
|
@ -1177,6 +1172,12 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case NV4097_SET_NO_PARANOID_TEXTURE_FETCHES:
|
||||||
|
{
|
||||||
|
// Nothing to do here
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case NV4097_INVALIDATE_VERTEX_CACHE_FILE:
|
case NV4097_INVALIDATE_VERTEX_CACHE_FILE:
|
||||||
{
|
{
|
||||||
// Nothing to do here
|
// Nothing to do here
|
||||||
|
@ -2415,7 +2416,7 @@ void RSXThread::Begin(u32 draw_mode)
|
||||||
|
|
||||||
void RSXThread::End()
|
void RSXThread::End()
|
||||||
{
|
{
|
||||||
ExecCMD();
|
Draw();
|
||||||
|
|
||||||
for (auto &vdata : m_vertex_data)
|
for (auto &vdata : m_vertex_data)
|
||||||
{
|
{
|
||||||
|
|
|
@ -343,8 +343,11 @@ public:
|
||||||
s32 m_color_conv_dtdy;
|
s32 m_color_conv_dtdy;
|
||||||
|
|
||||||
// Semaphore
|
// Semaphore
|
||||||
bool m_set_semaphore_offset;
|
// PGRAPH
|
||||||
u32 m_semaphore_offset;
|
u32 m_PGRAPH_semaphore_offset;
|
||||||
|
//PFIFO
|
||||||
|
u32 m_PFIFO_semaphore_offset;
|
||||||
|
u32 m_PFIFO_semaphore_release_value;
|
||||||
|
|
||||||
// Fog
|
// Fog
|
||||||
bool m_set_fog_mode;
|
bool m_set_fog_mode;
|
||||||
|
@ -597,7 +600,6 @@ protected:
|
||||||
m_set_line_width = false;
|
m_set_line_width = false;
|
||||||
m_set_line_smooth = false;
|
m_set_line_smooth = false;
|
||||||
m_set_shade_mode = false;
|
m_set_shade_mode = false;
|
||||||
m_set_semaphore_offset = false;
|
|
||||||
m_set_fog_mode = false;
|
m_set_fog_mode = false;
|
||||||
m_set_fog_params = false;
|
m_set_fog_params = false;
|
||||||
m_set_clip_plane = false;
|
m_set_clip_plane = false;
|
||||||
|
@ -644,10 +646,46 @@ protected:
|
||||||
virtual void OnInitThread() = 0;
|
virtual void OnInitThread() = 0;
|
||||||
virtual void OnExitThread() = 0;
|
virtual void OnExitThread() = 0;
|
||||||
virtual void OnReset() = 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;
|
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)
|
void LoadVertexData(u32 first, u32 count)
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < m_vertex_count; ++i)
|
for (u32 i = 0; i < m_vertex_count; ++i)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue