From 288581cb43aafd9ad2b528d471b010a8fd891026 Mon Sep 17 00:00:00 2001 From: vlj Date: Tue, 26 May 2015 18:35:56 +0200 Subject: [PATCH 1/7] RSX/GL/Null: Move semaphore handling to backend --- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 15 +++++++++++++ rpcs3/Emu/RSX/GL/GLGSRender.h | 4 ++++ rpcs3/Emu/RSX/Null/NullGSRender.h | 12 +++++++++++ rpcs3/Emu/RSX/RSXThread.cpp | 35 ++++++++++++++----------------- rpcs3/Emu/RSX/RSXThread.h | 30 +++++++++++++++++++++++--- 5 files changed, 74 insertions(+), 22 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index fc37fee9b8..40f319f68b 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -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; diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index 495f940172..828a3bcf20 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -197,4 +197,8 @@ protected: virtual void ExecCMD(u32 cmd); virtual void ExecCMD(); 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; }; diff --git a/rpcs3/Emu/RSX/Null/NullGSRender.h b/rpcs3/Emu/RSX/Null/NullGSRender.h index 33875cbabe..4644856b73 100644 --- a/rpcs3/Emu/RSX/Null/NullGSRender.h +++ b/rpcs3/Emu/RSX/Null/NullGSRender.h @@ -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 + { + } }; \ No newline at end of file diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index f204dfbd9c..754d50511e 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -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; } diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 7556f40565..7e2990ea0e 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -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; @@ -648,6 +650,28 @@ protected: virtual void ExecCMD(u32 cmd) = 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) { for (u32 i = 0; i < m_vertex_count; ++i) From 4485e6b8695be4cdce3c56d325ff6768d1f784d7 Mon Sep 17 00:00:00 2001 From: vlj Date: Mon, 8 Jun 2015 20:09:44 +0200 Subject: [PATCH 2/7] RSX: Do not emit error when parsing NV4097_SET_NO_PARANOID_TEXTURE_FETCHES This opcode disables whole quad fetch on RSX, this is handled by drivers on PC api. --- rpcs3/Emu/RSX/RSXThread.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 754d50511e..b8a6187513 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -1174,6 +1174,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 From 5abeec85ccd63d7cf819033020630ef5e3268dce Mon Sep 17 00:00:00 2001 From: vlj Date: Wed, 3 Jun 2015 18:49:49 +0200 Subject: [PATCH 3/7] GL/RSX: Let backend call LoadVertex themselves. --- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 4 ++-- rpcs3/Emu/RSX/RSXThread.cpp | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 40f319f68b..33c891e248 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -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) { diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index b8a6187513..3c6742a4f1 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -907,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; From 3a0894aaeab34f20e9f00bcac8c383fba8771ee2 Mon Sep 17 00:00:00 2001 From: raven02 Date: Tue, 9 Jun 2015 16:41:40 +0800 Subject: [PATCH 4/7] RSX: Use CELL_GCM suffix for index array --- rpcs3/Emu/RSX/RSXThread.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 3c6742a4f1..04bbe9aaa0 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -937,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; } @@ -950,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; From 4a7f6af8d97ff959a74b967218ea110908cf18ac Mon Sep 17 00:00:00 2001 From: vlj Date: Thu, 2 Jul 2015 19:05:27 +0200 Subject: [PATCH 5/7] Memory: Add a callback allowing customisation of handle_access_violation. --- Utilities/Thread.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index 3c04019ddf..9f7eb958bf 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -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 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); From 972515938c945b55813e8d9fb1f87470c443373a Mon Sep 17 00:00:00 2001 From: vlj Date: Thu, 2 Jul 2015 19:05:54 +0200 Subject: [PATCH 6/7] Memory: Fix virtualProtect protecting too much memory. --- rpcs3/Emu/Memory/vm.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 623f1489fb..ef10b43fe6 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -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); From f4efeabcf34af5ff062714c7dc9711721d919631 Mon Sep 17 00:00:00 2001 From: vlj Date: Thu, 2 Jul 2015 18:52:58 +0200 Subject: [PATCH 7/7] RSX: Rename and document function member. --- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 4 ++-- rpcs3/Emu/RSX/GL/GLGSRender.h | 4 ++-- rpcs3/Emu/RSX/Null/NullGSRender.h | 4 ++-- rpcs3/Emu/RSX/RSXThread.cpp | 4 ++-- rpcs3/Emu/RSX/RSXThread.h | 18 ++++++++++++++++-- 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 33c891e248..08adde2fb3 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -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()) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index 828a3bcf20..f1ea9cb83f 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -194,8 +194,8 @@ 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; diff --git a/rpcs3/Emu/RSX/Null/NullGSRender.h b/rpcs3/Emu/RSX/Null/NullGSRender.h index 4644856b73..a68e70a44e 100644 --- a/rpcs3/Emu/RSX/Null/NullGSRender.h +++ b/rpcs3/Emu/RSX/Null/NullGSRender.h @@ -31,11 +31,11 @@ private: { } - virtual void ExecCMD(u32 cmd) + virtual void Clear(u32 cmd) override { } - virtual void ExecCMD() + virtual void Draw() override { } diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 04bbe9aaa0..e50f2ad5f2 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -847,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; } @@ -2416,7 +2416,7 @@ void RSXThread::Begin(u32 draw_mode) void RSXThread::End() { - ExecCMD(); + Draw(); for (auto &vdata : m_vertex_data) { diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 7e2990ea0e..aa3f74e83f 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -646,8 +646,22 @@ 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; /**