Support CLUTs at an x offset.

Used by Kurohyo 2.  Highly unlikely to be a mis-estimate within stride.
This commit is contained in:
Unknown W. Brackets 2016-01-05 00:02:58 -08:00
parent 191350ff02
commit 909d477719
9 changed files with 15 additions and 17 deletions

View File

@ -169,7 +169,7 @@ public:
void NotifyBlockTransferAfter(u32 dstBasePtr, int dstStride, int dstX, int dstY, u32 srcBasePtr, int srcStride, int srcX, int srcY, int w, int h, int bpp, u32 skipDrawReason); void NotifyBlockTransferAfter(u32 dstBasePtr, int dstStride, int dstX, int dstY, u32 srcBasePtr, int srcStride, int srcX, int srcY, int w, int h, int bpp, u32 skipDrawReason);
virtual void ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool sync, int x, int y, int w, int h) = 0; virtual void ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool sync, int x, int y, int w, int h) = 0;
virtual void DownloadFramebufferForClut(void *clut, u32 fb_address, u32 loadBytes) = 0; virtual void DownloadFramebufferForClut(u32 fb_address, u32 loadBytes) = 0;
virtual void MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) = 0; virtual void MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) = 0;
virtual void DrawPixels(VirtualFramebuffer *vfb, int dstX, int dstY, const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) = 0; virtual void DrawPixels(VirtualFramebuffer *vfb, int dstX, int dstY, const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) = 0;
virtual void DrawFramebufferToOutput(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, bool applyPostShader) = 0; virtual void DrawFramebufferToOutput(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, bool applyPostShader) = 0;

View File

@ -213,13 +213,17 @@ void TextureCacheCommon::LoadClut(u32 clutAddr, u32 loadBytes) {
if (Memory::IsVRAMAddress(clutAddr)) { if (Memory::IsVRAMAddress(clutAddr)) {
// Clear the uncached bit, etc. to match framebuffers. // Clear the uncached bit, etc. to match framebuffers.
const u32 clutFramebufAddr = clutAddr & 0x3FFFFFFF; const u32 clutFramebufAddr = clutAddr & 0x3FFFFFFF;
const u32 clutFramebufEnd = clutFramebufAddr + loadBytes;
for (size_t i = 0, n = fbCache_.size(); i < n; ++i) { for (size_t i = 0, n = fbCache_.size(); i < n; ++i) {
auto framebuffer = fbCache_[i]; auto framebuffer = fbCache_[i];
if ((framebuffer->fb_address | 0x04000000) == clutFramebufAddr) { const u32 fb_address = framebuffer->fb_address | 0x04000000;
const u32 bpp = framebuffer->drawnFormat == GE_FORMAT_8888 ? 4 : 2;
if (fb_address + framebuffer->fb_stride * bpp > clutFramebufAddr && fb_address < clutFramebufEnd) {
framebuffer->last_frame_clut = gpuStats.numFlips; framebuffer->last_frame_clut = gpuStats.numFlips;
framebuffer->usageFlags |= FB_USAGE_CLUT; framebuffer->usageFlags |= FB_USAGE_CLUT;
clutRenderAddress_ = framebuffer->fb_address; clutRenderAddress_ = framebuffer->fb_address;
clutRenderOffset_ = clutFramebufAddr - fb_address;
} }
} }
} }
@ -227,7 +231,8 @@ void TextureCacheCommon::LoadClut(u32 clutAddr, u32 loadBytes) {
// It's possible for a game to (successfully) access outside valid memory. // It's possible for a game to (successfully) access outside valid memory.
u32 bytes = Memory::ValidSize(clutAddr, loadBytes); u32 bytes = Memory::ValidSize(clutAddr, loadBytes);
if (clutRenderAddress_ != 0xFFFFFFFF && !g_Config.bDisableSlowFramebufEffects) { if (clutRenderAddress_ != 0xFFFFFFFF && !g_Config.bDisableSlowFramebufEffects) {
DownloadFramebufferForClut(clutAddr, bytes); DownloadFramebufferForClut(clutRenderAddress_, clutRenderOffset_ + bytes);
Memory::MemcpyUnchecked(clutBufRaw_, clutAddr, bytes);
if (bytes < loadBytes) { if (bytes < loadBytes) {
memset((u8 *)clutBufRaw_ + bytes, 0x00, loadBytes - bytes); memset((u8 *)clutBufRaw_ + bytes, 0x00, loadBytes - bytes);
} }

View File

@ -157,6 +157,7 @@ protected:
u32 clutTotalBytes_; u32 clutTotalBytes_;
u32 clutMaxBytes_; u32 clutMaxBytes_;
u32 clutRenderAddress_; u32 clutRenderAddress_;
u32 clutRenderOffset_;
int standardScaleFactor_; int standardScaleFactor_;
}; };

View File

@ -859,7 +859,7 @@ namespace DX9 {
} }
} }
void FramebufferManagerDX9::DownloadFramebufferForClut(void *clut, u32 fb_address, u32 loadBytes) { void FramebufferManagerDX9::DownloadFramebufferForClut(u32 fb_address, u32 loadBytes) {
VirtualFramebuffer *vfb = GetVFBAt(fb_address); VirtualFramebuffer *vfb = GetVFBAt(fb_address);
if (vfb && vfb->fb_stride != 0) { if (vfb && vfb->fb_stride != 0) {
const u32 bpp = vfb->drawnFormat == GE_FORMAT_8888 ? 4 : 2; const u32 bpp = vfb->drawnFormat == GE_FORMAT_8888 ? 4 : 2;
@ -889,10 +889,6 @@ namespace DX9 {
RebindFramebuffer(); RebindFramebuffer();
} }
} }
if (Memory::IsValidAddress(fb_address | 0x04000000)) {
Memory::MemcpyUnchecked(clut, fb_address | 0x04000000, loadBytes);
}
} }
bool FramebufferManagerDX9::CreateDownloadTempBuffer(VirtualFramebuffer *nvfb) { bool FramebufferManagerDX9::CreateDownloadTempBuffer(VirtualFramebuffer *nvfb) {

View File

@ -74,7 +74,7 @@ public:
void BindFramebufferColor(int stage, VirtualFramebuffer *framebuffer, int flags); void BindFramebufferColor(int stage, VirtualFramebuffer *framebuffer, int flags);
void ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool sync, int x, int y, int w, int h) override; void ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool sync, int x, int y, int w, int h) override;
void DownloadFramebufferForClut(void *clut, u32 fb_address, u32 loadBytes) override; void DownloadFramebufferForClut(u32 fb_address, u32 loadBytes) override;
std::vector<FramebufferInfo> GetFramebufferList(); std::vector<FramebufferInfo> GetFramebufferList();

