Use a separate func for gpu memset().

This commit is contained in:
Unknown W. Brackets 2014-05-27 01:14:29 -07:00
parent b73c575418
commit 8dcc09c9e1
14 changed files with 100 additions and 31 deletions

View File

@ -106,7 +106,7 @@ static int Replace_memcpy() {
u32 bytes = PARAM(2);
bool skip = false;
if (Memory::IsVRAMAddress(destPtr) || Memory::IsVRAMAddress(srcPtr)) {
skip = gpu->UpdateMemory(destPtr, srcPtr, bytes);
skip = gpu->PerformMemoryCopy(destPtr, srcPtr, bytes);
}
if (!skip && bytes != 0) {
u8 *dst = Memory::GetPointerUnchecked(destPtr);
@ -127,7 +127,7 @@ static int Replace_memcpy16() {
u32 bytes = PARAM(2) * 16;
bool skip = false;
if (Memory::IsVRAMAddress(destPtr) || Memory::IsVRAMAddress(srcPtr)) {
skip = gpu->UpdateMemory(destPtr, srcPtr, bytes);
skip = gpu->PerformMemoryCopy(destPtr, srcPtr, bytes);
}
if (!skip && bytes != 0) {
u8 *dst = Memory::GetPointerUnchecked(destPtr);
@ -150,7 +150,7 @@ static int Replace_memcpy_swizzled() {
if (Memory::IsVRAMAddress(srcPtr)) {
// Cheat a bit to force a download of the framebuffer.
// VRAM + 0x00400000 is simply a VRAM mirror.
gpu->UpdateMemory(srcPtr ^ 0x00400000, srcPtr, pitch * h);
gpu->PerformMemoryCopy(srcPtr ^ 0x00400000, srcPtr, pitch * h);
}
u8 *dstp = Memory::GetPointerUnchecked(destPtr);
const u8 *srcp = Memory::GetPointerUnchecked(srcPtr);
@ -184,7 +184,7 @@ static int Replace_memmove() {
u32 bytes = PARAM(2);
bool skip = false;
if (Memory::IsVRAMAddress(destPtr) || Memory::IsVRAMAddress(srcPtr)) {
skip = gpu->UpdateMemory(destPtr, srcPtr, bytes);
skip = gpu->PerformMemoryCopy(destPtr, srcPtr, bytes);
}
if (!skip && bytes != 0) {
u8 *dst = Memory::GetPointerUnchecked(destPtr);
@ -204,9 +204,12 @@ static int Replace_memset() {
u8 *dst = Memory::GetPointerUnchecked(destPtr);
u8 value = PARAM(1);
u32 bytes = PARAM(2);
memset(dst, value, bytes);
bool skip = false;
if (Memory::IsVRAMAddress(destPtr)) {
gpu->UpdateMemory(destPtr, destPtr, bytes);
skip = gpu->PerformMemorySet(destPtr, value, bytes);
}
if (!skip) {
memset(dst, value, bytes);
}
RETURN(destPtr);
#ifndef MOBILE_DEVICE

View File

@ -50,7 +50,7 @@ int __DmacMemcpy(u32 dst, u32 src, u32 size) {
bool skip = false;
if (Memory::IsVRAMAddress(src) || Memory::IsVRAMAddress(dst)) {
skip = gpu->UpdateMemory(dst, src, size);
skip = gpu->PerformMemoryCopy(dst, src, size);
}
if (!skip) {
Memory::Memcpy(dst, Memory::GetPointer(src), size);

View File

@ -552,9 +552,12 @@ u32 sceKernelMemset(u32 addr, u32 fillc, u32 n)
{
u8 c = fillc & 0xff;
DEBUG_LOG(SCEINTC, "sceKernelMemset(ptr = %08x, c = %02x, n = %08x)", addr, c, n);
Memory::Memset(addr, c, n);
bool skip = false;
if (Memory::IsVRAMAddress(addr)) {
gpu->UpdateMemory(addr, addr, n);
skip = gpu->PerformMemorySet(addr, fillc, n);
}
if (!skip) {
Memory::Memset(addr, c, n);
}
return addr;
}
@ -565,7 +568,7 @@ u32 sceKernelMemcpy(u32 dst, u32 src, u32 size)
bool skip = false;
if (Memory::IsVRAMAddress(src) || Memory::IsVRAMAddress(dst)) {
skip = gpu->UpdateMemory(dst, src, size);
skip = gpu->PerformMemoryCopy(dst, src, size);
}
// Technically should crash if these are invalid and size > 0...

View File

@ -1315,7 +1315,12 @@ void DIRECTX9_GPU::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationTy
framebufferManager_.UpdateFromMemory(addr, size);
}
bool DIRECTX9_GPU::UpdateMemory(u32 dest, u32 src, int size) {
bool DIRECTX9_GPU::PerformMemoryCopy(u32 dest, u32 src, int size) {
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
return false;
}
bool DIRECTX9_GPU::PerformMemorySet(u32 dest, u8 v, int size) {
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
return false;
}

View File

@ -46,7 +46,8 @@ public:
virtual void BeginFrame();
virtual void UpdateStats();
virtual void InvalidateCache(u32 addr, int size, GPUInvalidationType type);
virtual bool UpdateMemory(u32 dest, u32 src, int size);
virtual bool PerformMemoryCopy(u32 dest, u32 src, int size);
virtual bool PerformMemorySet(u32 dest, u8 v, int size);
virtual void ClearCacheNextFrame();
virtual void DeviceLost(); // Only happens on Android. Drop all textures and shaders.

View File

@ -1,4 +1,4 @@
// Copyright (c) 2012- PPSSPP Project.
// Copyright (c) 2012- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@ -1851,7 +1851,7 @@ void FramebufferManager::UpdateFromMemory(u32 addr, int size, bool safe) {
}
}
bool FramebufferManager::NotifyFramebufferCopy(u32 src, u32 dst, int size) {
bool FramebufferManager::NotifyFramebufferCopy(u32 src, u32 dst, int size, bool isMemset) {
if (!useBufferedRendering_ || updateVRAM_) {
return false;
}
@ -1880,11 +1880,9 @@ bool FramebufferManager::NotifyFramebufferCopy(u32 src, u32 dst, int size) {
}
}
bool actuallyMemset = src == dst;
// TODO: Do ReadFramebufferToMemory etc where applicable.
// This will slow down MotoGP but make the hack above unnecessary.
if (dstBuffer && srcBuffer && !actuallyMemset) {
if (dstBuffer && srcBuffer && !isMemset) {
if (srcBuffer == dstBuffer) {
WARN_LOG_REPORT_ONCE(dstsrccpy, G3D, "Intra-buffer memcpy (not supported) %08x -> %08x", src, dst);
} else {

View File

@ -211,7 +211,7 @@ public:
}
inline bool ShouldDownloadFramebuffer(const VirtualFramebuffer *vfb) const;
bool NotifyFramebufferCopy(u32 src, u32 dest, int size);
bool NotifyFramebufferCopy(u32 src, u32 dest, int size, bool isMemset = false);
void DestroyFramebuf(VirtualFramebuffer *vfb);

View File

@ -662,7 +662,11 @@ void GLES_GPU::ProcessEvent(GPUEvent ev) {
break;
case GPU_EVENT_FB_MEMCPY:
UpdateMemoryInternal(ev.fb_memcpy.dst, ev.fb_memcpy.src, ev.fb_memcpy.size);
PerformMemoryCopyInternal(ev.fb_memcpy.dst, ev.fb_memcpy.src, ev.fb_memcpy.size);
break;
case GPU_EVENT_FB_MEMSET:
PerformMemorySetInternal(ev.fb_memset.dst, ev.fb_memset.v, ev.fb_memset.size);
break;
default:
@ -1968,16 +1972,20 @@ void GLES_GPU::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType t
}
}
void GLES_GPU::UpdateMemoryInternal(u32 dest, u32 src, int size) {
void GLES_GPU::PerformMemoryCopyInternal(u32 dest, u32 src, int size) {
if (!framebufferManager_.NotifyFramebufferCopy(src, dest, size)) {
Memory::Memcpy(dest, Memory::GetPointer(src), size);
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
} else {
}
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
}
void GLES_GPU::PerformMemorySetInternal(u32 dest, u8 v, int size) {
if (!framebufferManager_.NotifyFramebufferCopy(dest, dest, size, true)) {
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
}
}
bool GLES_GPU::UpdateMemory(u32 dest, u32 src, int size) {
bool GLES_GPU::PerformMemoryCopy(u32 dest, u32 src, int size) {
// Track stray copies of a framebuffer in RAM. MotoGP does this.
if (framebufferManager_.MayIntersectFramebuffer(src) || framebufferManager_.MayIntersectFramebuffer(dest)) {
if (IsOnSeparateCPUThread()) {
@ -1990,7 +1998,7 @@ bool GLES_GPU::UpdateMemory(u32 dest, u32 src, int size) {
// This is a memcpy, so we need to wait for it to complete.
SyncThread();
} else {
UpdateMemoryInternal(dest, src, size);
PerformMemoryCopyInternal(dest, src, size);
}
return true;
}
@ -1999,6 +2007,30 @@ bool GLES_GPU::UpdateMemory(u32 dest, u32 src, int size) {
return false;
}
bool GLES_GPU::PerformMemorySet(u32 dest, u8 v, int size) {
// This may indicate a memset, usually to 0, of a framebuffer.
if (framebufferManager_.MayIntersectFramebuffer(dest)) {
Memory::Memset(dest, v, size);
if (IsOnSeparateCPUThread()) {
GPUEvent ev(GPU_EVENT_FB_MEMSET);
ev.fb_memset.dst = dest;
ev.fb_memset.v = v;
ev.fb_memset.size = size;
ScheduleEvent(ev);
// We don't need to wait for the framebuffer to be updated.
} else {
PerformMemorySetInternal(dest, v, size);
}
return true;
}
// Or perhaps a texture, let's invalidate.
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
return false;
}
void GLES_GPU::ClearCacheNextFrame() {
textureCache_.ClearNextFrame();
}

View File

@ -44,7 +44,8 @@ public:
virtual void BeginFrame();
virtual void UpdateStats();
virtual void InvalidateCache(u32 addr, int size, GPUInvalidationType type);
virtual bool UpdateMemory(u32 dest, u32 src, int size);
virtual bool PerformMemoryCopy(u32 dest, u32 src, int size);
virtual bool PerformMemorySet(u32 dest, u8 v, int size);
virtual void ClearCacheNextFrame();
virtual void DeviceLost(); // Only happens on Android. Drop all textures and shaders.
@ -151,7 +152,8 @@ private:
void InitClearInternal();
void BeginFrameInternal();
void CopyDisplayToOutputInternal();
void UpdateMemoryInternal(u32 dest, u32 src, int size);
void PerformMemoryCopyInternal(u32 dest, u32 src, int size);
void PerformMemorySetInternal(u32 dest, u8 v, int size);
void InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type);
static CommandInfo cmdInfo_[256];

View File

@ -164,6 +164,7 @@ enum GPUEventType {
GPU_EVENT_FINISH_EVENT_LOOP,
GPU_EVENT_SYNC_THREAD,
GPU_EVENT_FB_MEMCPY,
GPU_EVENT_FB_MEMSET,
};
struct GPUEvent {
@ -182,6 +183,12 @@ struct GPUEvent {
u32 src;
int size;
} fb_memcpy;
// GPU_EVENT_FB_MEMSET
struct {
u32 dst;
u8 v;
int size;
} fb_memset;
};
operator GPUEventType() const {
@ -234,7 +241,8 @@ public:
// If size = -1, invalidate everything.
virtual void InvalidateCache(u32 addr, int size, GPUInvalidationType type) = 0;
// Update either RAM from VRAM, or VRAM from RAM... or even VRAM from VRAM.
virtual bool UpdateMemory(u32 dest, u32 src, int size) = 0;
virtual bool PerformMemoryCopy(u32 dest, u32 src, int size) = 0;
virtual bool PerformMemorySet(u32 dest, u8 v, int size) = 0;
// Will cause the texture cache to be cleared at the start of the next frame.
virtual void ClearCacheNextFrame() = 0;

View File

@ -657,7 +657,13 @@ void NullGPU::InvalidateCache(u32 addr, int size, GPUInvalidationType type) {
// Nothing to invalidate.
}
bool NullGPU::UpdateMemory(u32 dest, u32 src, int size) {
bool NullGPU::PerformMemoryCopy(u32 dest, u32 src, int size) {
// Nothing to update.
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
return false;
}
bool NullGPU::PerformMemorySet(u32 dest, u8 v, int size) {
// Nothing to update.
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
return false;

View File

@ -34,7 +34,8 @@ public:
virtual void CopyDisplayToOutput() {}
virtual void UpdateStats();
virtual void InvalidateCache(u32 addr, int size, GPUInvalidationType type);
virtual bool UpdateMemory(u32 dest, u32 src, int size);
virtual bool PerformMemoryCopy(u32 dest, u32 src, int size);
virtual bool PerformMemorySet(u32 dest, u8 v, int size);
virtual void ClearCacheNextFrame() {};
virtual void DeviceLost() {}

View File

@ -851,7 +851,16 @@ void SoftGPU::InvalidateCache(u32 addr, int size, GPUInvalidationType type)
// Nothing to invalidate.
}
bool SoftGPU::UpdateMemory(u32 dest, u32 src, int size)
bool SoftGPU::PerformMemoryCopy(u32 dest, u32 src, int size)
{
// Nothing to update.
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
// Let's just be safe.
framebufferDirty_ = true;
return false;
}
bool SoftGPU::PerformMemorySet(u32 dest, u8 v, int size)
{
// Nothing to update.
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);

View File

@ -59,7 +59,8 @@ public:
virtual void CopyDisplayToOutput();
virtual void UpdateStats();
virtual void InvalidateCache(u32 addr, int size, GPUInvalidationType type);
virtual bool UpdateMemory(u32 dest, u32 src, int size);
virtual bool PerformMemoryCopy(u32 dest, u32 src, int size);
virtual bool PerformMemorySet(u32 dest, u8 v, int size);
virtual void ClearCacheNextFrame() {};
virtual void DeviceLost() {}