Merge pull request #8994 from unknownbrackets/gpu-clear

Clear memory when clearing drawing
This commit is contained in:
Henrik Rydgård 2016-09-24 19:23:15 +02:00 committed by GitHub
commit 8001f7cb0b
6 changed files with 88 additions and 5 deletions

View File

@ -15,16 +15,16 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include <algorithm>
#include "Common/ColorConv.h"
#include "Core/Config.h"
#include "GPU/Common/DrawEngineCommon.h"
#include "GPU/Common/SplineCommon.h"
#include "GPU/Common/VertexDecoderCommon.h"
#include "GPU/ge_constants.h"
#include "GPU/GPUState.h"
#include "Core/Config.h"
#include <algorithm>
#define QUAD_INDICES_MAX 65536
DrawEngineCommon::DrawEngineCommon() : dec_(nullptr) {
@ -116,6 +116,67 @@ u32 DrawEngineCommon::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr,
return DrawEngineCommon::NormalizeVertices(outPtr, bufPtr, inPtr, dec, lowerBound, upperBound, vertType);
}
void DrawEngineCommon::ApplyClearToMemory(int x1, int y1, int x2, int y2, u32 clearColor) {
u8 *addr = Memory::GetPointer(gstate.getFrameBufAddress());
const bool singleByteClear = (clearColor >> 16) == (clearColor & 0xFFFF) && (clearColor >> 24) == (clearColor & 0xFF);
const int bpp = gstate.FrameBufFormat() == GE_FORMAT_8888 ? 4 : 2;
const int stride = gstate.FrameBufStride();
const int width = x2 - x1;
// Simple, but often alpha is different and gums up the works.
if (singleByteClear) {
const int byteStride = stride * bpp;
const int byteWidth = width * bpp;
addr += x1 * bpp;
for (int y = y1; y < y2; ++y) {
memset(addr + y * byteStride, clearColor, byteWidth);
}
} else {
u16 clear16 = 0;
switch (gstate.FrameBufFormat()) {
case GE_FORMAT_565: ConvertRGBA8888ToRGB565(&clear16, &clearColor, 1); break;
case GE_FORMAT_5551: ConvertRGBA8888ToRGBA5551(&clear16, &clearColor, 1); break;
case GE_FORMAT_4444: ConvertRGBA8888ToRGBA4444(&clear16, &clearColor, 1); break;
}
// This will most often be true - rarely is the width not aligned.
if ((width & 3) == 0 && (x1 & 3) == 0) {
u64 val64 = clearColor | ((u64)clearColor << 32);
int xstride = 2;
if (bpp == 2) {
// Spread to all eight bytes.
u64 c2 = clear16 | (clear16 << 16);
val64 = c2 | (c2 << 32);
xstride = 4;
}
u64 *addr64 = (u64 *)addr;
const int stride64 = stride / xstride;
const int x1_64 = x1 / xstride;
const int x2_64 = x2 / xstride;
for (int y = y1; y < y2; ++y) {
for (int x = x1_64; x < x2_64; ++x) {
addr64[y * stride64 + x] = val64;
}
}
} else if (bpp == 4) {
u32 *addr32 = (u32 *)addr;
for (int y = y1; y < y2; ++y) {
for (int x = x1; x < x2; ++x) {
addr32[y * stride + x] = clearColor;
}
}
} else if (bpp == 2) {
u16 *addr16 = (u16 *)addr;
for (int y = y1; y < y2; ++y) {
for (int x = x1; x < x2; ++x) {
addr16[y * stride + x] = clear16;
}
}
}
}
}
// This code is HIGHLY unoptimized!
//
// It does the simplest and safest test possible: If all points of a bbox is outside a single of

View File

