From 5a77cae2e3434fa5cbb3710f183328e36620fa5f Mon Sep 17 00:00:00 2001 From: Pierre Bourdon Date: Fri, 18 May 2012 23:13:53 +0200 Subject: [PATCH 1/5] Check if BP and XF changes actually change values before flushing --- Source/Core/VideoCommon/Src/BPStructs.cpp | 12 ++++- Source/Core/VideoCommon/Src/XFStructs.cpp | 65 +++++++++++++++++------ 2 files changed, 59 insertions(+), 18 deletions(-) diff --git a/Source/Core/VideoCommon/Src/BPStructs.cpp b/Source/Core/VideoCommon/Src/BPStructs.cpp index d59523e117..84f2426f26 100644 --- a/Source/Core/VideoCommon/Src/BPStructs.cpp +++ b/Source/Core/VideoCommon/Src/BPStructs.cpp @@ -128,7 +128,17 @@ void BPWritten(const BPCmd& bp) FlushPipeline(); } } // END ZTP SPEEDUP HACK - else FlushPipeline(); + else + { + if (((s32*)&bpmem)[bp.address] != bp.newvalue) + { + FlushPipeline(); + } + else if (bp.address == BPMEM_TRIGGER_EFB_COPY + || bp.address == BPMEM_CLEARBBOX1 + || bp.address == BPMEM_CLEARBBOX2) + FlushPipeline(); + } ((u32*)&bpmem)[bp.address] = bp.newvalue; diff --git a/Source/Core/VideoCommon/Src/XFStructs.cpp b/Source/Core/VideoCommon/Src/XFStructs.cpp index ec3975cb07..d879c83652 100644 --- a/Source/Core/VideoCommon/Src/XFStructs.cpp +++ b/Source/Core/VideoCommon/Src/XFStructs.cpp @@ -121,12 +121,18 @@ void XFRegWritten(int transferSize, u32 baseAddress, u32 *pData) case XFMEM_SETVIEWPORT+3: case XFMEM_SETVIEWPORT+4: case XFMEM_SETVIEWPORT+5: - VertexManager::Flush(); - VertexShaderManager::SetViewportChanged(); - PixelShaderManager::SetViewportChanged(); + { + u8 size = std::min(transferSize, 6 * 4); + if (memcmp((u32*)&xfregs + (address - 0x1000), pData + dataIndex, size)) + { + VertexManager::Flush(); + VertexShaderManager::SetViewportChanged(); + PixelShaderManager::SetViewportChanged(); + } - nextAddress = XFMEM_SETVIEWPORT + 6; - break; + nextAddress = XFMEM_SETVIEWPORT + 6; + break; + } case XFMEM_SETPROJECTION: case XFMEM_SETPROJECTION+1: @@ -135,11 +141,17 @@ void XFRegWritten(int transferSize, u32 baseAddress, u32 *pData) case XFMEM_SETPROJECTION+4: case XFMEM_SETPROJECTION+5: case XFMEM_SETPROJECTION+6: - VertexManager::Flush(); - VertexShaderManager::SetProjectionChanged(); + { + u8 size = std::min(transferSize, 7 * 4); + if (memcmp((u32*)&xfregs + (address - 0x1000), pData + dataIndex, size)) + { + VertexManager::Flush(); + VertexShaderManager::SetProjectionChanged(); + } - nextAddress = XFMEM_SETPROJECTION + 7; - break; + nextAddress = XFMEM_SETPROJECTION + 7; + break; + } case XFMEM_SETNUMTEXGENS: // GXSetNumTexGens if (xfregs.numTexGen.numTexGens != (newValue & 15)) @@ -154,10 +166,16 @@ void XFRegWritten(int transferSize, u32 baseAddress, u32 *pData) case XFMEM_SETTEXMTXINFO+5: case XFMEM_SETTEXMTXINFO+6: case XFMEM_SETTEXMTXINFO+7: - VertexManager::Flush(); + { + u8 size = std::min(transferSize, 8 * 4); + if (memcmp((u32*)&xfregs + (address - 0x1000), pData + dataIndex, size)) + { + VertexManager::Flush(); + } - nextAddress = XFMEM_SETTEXMTXINFO + 8; - break; + nextAddress = XFMEM_SETTEXMTXINFO + 8; + break; + } case XFMEM_SETPOSMTXINFO: case XFMEM_SETPOSMTXINFO+1: @@ -167,10 +185,16 @@ void XFRegWritten(int transferSize, u32 baseAddress, u32 *pData) case XFMEM_SETPOSMTXINFO+5: case XFMEM_SETPOSMTXINFO+6: case XFMEM_SETPOSMTXINFO+7: - VertexManager::Flush(); + { + u8 size = std::min(transferSize, 8 * 4); + if (memcmp((u32*)&xfregs + (address - 0x1000), pData + dataIndex, size)) + { + VertexManager::Flush(); + } - nextAddress = XFMEM_SETPOSMTXINFO + 8; - break; + nextAddress = XFMEM_SETPOSMTXINFO + 8; + break; + } // -------------- // Unknown Regs @@ -240,8 +264,15 @@ void LoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData) transferSize = 0; } - XFMemWritten(xfMemTransferSize, xfMemBase); - memcpy_gc(&xfmem[xfMemBase], pData, xfMemTransferSize * 4); + for (u32 i = 0; i < xfMemTransferSize; ++i) + { + if (((u32*)&xfmem[xfMemBase])[i] != pData[i]) + { + XFMemWritten(xfMemTransferSize, xfMemBase); + memcpy_gc(&xfmem[xfMemBase], pData, xfMemTransferSize * 4); + break; + } + } pData += xfMemTransferSize; } From b8d4d013f6aa641d823a4a33e1cb09deb06f7f7a Mon Sep 17 00:00:00 2001 From: Pierre Bourdon Date: Fri, 18 May 2012 23:27:02 +0200 Subject: [PATCH 2/5] Compute the comparison size properly (transferSize is in u32, not in u8) --- Source/Core/VideoCommon/Src/XFStructs.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/Core/VideoCommon/Src/XFStructs.cpp b/Source/Core/VideoCommon/Src/XFStructs.cpp index d879c83652..b75e7188af 100644 --- a/Source/Core/VideoCommon/Src/XFStructs.cpp +++ b/Source/Core/VideoCommon/Src/XFStructs.cpp @@ -122,7 +122,7 @@ void XFRegWritten(int transferSize, u32 baseAddress, u32 *pData) case XFMEM_SETVIEWPORT+4: case XFMEM_SETVIEWPORT+5: { - u8 size = std::min(transferSize, 6 * 4); + u8 size = std::min(transferSize * 4, 6 * 4); if (memcmp((u32*)&xfregs + (address - 0x1000), pData + dataIndex, size)) { VertexManager::Flush(); @@ -142,7 +142,7 @@ void XFRegWritten(int transferSize, u32 baseAddress, u32 *pData) case XFMEM_SETPROJECTION+5: case XFMEM_SETPROJECTION+6: { - u8 size = std::min(transferSize, 7 * 4); + u8 size = std::min(transferSize * 4, 7 * 4); if (memcmp((u32*)&xfregs + (address - 0x1000), pData + dataIndex, size)) { VertexManager::Flush(); @@ -167,7 +167,7 @@ void XFRegWritten(int transferSize, u32 baseAddress, u32 *pData) case XFMEM_SETTEXMTXINFO+6: case XFMEM_SETTEXMTXINFO+7: { - u8 size = std::min(transferSize, 8 * 4); + u8 size = std::min(transferSize * 4, 8 * 4); if (memcmp((u32*)&xfregs + (address - 0x1000), pData + dataIndex, size)) { VertexManager::Flush(); @@ -186,7 +186,7 @@ void XFRegWritten(int transferSize, u32 baseAddress, u32 *pData) case XFMEM_SETPOSMTXINFO+6: case XFMEM_SETPOSMTXINFO+7: { - u8 size = std::min(transferSize, 8 * 4); + u8 size = std::min(transferSize * 4, 8 * 4); if (memcmp((u32*)&xfregs + (address - 0x1000), pData + dataIndex, size)) { VertexManager::Flush(); From 7cccb4baa724188ac4af546e2109e988713893aa Mon Sep 17 00:00:00 2001 From: Pierre Bourdon Date: Sat, 19 May 2012 10:54:40 +0200 Subject: [PATCH 3/5] Check if data was modified in LoadIndexedXF too --- Source/Core/VideoCommon/Src/XFStructs.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/Source/Core/VideoCommon/Src/XFStructs.cpp b/Source/Core/VideoCommon/Src/XFStructs.cpp index b75e7188af..cd97271526 100644 --- a/Source/Core/VideoCommon/Src/XFStructs.cpp +++ b/Source/Core/VideoCommon/Src/XFStructs.cpp @@ -288,13 +288,15 @@ void LoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData) // TODO - verify that it is correct. Seems to work, though. void LoadIndexedXF(u32 val, int refarray) { - int index = val >> 16; - int address = val & 0xFFF; // check mask - int size = ((val >> 12) & 0xF) + 1; - //load stuff from array to address in xf mem + int index = val >> 16; + int address = val & 0xFFF; // check mask + int size = ((val >> 12) & 0xF) + 1; + //load stuff from array to address in xf mem - XFMemWritten(size, address); - - for (int i = 0; i < size; i++) - xfmem[address + i] = Memory::Read_U32(arraybases[refarray] + arraystrides[refarray] * index + i * 4); + u32* newData = (u32*)Memory::GetPointer(arraybases[refarray] + arraystrides[refarray] * index); + if (memcmp(xfmem + address, newData, size * 4)) + { + XFMemWritten(size, address); + memcpy_gc(xfmem + address, newData, size * 4); + } } From c95baf614d2699233b7bf7a474d96aa6c4cf2b78 Mon Sep 17 00:00:00 2001 From: Pierre Bourdon Date: Sun, 20 May 2012 20:56:03 +0200 Subject: [PATCH 4/5] Avoid changing video state on useless BP writes When a game writes the same value that was already configured to a BP register, Dolphin previously flushed the GPU pipeline and reconfigured the internal video state (calling SetScissor/SetLineWidth/SetDepthMode). Some of these useless writes still need to perform actions, for example writes to the EFB copy trigger or the texture preload registers (which need to reload the texture from memory). --- Source/Core/VideoCommon/Src/BPStructs.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/Source/Core/VideoCommon/Src/BPStructs.cpp b/Source/Core/VideoCommon/Src/BPStructs.cpp index 84f2426f26..160ee1a61b 100644 --- a/Source/Core/VideoCommon/Src/BPStructs.cpp +++ b/Source/Core/VideoCommon/Src/BPStructs.cpp @@ -130,14 +130,24 @@ void BPWritten(const BPCmd& bp) } // END ZTP SPEEDUP HACK else { - if (((s32*)&bpmem)[bp.address] != bp.newvalue) + if (((s32*)&bpmem)[bp.address] == bp.newvalue) { - FlushPipeline(); + if (!(bp.address == BPMEM_TRIGGER_EFB_COPY + || bp.address == BPMEM_CLEARBBOX1 + || bp.address == BPMEM_CLEARBBOX2 + || bp.address == BPMEM_SETDRAWDONE + || bp.address == BPMEM_PE_TOKEN_ID + || bp.address == BPMEM_PE_TOKEN_INT_ID + || bp.address == BPMEM_LOADTLUT0 + || bp.address == BPMEM_LOADTLUT1 + || bp.address == BPMEM_TEXINVALIDATE + || bp.address == BPMEM_PRELOAD_MODE)) + { + return; + } } - else if (bp.address == BPMEM_TRIGGER_EFB_COPY - || bp.address == BPMEM_CLEARBBOX1 - || bp.address == BPMEM_CLEARBBOX2) - FlushPipeline(); + + FlushPipeline(); } ((u32*)&bpmem)[bp.address] = bp.newvalue; From fee2d83f68d92a6f3b7461b06f4dce2dbd6f1c07 Mon Sep 17 00:00:00 2001 From: Pierre Bourdon Date: Sun, 20 May 2012 22:16:21 +0200 Subject: [PATCH 5/5] Fix a data endianness problem introduced by r7cccb4baa724. --- Source/Core/VideoCommon/Src/XFStructs.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Source/Core/VideoCommon/Src/XFStructs.cpp b/Source/Core/VideoCommon/Src/XFStructs.cpp index cd97271526..f8330604ad 100644 --- a/Source/Core/VideoCommon/Src/XFStructs.cpp +++ b/Source/Core/VideoCommon/Src/XFStructs.cpp @@ -293,10 +293,21 @@ void LoadIndexedXF(u32 val, int refarray) int size = ((val >> 12) & 0xF) + 1; //load stuff from array to address in xf mem + u32* currData = (u32*)(xfmem + address); u32* newData = (u32*)Memory::GetPointer(arraybases[refarray] + arraystrides[refarray] * index); - if (memcmp(xfmem + address, newData, size * 4)) + bool changed = false; + for (int i = 0; i < size; ++i) { - XFMemWritten(size, address); - memcpy_gc(xfmem + address, newData, size * 4); + if (currData[i] != Common::swap32(newData[i])) + { + changed = true; + XFMemWritten(size, address); + break; + } + } + if (changed) + { + for (int i = 0; i < size; ++i) + currData[i] = Common::swap32(newData[i]); } }