View File

@ -805,7 +805,7 @@ void TextureCacheDX9::ApplyTexture() {
} }
void TextureCacheDX9::DownloadFramebufferForClut(u32 clutAddr, u32 bytes) { void TextureCacheDX9::DownloadFramebufferForClut(u32 clutAddr, u32 bytes) {
framebufferManager_->DownloadFramebufferForClut(clutBufRaw_, clutAddr, bytes); framebufferManager_->DownloadFramebufferForClut(clutAddr, bytes);
} }
class TextureShaderApplierDX9 { class TextureShaderApplierDX9 {

View File

@ -1241,7 +1241,7 @@ void FramebufferManager::ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool s
} }
} }
void FramebufferManager::DownloadFramebufferForClut(void *clut, u32 fb_address, u32 loadBytes) { void FramebufferManager::DownloadFramebufferForClut(u32 fb_address, u32 loadBytes) {
PROFILE_THIS_SCOPE("gpu-readback"); PROFILE_THIS_SCOPE("gpu-readback");
// Flush async just in case. // Flush async just in case.
PackFramebufferAsync_(nullptr); PackFramebufferAsync_(nullptr);
@ -1275,10 +1275,6 @@ void FramebufferManager::DownloadFramebufferForClut(void *clut, u32 fb_address,
RebindFramebuffer(); RebindFramebuffer();
} }
} }
if (Memory::IsValidAddress(fb_address | 0x04000000)) {
Memory::MemcpyUnchecked(clut, fb_address | 0x04000000, loadBytes);
}
} }
bool FramebufferManager::CreateDownloadTempBuffer(VirtualFramebuffer *nvfb) { bool FramebufferManager::CreateDownloadTempBuffer(VirtualFramebuffer *nvfb) {

View File

@ -102,7 +102,7 @@ public:
// Reads a rectangular subregion of a framebuffer to the right position in its backing memory. // Reads a rectangular subregion of a framebuffer to the right position in its backing memory.
void ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool sync, int x, int y, int w, int h) override; void ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool sync, int x, int y, int w, int h) override;
void DownloadFramebufferForClut(void *clut, u32 fb_address, u32 loadBytes) override; void DownloadFramebufferForClut(u32 fb_address, u32 loadBytes) override;
std::vector<FramebufferInfo> GetFramebufferList(); std::vector<FramebufferInfo> GetFramebufferList();

View File

@ -880,7 +880,7 @@ void TextureCache::ApplyTexture() {
} }
void TextureCache::DownloadFramebufferForClut(u32 clutAddr, u32 bytes) { void TextureCache::DownloadFramebufferForClut(u32 clutAddr, u32 bytes) {
framebufferManager_->DownloadFramebufferForClut(clutBufRaw_, clutAddr, bytes); framebufferManager_->DownloadFramebufferForClut(clutAddr, bytes);
} }
class TextureShaderApplier { class TextureShaderApplier {