Skip to content

Commit

Permalink
More improvements
Browse files Browse the repository at this point in the history
- Support reading PSMZ24 formats (for SSX3)
- Handle transfers with offsets in TRXPOS.
- Fix build issue.
  • Loading branch information
jpd002 committed Aug 3, 2023
1 parent ccf1aff commit bc12688
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 46 deletions.
1 change: 1 addition & 0 deletions Source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ set(COMMON_SRC_FILES
gs/GsPixelFormats.h
gs/GsSpriteRegion.h
gs/GsTextureCache.h
gs/GsTransferRange.h
hdd/ApaDefs.h
hdd/ApaReader.cpp
hdd/ApaReader.h
Expand Down
5 changes: 3 additions & 2 deletions Source/gs/GSH_OpenGL/GSH_OpenGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "../../Log.h"
#include "../../AppConfig.h"
#include "../GsPixelFormats.h"
#include "../GsTransferRange.h"
#include "GSH_OpenGL.h"

#ifdef USE_DUALSOURCE_BLENDING
Expand Down Expand Up @@ -2006,7 +2007,7 @@ void CGSH_OpenGL::ProcessHostToLocalTransfer()
auto trxReg = make_convertible<TRXREG>(m_nReg[GS_REG_TRXREG]);
auto trxPos = make_convertible<TRXPOS>(m_nReg[GS_REG_TRXPOS]);

auto [transferAddress, transferSize] = GetTransferInvalidationRange(bltBuf, trxReg, trxPos);
auto [transferAddress, transferSize] = GsTransfer::GetDstRange(bltBuf, trxReg, trxPos);

m_textureCache.InvalidateRange(transferAddress, transferSize);

Expand Down Expand Up @@ -2120,7 +2121,7 @@ void CGSH_OpenGL::ProcessLocalToLocalTransfer()
// Sample down to requested size
imgbuffer = imgbuffer.Resize(trxReg.nRRW, trxReg.nRRH);

auto [transferAddress, transferSize] = GetTransferInvalidationRange(bltBuf, trxReg, trxPos);
auto [transferAddress, transferSize] = GsTransfer::GetDstRange(bltBuf, trxReg, trxPos);
m_textureCache.InvalidateRange(transferAddress, transferSize);

//Write back to RAM
Expand Down
7 changes: 2 additions & 5 deletions Source/gs/GSH_Vulkan/GSH_Vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <cstring>
#include "std_experimental_map.h"
#include "../GsPixelFormats.h"
#include "../GsTransferRange.h"
#include "../../Log.h"
#include "../../AppConfig.h"
#include "GSH_VulkanPlatformDefs.h"
Expand Down Expand Up @@ -1339,11 +1340,7 @@ void CGSH_Vulkan::ProcessLocalToHostTransfer()
auto transfer = m_xferHistory.find(bltBuf);
transfer->second.MarkUsed();

CGsCachedArea area;
area.SetArea(bltBuf.nSrcPsm, bltBuf.GetSrcPtr(), bltBuf.GetSrcWidth(), trxReg.nRRH);

uint32 copyBase = bltBuf.GetSrcPtr();
uint32 copySize = area.GetSize();
auto [copyBase, copySize] = GsTransfer::GetSrcRange(bltBuf, trxReg, trxPos);

auto& srcBuffer = m_context->memoryBuffer;
auto& dstBuffer = m_context->memoryBufferTransfer;
Expand Down
1 change: 1 addition & 0 deletions Source/gs/GSH_Vulkan/GSH_Vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "GSH_VulkanTransferLocal.h"
#include <vector>
#include <map>
#include <cstring>
#include "../GSHandler.h"
#include "../GsDebuggerInterface.h"
#include "../GsCachedArea.h"
Expand Down
37 changes: 5 additions & 32 deletions Source/gs/GSHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,12 @@ CGSHandler::CGSHandler(bool gsThreaded)
m_transferWriteHandlers[PSMT4HH] = &CGSHandler::TransferWriteHandlerPSMT4H<28, 0xF0000000>;

m_transferReadHandlers[PSMCT32] = &CGSHandler::TransferReadHandlerGeneric<CGsPixelFormats::STORAGEPSMCT32>;
m_transferReadHandlers[PSMCT24] = &CGSHandler::TransferReadHandlerPSMCT24;
m_transferReadHandlers[PSMCT24] = &CGSHandler::TransferReadHandler24<CGsPixelFormats::STORAGEPSMCT32>;
m_transferReadHandlers[PSMCT16] = &CGSHandler::TransferReadHandlerGeneric<CGsPixelFormats::STORAGEPSMCT16>;
m_transferReadHandlers[PSMT8] = &CGSHandler::TransferReadHandlerGeneric<CGsPixelFormats::STORAGEPSMT8>;
m_transferReadHandlers[PSMT8H] = &CGSHandler::TransferReadHandlerPSMT8H;
m_transferReadHandlers[PSMZ32] = &CGSHandler::TransferReadHandlerGeneric<CGsPixelFormats::STORAGEPSMZ32>;
m_transferReadHandlers[PSMZ24] = &CGSHandler::TransferReadHandler24<CGsPixelFormats::STORAGEPSMZ32>;
m_transferReadHandlers[PSMZ16S] = &CGSHandler::TransferReadHandlerGeneric<CGsPixelFormats::STORAGEPSMZ16S>;

ResetBase();
Expand Down Expand Up @@ -787,35 +788,6 @@ void CGSHandler::SubmitWriteBufferImpl(uint32 bufferStartIndex, uint32 bufferEnd
m_transferCount--;
}

std::pair<uint32, uint32> CGSHandler::GetTransferInvalidationRange(const BITBLTBUF& bltBuf, const TRXREG& trxReg, const TRXPOS& trxPos)
{
uint32 transferAddress = bltBuf.GetDstPtr();

//Find the pages that are touched by this transfer
auto transferPageSize = CGsPixelFormats::GetPsmPageSize(bltBuf.nDstPsm);

// DBZ Budokai Tenkaichi 2 and 3 use invalid (empty) buffer sizes
// Account for that, by assuming trxReg.nRRW.
auto width = bltBuf.GetDstWidth();
if(width == 0)
{
width = trxReg.nRRW;
}

//Espgaluda uses an offset into a big memory area. The Y offset is not necessarily
//a multiple of the page height. We need to make sure to take this into account.
uint32 intraPageOffsetY = trxPos.nDSAY % transferPageSize.second;

uint32 pageCountX = (width + transferPageSize.first - 1) / transferPageSize.first;
uint32 pageCountY = (intraPageOffsetY + trxReg.nRRH + transferPageSize.second - 1) / transferPageSize.second;

uint32 pageCount = pageCountX * pageCountY;
uint32 transferSize = pageCount * CGsPixelFormats::PAGESIZE;
uint32 transferOffset = (trxPos.nDSAY / transferPageSize.second) * pageCountX * CGsPixelFormats::PAGESIZE;

return std::make_pair(transferAddress + transferOffset, transferSize);
}

void CGSHandler::BeginTransfer()
{
uint32 trxDir = m_nReg[GS_REG_TRXDIR] & 0x03;
Expand Down Expand Up @@ -1129,15 +1101,16 @@ void CGSHandler::TransferReadHandlerGeneric(void* buffer, uint32 length)
}
}