@ -60,6 +60,8 @@ protected:
// Preprocessing for spline/bezier
u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType);
void ApplyClearToMemory(int x1, int y1, int x2, int y2, u32 clearColor);
VertexDecoder *GetVertexDecoder(u32 vtype);
inline int IndexSize(u32 vtype) const {

View File

@ -129,6 +129,8 @@ void FramebufferManagerCommon::Init() {
// The game draws solid colors to a small framebuffer, and then reads this directly in VRAM.
// We force this framebuffer to 1x and force download it automatically.
hackForce04154000Download_ = gameId == "NPJH50631" || gameId == "NPJH50372" || gameId == "NPJH90164" || gameId == "NPJH50515";
// Let's also apply to Me & My Katamari.
hackForce04154000Download_ = hackForce04154000Download_ || gameId == "ULUS10094" || gameId == "ULES00339" || gameId == "ULJS00033" || gameId == "UCKS45022" || gameId == "ULJS19009" || gameId == "NPJH50141";
// And an initial clear. We don't clear per frame as the games are supposed to handle that
// by themselves.
@ -1032,4 +1034,4 @@ void FramebufferManagerCommon::ShowScreenResolution() {
messageStream << PSP_CoreParameter().pixelWidth << "x" << PSP_CoreParameter().pixelHeight;
host->NotifyUserMessage(messageStream.str(), 2.0f, 0xFFFFFF, "resize");
}
}

View File

@ -876,9 +876,15 @@ rotateVBO:
dxstate.colorMask.set((mask & D3DCLEAR_TARGET) != 0, (mask & D3DCLEAR_TARGET) != 0, (mask & D3DCLEAR_TARGET) != 0, (mask & D3DCLEAR_STENCIL) != 0);
pD3Ddevice->Clear(0, NULL, mask, clearColor, clearDepth, clearColor >> 24);
int scissorX1 = gstate.getScissorX1();
int scissorY1 = gstate.getScissorY1();
int scissorX2 = gstate.getScissorX2() + 1;
int scissorY2 = gstate.getScissorY2() + 1;
framebufferManager_->SetSafeSize(scissorX2, scissorY2);
if (g_Config.bBlockTransferGPU && gstate.isClearModeColorMask() && (gstate.isClearModeAlphaMask() || gstate.FrameBufFormat() == GE_FORMAT_565)) {
ApplyClearToMemory(scissorX1, scissorY1, scissorX2, scissorY2, clearColor);
}
}
}

View File

@ -987,9 +987,15 @@ rotateVBO:
glClear(target);
framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason);
int scissorX1 = gstate.getScissorX1();
int scissorY1 = gstate.getScissorY1();
int scissorX2 = gstate.getScissorX2() + 1;
int scissorY2 = gstate.getScissorY2() + 1;
framebufferManager_->SetSafeSize(scissorX2, scissorY2);
if (g_Config.bBlockTransferGPU && colorMask && (alphaMask || gstate.FrameBufFormat() == GE_FORMAT_565)) {
ApplyClearToMemory(scissorX1, scissorY1, scissorX2, scissorY2, clearColor);
}
}
}

View File

@ -817,9 +817,15 @@ void DrawEngineVulkan::DoFlush(VkCommandBuffer cmd) {
// We let the framebuffer manager handle the clear. It can use renderpasses to optimize on tilers.
framebufferManager_->NotifyClear(gstate.isClearModeColorMask(), gstate.isClearModeAlphaMask(), gstate.isClearModeDepthMask(), result.color, result.depth);
int scissorX1 = gstate.getScissorX1();
int scissorY1 = gstate.getScissorY1();
int scissorX2 = gstate.getScissorX2() + 1;
int scissorY2 = gstate.getScissorY2() + 1;
framebufferManager_->SetSafeSize(scissorX2, scissorY2);
if (g_Config.bBlockTransferGPU && gstate.isClearModeColorMask() && (gstate.isClearModeAlphaMask() || gstate.FrameBufFormat() == GE_FORMAT_565)) {
ApplyClearToMemory(scissorX1, scissorY1, scissorX2, scissorY2, result.color);
}
}
}