void CGSHandler::TransferReadHandlerPSMCT24(void* buffer, uint32 length)
template <typename Storage>
void CGSHandler::TransferReadHandler24(void* buffer, uint32 length)
{
auto trxPos = make_convertible<TRXPOS>(m_nReg[GS_REG_TRXPOS]);
auto trxReg = make_convertible<TRXREG>(m_nReg[GS_REG_TRXREG]);
auto trxBuf = make_convertible<BITBLTBUF>(m_nReg[GS_REG_BITBLTBUF]);

auto dst = reinterpret_cast<uint8*>(buffer);

CGsPixelFormats::CPixelIndexorPSMCT32 indexor(GetRam(), trxBuf.GetSrcPtr(), trxBuf.nSrcWidth);
CGsPixelFormats::CPixelIndexor<Storage> indexor(GetRam(), trxBuf.GetSrcPtr(), trxBuf.nSrcWidth);
for(uint32 i = 0; i < length; i += 3)
{
uint32 x = (m_trxCtx.nRRX + trxPos.nSSAX) % 2048;
Expand Down
5 changes: 2 additions & 3 deletions Source/gs/GSHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -888,8 +888,6 @@ class CGSHandler
DISPLAY_RECT GetDisplayRect(uint64) const;
DISPLAY_INFO GetCurrentDisplayInfo();

static std::pair<uint32, uint32> GetTransferInvalidationRange(const BITBLTBUF&, const TRXREG&, const TRXPOS&);

virtual Framework::CBitmap GetScreenshot();

void SendGSCall(CMailBox::FunctionType&&);
Expand Down Expand Up @@ -1055,7 +1053,8 @@ class CGSHandler
void TransferReadHandlerInvalid(void*, uint32);
template <typename Storage>
void TransferReadHandlerGeneric(void*, uint32);
void TransferReadHandlerPSMCT24(void*, uint32);
template <typename Storage>
void TransferReadHandler24(void*, uint32);
void TransferReadHandlerPSMT8H(void*, uint32);

virtual void SyncCLUT(const TEX0&);
Expand Down
101 changes: 101 additions & 0 deletions Source/gs/GsTransferRange.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#pragma once

#include "GSHandler.h"

namespace GsTransfer
{
struct TransferRangeSrc
{
static uint32 GetBufferAddress(const CGSHandler::BITBLTBUF& bltBuf)
{
return bltBuf.GetSrcPtr();
}
static uint32 GetBufferWidth(const CGSHandler::BITBLTBUF& bltBuf)
{
return bltBuf.GetSrcWidth();
}
static uint32 GetBufferPsm(const CGSHandler::BITBLTBUF& bltBuf)
{
return bltBuf.nSrcPsm;
}
static uint32 GetSAX(const CGSHandler::TRXPOS& trxPos)
{
return trxPos.nSSAX;
}
static uint32 GetSAY(const CGSHandler::TRXPOS& trxPos)
{
return trxPos.nSSAY;
}
};

struct TransferRangeDst
{
static uint32 GetBufferAddress(const CGSHandler::BITBLTBUF& bltBuf)
{
return bltBuf.GetDstPtr();
}
static uint32 GetBufferWidth(const CGSHandler::BITBLTBUF& bltBuf)
{
return bltBuf.GetDstWidth();
}
static uint32 GetBufferPsm(const CGSHandler::BITBLTBUF& bltBuf)
{
return bltBuf.nDstPsm;
}
static uint32 GetSAX(const CGSHandler::TRXPOS& trxPos)
{
return trxPos.nDSAX;
}
static uint32 GetSAY(const CGSHandler::TRXPOS& trxPos)
{
return trxPos.nDSAY;
}
};

template <typename TransferRangeTraits>
static std::pair<uint32, uint32> GetRange(const CGSHandler::BITBLTBUF& bltBuf, const CGSHandler::TRXREG& trxReg, const CGSHandler::TRXPOS& trxPos)
{
uint32 transferAddress = TransferRangeTraits::GetBufferAddress(bltBuf);
uint32 psm = TransferRangeTraits::GetBufferPsm(bltBuf);

//Find the pages that are touched by this transfer
auto transferPageSize = CGsPixelFormats::GetPsmPageSize(psm);

// DBZ Budokai Tenkaichi 2 and 3 use invalid (empty) buffer sizes
// Account for that, by assuming trxReg.nRRW.
auto width = TransferRangeTraits::GetBufferWidth(bltBuf);
if(width == 0)
{
width = trxReg.nRRW;
}

uint32 sax = TransferRangeTraits::GetSAX(trxPos);
uint32 say = TransferRangeTraits::GetSAY(trxPos);

//Make sure we are within our buffer
assert((trxReg.nRRW + sax) <= width);

//Espgaluda uses an offset into a big memory area. The Y offset is not necessarily
//a multiple of the page height. We need to make sure to take this into account.
uint32 intraPageOffsetY = say % transferPageSize.second;

uint32 pageCountX = (width + transferPageSize.first - 1) / transferPageSize.first;
uint32 pageCountY = (intraPageOffsetY + trxReg.nRRH + transferPageSize.second - 1) / transferPageSize.second;

uint32 pageCount = pageCountX * pageCountY;
uint32 transferSize = pageCount * CGsPixelFormats::PAGESIZE;
uint32 transferOffset = (say / transferPageSize.second) * pageCountX * CGsPixelFormats::PAGESIZE;

return std::make_pair(transferAddress + transferOffset, transferSize);
}

static auto GetSrcRange(const CGSHandler::BITBLTBUF& bltBuf, const CGSHandler::TRXREG& trxReg, const CGSHandler::TRXPOS& trxPos)
{
return GetRange<TransferRangeSrc>(bltBuf, trxReg, trxPos);
}

static auto GetDstRange(const CGSHandler::BITBLTBUF& bltBuf, const CGSHandler::TRXREG& trxReg, const CGSHandler::TRXPOS& trxPos)
{
return GetRange<TransferRangeDst>(bltBuf, trxReg, trxPos);
}
}
9 changes: 5 additions & 4 deletions tools/GsAreaTest/GsTransferInvalidationTest.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "GsTransferInvalidationTest.h"
#include "gs/GSHandler.h"
#include "gs/GsPixelFormats.h"
#include "gs/GsTransferRange.h"

static CGSHandler::BITBLTBUF MakeDstBltBuf(uint32 psm, uint32 bufPtr, uint32 bufWidth)
{
Expand Down Expand Up @@ -40,7 +41,7 @@ static void SinglePageTransferTest()
auto trxReg = MakeTrxReg(Storage::PAGEWIDTH, Storage::PAGEHEIGHT);
auto trxPos = make_convertible<CGSHandler::TRXPOS>(0);

auto [transferAddress, transferSize] = CGSHandler::GetTransferInvalidationRange(bltBuf, trxReg, trxPos);
auto [transferAddress, transferSize] = GsTransfer::GetDstRange(bltBuf, trxReg, trxPos);

TEST_VERIFY(transferAddress == bufPtr);
TEST_VERIFY(transferSize == CGsPixelFormats::PAGESIZE);
Expand All @@ -61,7 +62,7 @@ static void SimpleOffsetYTransferTest()
auto trxReg = MakeTrxReg(16, 16);
auto trxPos = MakeDstTrxPos(0, CGsPixelFormats::STORAGEPSMCT32::PAGEHEIGHT * pageOffsetY);

auto [transferAddress, transferSize] = CGSHandler::GetTransferInvalidationRange(bltBuf, trxReg, trxPos);
auto [transferAddress, transferSize] = GsTransfer::GetDstRange(bltBuf, trxReg, trxPos);

TEST_VERIFY(transferAddress == (bufPtr + (CGsPixelFormats::PAGESIZE * pageCountX * pageOffsetY)));
//TEST_VERIFY(transferSize == CGsPixelFormats::PAGESIZE);
Expand All @@ -79,7 +80,7 @@ static void ZeroBufWidthTransferTest()
auto trxReg = MakeTrxReg(16, 16);
auto trxPos = make_convertible<CGSHandler::TRXPOS>(0);

auto [transferAddress, transferSize] = CGSHandler::GetTransferInvalidationRange(bltBuf, trxReg, trxPos);
auto [transferAddress, transferSize] = GsTransfer::GetDstRange(bltBuf, trxReg, trxPos);

TEST_VERIFY(transferAddress == bufPtr);
TEST_VERIFY(transferSize == CGsPixelFormats::PAGESIZE);
Expand All @@ -94,7 +95,7 @@ void EspgaludaTransferTest()
auto trxReg = MakeTrxReg(160, 128);
auto trxPos = MakeDstTrxPos(16, 16);

auto [transferAddress, transferSize] = CGSHandler::GetTransferInvalidationRange(bltBuf, trxReg, trxPos);
auto [transferAddress, transferSize] = GsTransfer::GetDstRange(bltBuf, trxReg, trxPos);

//PSMT8 page size is 128x64
//This transfer spans 8 pages on the X dimension -> ceil(1024 / 128)
Expand Down

0 comments on commit bc12688

Please sign in to comment.