More GPU cleaning, removing uses of GPUState.h where not needed.

Want to get rid of direct accesses to GPUState in modules that may be reused in
my future next-gen backends, that will reformat display lists into command lists that will
then be optimized and executed, out of sync with the real GPUState.

Candidate modules that may be reused in full are Framebuffer and Depal, possibly TextureCache to some degree.
This commit is contained in:
Henrik Rydgard 2015-07-26 22:38:40 +02:00
parent 33246ffc8d
commit 2430c283a5
34 changed files with 343 additions and 306 deletions

View File

@ -1508,6 +1508,8 @@ add_library(GPU OBJECT
GPU/GPUInterface.h
GPU/GeDisasm.cpp
GPU/GeDisasm.h
GPU/GPU.cpp
GPU/GPU.h
GPU/GPUCommon.cpp
GPU/GPUCommon.h
GPU/GPUState.cpp

View File

@ -32,6 +32,7 @@
#include "Core/HLE/FunctionWrappers.h"
#include "GPU/Math3D.h"
#include "GPU/GPU.h"
#include "GPU/GPUInterface.h"
#include "GPU/GPUState.h"
@ -687,14 +688,14 @@ static int Hook_brandish_download_frame() {
}
static int Hook_growlanser_create_saveicon() {
const u32 fb_address = Memory::Read_U32(currentMIPS->r[MIPS_REG_SP] + 4);
const u32 fmt = Memory::Read_U32(currentMIPS->r[MIPS_REG_SP]);
const u32 sz = fmt == GE_FORMAT_8888 ? 0x00088000 : 0x00044000;
if (Memory::IsVRAMAddress(fb_address) && fmt <= 3) {
gpu->PerformMemoryDownload(fb_address, sz);
CBreakPoints::ExecMemCheck(fb_address, true, sz, currentMIPS->pc);
}
return 0;
const u32 fb_address = Memory::Read_U32(currentMIPS->r[MIPS_REG_SP] + 4);
const u32 fmt = Memory::Read_U32(currentMIPS->r[MIPS_REG_SP]);
const u32 sz = fmt == GE_FORMAT_8888 ? 0x00088000 : 0x00044000;
if (Memory::IsVRAMAddress(fb_address) && fmt <= 3) {
gpu->PerformMemoryDownload(fb_address, sz);
CBreakPoints::ExecMemCheck(fb_address, true, sz, currentMIPS->pc);
}
return 0;
}
static int Hook_sd_gundam_g_generation_download_frame() {
@ -984,7 +985,7 @@ static int Hook_utawarerumono_download_frame() {
if (Memory::IsVRAMAddress(fb_address)) {
gpu->PerformMemoryDownload(fb_address, 0x00088000);
CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc);
}
}
return 0;
}
@ -1011,7 +1012,7 @@ static int Hook_gakuenheaven_download_frame() {
if (Memory::IsVRAMAddress(fb_address)) {
gpu->PerformMemoryDownload(fb_address, 0x00088000);
CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc);
}
}
return 0;
}
@ -1020,7 +1021,7 @@ static int Hook_youkosohitsujimura_download_frame() {
if (Memory::IsVRAMAddress(fb_address)) {
gpu->PerformMemoryDownload(fb_address, 0x00088000);
CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc);
}
}
return 0;
}

View File

@ -50,6 +50,7 @@
#include "Core/HLE/sceKernelThread.h"
#include "Core/HLE/sceKernelInterrupt.h"
#include "GPU/GPU.h"
#include "GPU/GPUState.h"
#include "GPU/GPUInterface.h"
#include "GPU/Common/FramebufferCommon.h"
@ -215,8 +216,6 @@ void __DisplayInit() {
fpsHistoryValid = 0;
fpsHistoryPos = 0;
InitGfxState();
__KernelRegisterWaitTypeFuncs(WAITTYPE_VBLANK, __DisplayVblankBeginCallback, __DisplayVblankEndCallback);
}
@ -272,6 +271,11 @@ void __DisplayDoState(PointerWrap &p) {
}
p.Do(gstate);
// TODO: GPU stuff is really not the responsibility of sceDisplay.
// Display just displays the buffers the GPU has drawn, they are really completely distinct.
// Maybe a bit tricky to move at this point, though...
gstate_c.DoState(p);
#ifndef _XBOX
if (s < 2) {
@ -298,7 +302,6 @@ void __DisplayDoState(PointerWrap &p) {
void __DisplayShutdown() {
vblankListeners.clear();
vblankWaitingThreads.clear();
ShutdownGfxState();
}
void __DisplayListenVblank(VblankCallback callback) {

View File

@ -1,34 +0,0 @@
set(SRCS
GPUCommon.cpp
GPUState.cpp
Math3D.cpp
GLES/GLES_GPU.cpp
GLES/FragmentShaderGenerator.cpp
GLES/Framebuffer.cpp
GLES/IndexGenerator.cpp
GLES/ShaderManager.cpp
GLES/Spline.cpp
GLES/StateMapping.cpp
GLES/TextureCache.cpp
GLES/TextureScaler.cpp
GLES/TransformPipeline.cpp
GLES/VertexDecoder.cpp
GLES/VertexShaderGenerator.cpp
Null/NullGpu.cpp
Software/Clipper.cpp
Software/Lighting.cpp
Software/Rasterizer.cpp
Software/SoftGpu.cpp
Software/TransformUnit.cpp
)
set(SRCS ${SRCS})
add_library(gpu STATIC ${SRCS})
target_link_libraries(gpu general gfx_es2)
target_link_libraries(gpu general lin)
if(UNIX)
add_definitions(-fPIC)
endif(UNIX)

View File

@ -340,7 +340,7 @@ void FramebufferManagerCommon::DoSetRenderFrameBuffer() {
vfb->drawnHeight = 0;
vfb->drawnFormat = fmt;
vfb->usageFlags = FB_USAGE_RENDERTARGET;
SetColorUpdated(vfb);
SetColorUpdated(vfb, gstate_c.skipDrawReason);
vfb->depthUpdated = false;
u32 byteSize = FramebufferByteSize(vfb);
@ -454,7 +454,7 @@ void FramebufferManagerCommon::UpdateFromMemory(u32 addr, int size, bool safe) {
fmt = displayFormat_;
}
DrawPixels(vfb, 0, 0, Memory::GetPointer(addr | 0x04000000), fmt, vfb->fb_stride, vfb->width, vfb->height);
SetColorUpdated(vfb);
SetColorUpdated(vfb, gstate_c.skipDrawReason);
} else {
INFO_LOG(SCEGE, "Invalidating FBO for %08x (%i x %i x %i)", vfb->fb_address, vfb->width, vfb->height, vfb->format);
DestroyFramebuf(vfb);
@ -543,7 +543,7 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size,
// Just do the blit!
if (g_Config.bBlockTransferGPU) {
BlitFramebuffer(dstBuffer, 0, dstY, srcBuffer, 0, srcY, srcBuffer->width, srcH, 0);
SetColorUpdated(dstBuffer);
SetColorUpdated(dstBuffer, gstate_c.skipDrawReason);
RebindFramebuffer();
}
}
@ -554,7 +554,7 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size,
FlushBeforeCopy();
const u8 *srcBase = Memory::GetPointerUnchecked(src);
DrawPixels(dstBuffer, 0, dstY, srcBase, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->width, dstH);
SetColorUpdated(dstBuffer);
SetColorUpdated(dstBuffer, gstate_c.skipDrawReason);
RebindFramebuffer();
// This is a memcpy, let's still copy just in case.
return false;
@ -683,7 +683,7 @@ bool FramebufferManagerCommon::NotifyBlockTransferBefore(u32 dstBasePtr, int dst
FlushBeforeCopy();
BlitFramebuffer(dstBuffer, dstX, dstY, srcBuffer, srcX, srcY, dstWidth, dstHeight, bpp);
RebindFramebuffer();
SetColorUpdated(dstBuffer);
SetColorUpdated(dstBuffer, gstate_c.skipDrawReason);
return true;
}
} else {
@ -699,7 +699,7 @@ bool FramebufferManagerCommon::NotifyBlockTransferBefore(u32 dstBasePtr, int dst
FlushBeforeCopy();
BlitFramebuffer(dstBuffer, dstX, dstY, srcBuffer, srcX, srcY, dstWidth, dstHeight, bpp);
RebindFramebuffer();
SetColorUpdated(dstBuffer);
SetColorUpdated(dstBuffer, gstate_c.skipDrawReason);
return true; // No need to actually do the memory copy behind, probably.
}
}
@ -764,7 +764,7 @@ void FramebufferManagerCommon::NotifyBlockTransferAfter(u32 dstBasePtr, int dstS
int dstBpp = dstBuffer->format == GE_FORMAT_8888 ? 4 : 2;
float dstXFactor = (float)bpp / dstBpp;
DrawPixels(dstBuffer, static_cast<int>(dstX * dstXFactor), dstY, srcBase, dstBuffer->format, static_cast<int>(srcStride * dstXFactor), static_cast<int>(dstWidth * dstXFactor), dstHeight);
SetColorUpdated(dstBuffer);
SetColorUpdated(dstBuffer, gstate_c.skipDrawReason);
RebindFramebuffer();
}
}

View File

@ -19,9 +19,10 @@
#include <set>
#include <vector>
#include "Common/CommonTypes.h"
#include "Core/MemMap.h"
#include "GPU/GPUState.h"
#include "GPU/GPU.h"
#include "GPU/ge_constants.h"
enum {
@ -100,12 +101,12 @@ public:
void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format);
void DoSetRenderFrameBuffer();
void SetRenderFrameBuffer() {
void SetRenderFrameBuffer(bool framebufChanged, int skipDrawReason) {
// Inlining this part since it's so frequent.
if (!gstate_c.framebufChanged && currentRenderVfb_) {
if (!framebufChanged && currentRenderVfb_) {
currentRenderVfb_->last_frame_render = gpuStats.numFlips;
currentRenderVfb_->dirtyAfterDisplay = true;
if (!gstate_c.skipDrawReason)
if (!skipDrawReason)
currentRenderVfb_->reallyDirtyAfterDisplay = true;
return;
}
@ -166,9 +167,9 @@ public:
currentRenderVfb_->depthUpdated = true;
}
}
void SetColorUpdated() {
void SetColorUpdated(int skipDrawReason) {
if (currentRenderVfb_) {
SetColorUpdated(currentRenderVfb_);
SetColorUpdated(currentRenderVfb_, skipDrawReason);
}
}
void SetRenderSize(VirtualFramebuffer *vfb);
@ -198,13 +199,13 @@ protected:
void UpdateFramebufUsage(VirtualFramebuffer *vfb);
void SetColorUpdated(VirtualFramebuffer *dstBuffer) {
void SetColorUpdated(VirtualFramebuffer *dstBuffer, int skipDrawReason) {
dstBuffer->memoryUpdated = false;
dstBuffer->dirtyAfterDisplay = true;
dstBuffer->drawnWidth = dstBuffer->width;
dstBuffer->drawnHeight = dstBuffer->height;
dstBuffer->drawnFormat = dstBuffer->format;
if ((gstate_c.skipDrawReason & SKIPDRAW_SKIPFRAME) == 0)
if ((skipDrawReason & SKIPDRAW_SKIPFRAME) == 0)
dstBuffer->reallyDirtyAfterDisplay = true;
}

View File

@ -20,6 +20,7 @@
#include <vector>
#include <string>
#include "GPU/GPU.h"
#include "GPU/GPUInterface.h"
#include "Core/MemMap.h"

View File

@ -18,6 +18,9 @@
#include "ext/xxhash.h"
#include "Common/CPUDetect.h"
#include "Common/ColorConv.h"
#include "GPU/GPU.h"
#include "GPU/GPUState.h"
#include "GPU/Common/TextureDecoder.h"
// NEON is in a separate file so that it can be compiled with a runtime check.
#include "GPU/Common/TextureDecoderNEON.h"
@ -64,6 +67,39 @@ u32 QuickTexHashSSE2(const void *checkp, u32 size) {
}
#endif
// Masks to downalign bufw to 16 bytes, and wrap at 2048.
static const u32 textureAlignMask16[16] = {
0x7FF & ~(((8 * 16) / 16) - 1), //GE_TFMT_5650,
0x7FF & ~(((8 * 16) / 16) - 1), //GE_TFMT_5551,
0x7FF & ~(((8 * 16) / 16) - 1), //GE_TFMT_4444,
0x7FF & ~(((8 * 16) / 32) - 1), //GE_TFMT_8888,
0x7FF & ~(((8 * 16) / 4) - 1), //GE_TFMT_CLUT4,
0x7FF & ~(((8 * 16) / 8) - 1), //GE_TFMT_CLUT8,
0x7FF & ~(((8 * 16) / 16) - 1), //GE_TFMT_CLUT16,
0x7FF & ~(((8 * 16) / 32) - 1), //GE_TFMT_CLUT32,
0x7FF, //GE_TFMT_DXT1,
0x7FF, //GE_TFMT_DXT3,
0x7FF, //GE_TFMT_DXT5,
0, // INVALID,
0, // INVALID,
0, // INVALID,
0, // INVALID,
0, // INVALID,
};
u32 GetTextureBufw(int level, u32 texaddr, GETextureFormat format) {
// This is a hack to allow for us to draw the huge PPGe texture, which is always in kernel ram.
if (texaddr < PSP_GetKernelMemoryEnd())
return gstate.texbufwidth[level] & 0x1FFF;
u32 bufw = gstate.texbufwidth[level] & textureAlignMask16[format];
if (bufw == 0) {
// If it's less than 16 bytes, use 16 bytes.
bufw = (8 * 16) / textureBitsPerPixel[format];
}
return bufw;
}
u32 QuickTexHashNonSSE(const void *checkp, u32 size) {
u32 check = 0;

View File

@ -27,7 +27,6 @@ enum CheckAlphaResult {
#include "Common/Common.h"
#include "Core/MemMap.h"
#include "GPU/ge_constants.h"
#include "GPU/GPUState.h"
#include "GPU/Common/TextureDecoderNEON.h"
void SetupTextureDecoder();
@ -133,38 +132,7 @@ static const u8 textureBitsPerPixel[16] = {
0, // INVALID,
};
// Masks to downalign bufw to 16 bytes, and wrap at 2048.
static const u32 textureAlignMask16[16] = {
0x7FF & ~(((8 * 16) / 16) - 1), //GE_TFMT_5650,
0x7FF & ~(((8 * 16) / 16) - 1), //GE_TFMT_5551,
0x7FF & ~(((8 * 16) / 16) - 1), //GE_TFMT_4444,
0x7FF & ~(((8 * 16) / 32) - 1), //GE_TFMT_8888,
0x7FF & ~(((8 * 16) / 4) - 1), //GE_TFMT_CLUT4,
0x7FF & ~(((8 * 16) / 8) - 1), //GE_TFMT_CLUT8,
0x7FF & ~(((8 * 16) / 16) - 1), //GE_TFMT_CLUT16,
0x7FF & ~(((8 * 16) / 32) - 1), //GE_TFMT_CLUT32,
0x7FF, //GE_TFMT_DXT1,
0x7FF, //GE_TFMT_DXT3,
0x7FF, //GE_TFMT_DXT5,
0, // INVALID,
0, // INVALID,
0, // INVALID,
0, // INVALID,
0, // INVALID,
};
static inline u32 GetTextureBufw(int level, u32 texaddr, GETextureFormat format) {
// This is a hack to allow for us to draw the huge PPGe texture, which is always in kernel ram.
if (texaddr < PSP_GetKernelMemoryEnd())
return gstate.texbufwidth[level] & 0x1FFF;
u32 bufw = gstate.texbufwidth[level] & textureAlignMask16[format];
if (bufw == 0) {
// If it's less than 16 bytes, use 16 bytes.
bufw = (8 * 16) / textureBitsPerPixel[format];
}
return bufw;
}
u32 GetTextureBufw(int level, u32 texaddr, GETextureFormat format);
template <typename IndexT, typename ClutT>
inline void DeIndexTexture(ClutT *dest, const IndexT *indexed, int length, const ClutT *clut) {

View File

@ -1218,7 +1218,7 @@ namespace DX9 {
void FramebufferManagerDX9::FlushBeforeCopy() {
// Flush anything not yet drawn before blitting, downloading, or uploading.
// This might be a stalled list, or unflushed before a block transfer, etc.
SetRenderFrameBuffer();
SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason);
transformDraw_->Flush();
}

View File

@ -741,7 +741,7 @@ void DIRECTX9_GPU::Execute_Prim(u32 op, u32 diff) {
}
// This also make skipping drawing very effective.
framebufferManager_.SetRenderFrameBuffer();
framebufferManager_.SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason);
if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) {
transformDraw_.SetupVertexDecoder(gstate.vertType);
// Rough estimate, not sure what's correct.
@ -796,7 +796,7 @@ void DIRECTX9_GPU::Execute_Prim(u32 op, u32 diff) {
void DIRECTX9_GPU::Execute_Bezier(u32 op, u32 diff) {
// This also make skipping drawing very effective.
framebufferManager_.SetRenderFrameBuffer();
framebufferManager_.SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason);
if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) {
// TODO: Should this eat some cycles? Probably yes. Not sure if important.
return;
@ -839,7 +839,7 @@ void DIRECTX9_GPU::Execute_Bezier(u32 op, u32 diff) {
void DIRECTX9_GPU::Execute_Spline(u32 op, u32 diff) {
// This also make skipping drawing very effective.
framebufferManager_.SetRenderFrameBuffer();
framebufferManager_.SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason);
if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) {
// TODO: Should this eat some cycles? Probably yes. Not sure if important.
return;

View File

@ -22,8 +22,8 @@
#include "../Globals.h"
#include "helper/global.h"
#include "helper/fbo.h"
#include "GPU/GPU.h"
#include "GPU/GPUInterface.h"
#include "GPU/GPUState.h"
#include "GPU/Directx9/TextureScalerDX9.h"
#include "GPU/Common/TextureCacheCommon.h"

View File

@ -857,7 +857,7 @@ rotateVBO:
framebufferManager_->SetDepthUpdated();
}
if (mask & D3DCLEAR_TARGET) {
framebufferManager_->SetColorUpdated();
framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason);
}
dxstate.colorMask.set((mask & D3DCLEAR_TARGET) != 0, (mask & D3DCLEAR_TARGET) != 0, (mask & D3DCLEAR_TARGET) != 0, (mask & D3DCLEAR_STENCIL) != 0);
@ -876,7 +876,7 @@ rotateVBO:
dcid_ = 0;
prevPrim_ = GE_PRIM_INVALID;
gstate_c.vertexFullAlpha = true;
framebufferManager_->SetColorUpdated();
framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason);
host->GPUNotifyDraw();
}

View File

@ -21,6 +21,7 @@
#include <d3d9.h>
#include "GPU/GPUState.h"
#include "GPU/Common/GPUDebugInterface.h"
#include "GPU/Common/IndexGenerator.h"
#include "GPU/Common/VertexDecoderCommon.h"
@ -28,6 +29,7 @@
#include "GPU/Directx9/PixelShaderGeneratorDX9.h"
struct DecVtxFormat;
struct UVScale;
namespace DX9 {

View File

@ -1857,7 +1857,7 @@ void FramebufferManager::DestroyAllFBOs() {
void FramebufferManager::FlushBeforeCopy() {
// Flush anything not yet drawn before blitting, downloading, or uploading.
// This might be a stalled list, or unflushed before a block transfer, etc.
SetRenderFrameBuffer();
SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason);
transformDraw_->Flush();
}

View File

@ -805,7 +805,7 @@ void GLES_GPU::Execute_Prim(u32 op, u32 diff) {
}
// This also makes skipping drawing very effective.
framebufferManager_.SetRenderFrameBuffer();
framebufferManager_.SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason);
if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) {
transformDraw_.SetupVertexDecoder(gstate.vertType);
// Rough estimate, not sure what's correct.
@ -881,7 +881,7 @@ void GLES_GPU::Execute_VertexTypeSkinning(u32 op, u32 diff) {
void GLES_GPU::Execute_Bezier(u32 op, u32 diff) {
// This also make skipping drawing very effective.
framebufferManager_.SetRenderFrameBuffer();
framebufferManager_.SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason);
if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) {
// TODO: Should this eat some cycles? Probably yes. Not sure if important.
return;
@ -924,7 +924,7 @@ void GLES_GPU::Execute_Bezier(u32 op, u32 diff) {
void GLES_GPU::Execute_Spline(u32 op, u32 diff) {
// This also make skipping drawing very effective.
framebufferManager_.SetRenderFrameBuffer();
framebufferManager_.SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason);
if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) {
// TODO: Should this eat some cycles? Probably yes. Not sure if important.
return;

View File

@ -828,9 +828,10 @@ LinkedShader *ShaderManager::ApplyFragmentShader(Shader *vs, int prim, u32 vertT
// Okay, we have both shaders. Let's see if there's a linked one.
LinkedShader *ls = NULL;
u32 switchDirty = shaderSwitchDirty_;
for (auto iter = linkedShaderCache_.begin(); iter != linkedShaderCache_.end(); ++iter) {
// Deferred dirtying! Let's see if we can make this even more clever later.
iter->ls->dirtyUniforms |= shaderSwitchDirty_;
iter->ls->dirtyUniforms |= switchDirty;
if (iter->vs == vs && iter->fs == fs) {
ls = iter->ls;

View File

@ -876,7 +876,7 @@ rotateVBO:
// Stencil takes alpha.
glClearStencil(clearColor >> 24);
glClear(target);
framebufferManager_->SetColorUpdated();
framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason);
}
}
@ -891,7 +891,7 @@ rotateVBO:
dcid_ = 0;
prevPrim_ = GE_PRIM_INVALID;
gstate_c.vertexFullAlpha = true;
framebufferManager_->SetColorUpdated();
framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason);
#ifndef MOBILE_DEVICE
host->GPUNotifyDraw();

View File

@ -18,6 +18,8 @@
#pragma once
#include <unordered_map>
#include "GPU/GPUState.h"
#include "GPU/Common/GPUDebugInterface.h"
#include "GPU/Common/IndexGenerator.h"
#include "GPU/Common/VertexDecoderCommon.h"

98
GPU/GPU.cpp Normal file
View File

@ -0,0 +1,98 @@
// Copyright (c) 2015- 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
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "Core/Core.h"
#include "GPU/GPU.h"
#include "GPU/GPUInterface.h"
#include "GPU/GLES/GLES_GPU.h"
#include "GPU/Null/NullGpu.h"
#include "GPU/Software/SoftGpu.h"
#if defined(_WIN32)
#include "GPU/Directx9/helper/global.h"
#include "GPU/Directx9/GPU_DX9.h"
#endif
GPUStatistics gpuStats;
GPUInterface *gpu;
GPUDebugInterface *gpuDebug;
template <typename T>
static void SetGPU(T *obj) {
gpu = obj;
gpuDebug = obj;
}
bool GPU_Init() {
switch (PSP_CoreParameter().gpuCore) {
case GPU_NULL:
SetGPU(new NullGPU());
break;
case GPU_GLES:
SetGPU(new GLES_GPU());
break;
case GPU_SOFTWARE:
SetGPU(new SoftGPU());
break;
case GPU_DIRECTX9:
#if defined(_WIN32)
SetGPU(new DIRECTX9_GPU());
#endif
break;
}
return gpu != NULL;
}
void GPU_Shutdown() {
delete gpu;
gpu = 0;
gpuDebug = 0;
}
void GPU_Reinitialize() {
if (gpu) {
gpu->Reinitialize();
}
}
void InitGfxState() {
memset(&gstate, 0, sizeof(gstate));
memset(&gstate_c, 0, sizeof(gstate_c));
for (int i = 0; i < 256; i++) {
gstate.cmdmem[i] = i << 24;
}
// Lighting is not enabled by default, matrices are zero initialized.
memset(gstate.worldMatrix, 0, sizeof(gstate.worldMatrix));
memset(gstate.viewMatrix, 0, sizeof(gstate.viewMatrix));
memset(gstate.projMatrix, 0, sizeof(gstate.projMatrix));
memset(gstate.tgenMatrix, 0, sizeof(gstate.tgenMatrix));
memset(gstate.boneMatrix, 0, sizeof(gstate.boneMatrix));
}
void ShutdownGfxState() {
}
// When you have changed state outside the psp gfx core,
// or saved the context and has reloaded it, call this function.
void ReapplyGfxState() {
if (!gpu)
return;
gpu->ReapplyGfxState();
}

113
GPU/GPU.h Normal file
View File

@ -0,0 +1,113 @@
// Copyright (c) 2015- 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
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#pragma once
#include <cstring>
class GPUInterface;
class GPUDebugInterface;
enum SkipDrawReasonFlags {
SKIPDRAW_SKIPFRAME = 1,
SKIPDRAW_NON_DISPLAYED_FB = 2, // Skip drawing to FBO:s that have not been displayed.
SKIPDRAW_BAD_FB_TEXTURE = 4,
SKIPDRAW_WINDOW_MINIMIZED = 8, // Don't draw when the host window is minimized.
};
// Global GPU-related utility functions.
// Nothing directly Ge-related in here.
// PSP uses a curious 24-bit float - it's the top 24 bits of a regular IEEE754 32-bit float.
// This is used for light positions, transform matrices, you name it.
inline float getFloat24(unsigned int data) {
data <<= 8;
float f;
memcpy(&f, &data, 4);
return f;
}
// in case we ever want to generate PSP display lists...
inline unsigned int toFloat24(float f) {
unsigned int i;
memcpy(&i, &f, 4);
return i >> 8;
}
struct GPUStatistics {
void Reset() {
// Never add a vtable :)
memset(this, 0, sizeof(*this));
}
void ResetFrame() {
numDrawCalls = 0;
numCachedDrawCalls = 0;
numVertsSubmitted = 0;
numCachedVertsDrawn = 0;
numUncachedVertsDrawn = 0;
numTrackedVertexArrays = 0;
numTextureInvalidations = 0;
numTextureSwitches = 0;
numShaderSwitches = 0;
numFlushes = 0;
numTexturesDecoded = 0;
numAlphaTestedDraws = 0;
numNonAlphaTestedDraws = 0;
msProcessingDisplayLists = 0;
vertexGPUCycles = 0;
otherGPUCycles = 0;
memset(gpuCommandsAtCallLevel, 0, sizeof(gpuCommandsAtCallLevel));
}
// Per frame statistics
int numDrawCalls;
int numCachedDrawCalls;
int numFlushes;
int numVertsSubmitted;
int numCachedVertsDrawn;
int numUncachedVertsDrawn;
int numTrackedVertexArrays;
int numTextureInvalidations;
int numTextureSwitches;
int numShaderSwitches;
int numTexturesDecoded;
double msProcessingDisplayLists;
int vertexGPUCycles;
int otherGPUCycles;
int gpuCommandsAtCallLevel[4];
int numAlphaTestedDraws;
int numNonAlphaTestedDraws;
// Total statistics, updated by the GPU core in UpdateStats
int numVBlanks;
int numFlips;
int numTextures;
int numVertexShaders;
int numFragmentShaders;
int numShaders;
int numFBOs;
};
extern GPUStatistics gpuStats;
extern GPUInterface *gpu;
extern GPUDebugInterface *gpuDebug;
bool GPU_Init();
void GPU_Shutdown();
void GPU_Reinitialize();

View File

@ -227,6 +227,7 @@
<ClInclude Include="GLES\TextureScaler.h" />
<ClInclude Include="GLES\TransformPipeline.h" />
<ClInclude Include="GLES\VertexShaderGenerator.h" />
<ClInclude Include="GPU.h" />
<ClInclude Include="GPUCommon.h" />
<ClInclude Include="GPUInterface.h" />
<ClInclude Include="GPUState.h" />
@ -300,6 +301,7 @@
<ClCompile Include="GLES\TextureScaler.cpp" />
<ClCompile Include="GLES\TransformPipeline.cpp" />
<ClCompile Include="GLES\VertexShaderGenerator.cpp" />
<ClCompile Include="GPU.cpp" />
<ClCompile Include="GPUCommon.cpp" />
<ClCompile Include="GPUState.cpp" />
<ClCompile Include="Math3D.cpp" />

View File

@ -183,6 +183,7 @@
<ClInclude Include="Common\TextureScalerCommon.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="GPU.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="Math3D.cpp">
@ -350,8 +351,9 @@
<ClCompile Include="Common\TextureScalerCommon.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="GPU.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="CMakeLists.txt" />
</ItemGroup>
</Project>
</Project>

View File

@ -3,6 +3,7 @@
#include "native/base/timeutil.h"
#include "Common/ColorConv.h"
#include "GPU/GeDisasm.h"
#include "GPU/GPU.h"
#include "GPU/GPUCommon.h"
#include "GPU/GPUState.h"
#include "ChunkFile.h"
@ -24,6 +25,11 @@ GPUCommon::GPUCommon() :
Reinitialize();
SetupColorConv();
SetThreadEnabled(g_Config.bSeparateCPUThread);
InitGfxState();
}
GPUCommon::~GPUCommon() {
ShutdownGfxState();
}
void GPUCommon::Reinitialize() {
@ -639,7 +645,7 @@ void GPUCommon::ReapplyGfxStateInternal() {
// Let's just skip the transfer size stuff, it's just values.
}
inline void GPUCommon::UpdateState(GPUState state) {
inline void GPUCommon::UpdateState(GPURunState state) {
gpuState = state;
if (state != GPUSTATE_RUNNING)
downcount = 0;

View File

@ -14,11 +14,10 @@
typedef ThreadEventQueue<GPUInterface, GPUEvent, GPUEventType, GPU_EVENT_INVALID, GPU_EVENT_SYNC_THREAD, GPU_EVENT_FINISH_EVENT_LOOP> GPUThreadEventQueue;
class GPUCommon : public GPUThreadEventQueue, public GPUDebugInterface
{
class GPUCommon : public GPUThreadEventQueue, public GPUDebugInterface {
public:
GPUCommon();
virtual ~GPUCommon() {}
virtual ~GPUCommon();
virtual void Reinitialize();
virtual void InterruptStart(int listid);
@ -128,7 +127,7 @@ protected:
void UpdatePC(u32 currentPC) {
UpdatePC(currentPC, currentPC);
}
void UpdateState(GPUState state);
void UpdateState(GPURunState state);
void PopDLQueue();
void CheckDrawSync();
int GetNextListIndex();
@ -163,7 +162,7 @@ protected:
recursive_mutex listLock;
bool interruptRunning;
GPUState gpuState;
GPURunState gpuState;
bool isbreak;
u64 drawCompleteTicks;
u64 busyTicks;

View File

@ -21,6 +21,7 @@
#include <string>
#include <vector>
#include "GPU/GPU.h"
#include "Core/MemMap.h"
#include "GPU/ge_constants.h"
@ -54,8 +55,7 @@ enum DisplayListState {
PSP_GE_DL_STATE_PAUSED = 4,
};
enum SignalBehavior
{
enum SignalBehavior {
PSP_GE_SIGNAL_NONE = 0x00,
PSP_GE_SIGNAL_HANDLER_SUSPEND = 0x01,
PSP_GE_SIGNAL_HANDLER_CONTINUE = 0x02,
@ -91,8 +91,7 @@ enum SignalBehavior
PSP_GE_SIGNAL_BREAK2 = 0xFF,
};
enum GPUState
{
enum GPURunState {
GPUSTATE_RUNNING = 0,
GPUSTATE_DONE = 1,
GPUSTATE_STALL = 2,
@ -100,15 +99,13 @@ enum GPUState
GPUSTATE_ERROR = 4,
};
enum GPUSyncType
{
enum GPUSyncType {
GPU_SYNC_DRAW,
GPU_SYNC_LIST,
};
// Used for debug
struct FramebufferInfo
{
struct FramebufferInfo {
u32 fb_address;
u32 z_address;
int format;
@ -117,15 +114,13 @@ struct FramebufferInfo
void* fbo;
};
struct DisplayListStackEntry
{
struct DisplayListStackEntry {
u32 pc;
u32 offsetAddr;
u32 baseAddr;
};
struct DisplayList
{
struct DisplayList {
int id;
u32 startpc;
u32 pc;

View File

@ -18,20 +18,13 @@
#include "GPU/ge_constants.h"
#include "GPU/GPUState.h"
#include "GPU/GLES/ShaderManager.h"
#include "GPU/GLES/GLES_GPU.h"
#include "GPU/Null/NullGpu.h"
#include "GPU/Software/SoftGpu.h"
#if defined(_WIN32)
#include "GPU/Directx9/helper/global.h"
#include "GPU/Directx9/GPU_DX9.h"
#endif
#include "Common/ChunkFile.h"
#include "Core/CoreParameter.h"
#include "Core/Config.h"
#include "Core/System.h"
#include "Core/MemMap.h"
#ifdef _M_SSE
#include <emmintrin.h>
#endif
@ -41,75 +34,6 @@ GPUgstate MEMORY_ALIGNED16(gstate);
// Let's align this one too for good measure.
GPUStateCache MEMORY_ALIGNED16(gstate_c);
GPUInterface *gpu;
GPUDebugInterface *gpuDebug;
GPUStatistics gpuStats;
template <typename T>
static void SetGPU(T *obj) {
gpu = obj;
gpuDebug = obj;
}
bool GPU_Init() {
switch (PSP_CoreParameter().gpuCore) {
case GPU_NULL:
SetGPU(new NullGPU());
break;
case GPU_GLES:
SetGPU(new GLES_GPU());
break;
case GPU_SOFTWARE:
SetGPU(new SoftGPU());
break;
case GPU_DIRECTX9:
#if defined(_WIN32)
SetGPU(new DIRECTX9_GPU());
#endif
break;
}
return gpu != NULL;
}
void GPU_Shutdown() {
delete gpu;
gpu = 0;
gpuDebug = 0;
}
void GPU_Reinitialize() {
if (gpu) {
gpu->Reinitialize();
}
}
void InitGfxState() {
memset(&gstate, 0, sizeof(gstate));
memset(&gstate_c, 0, sizeof(gstate_c));
for (int i = 0; i < 256; i++) {
gstate.cmdmem[i] = i << 24;
}
// Lighting is not enabled by default, matrices are zero initialized.
memset(gstate.worldMatrix, 0, sizeof(gstate.worldMatrix));
memset(gstate.viewMatrix, 0, sizeof(gstate.viewMatrix));
memset(gstate.projMatrix, 0, sizeof(gstate.projMatrix));
memset(gstate.tgenMatrix, 0, sizeof(gstate.tgenMatrix));
memset(gstate.boneMatrix, 0, sizeof(gstate.boneMatrix));
}
void ShutdownGfxState() {
}
// When you have changed state outside the psp gfx core,
// or saved the context and has reloaded it, call this function.
void ReapplyGfxState() {
if (!gpu)
return;
gpu->ReapplyGfxState();
}
struct CmdRange {
u8 start;
u8 end;

View File

@ -19,38 +19,19 @@
#include <cmath>
#include "../Globals.h"
#include "ge_constants.h"
#include "Globals.h"
#include "GPU/GPU.h"
#include "GPU/ge_constants.h"
#include "Common/Common.h"
class PointerWrap;
// PSP uses a curious 24-bit float - it's basically the top 24 bits of a regular IEEE754 32-bit float.
// This is used for light positions, transform matrices, you name it.
inline float getFloat24(unsigned int data)
{
data <<= 8;
float f;
memcpy(&f, &data, 4);
return f;
}
// in case we ever want to generate PSP display lists...
inline unsigned int toFloat24(float f) {
unsigned int i;
memcpy(&i, &f, 4);
return i >> 8;
}
struct GPUgstate
{
struct GPUgstate {
// Getting rid of this ugly union in favor of the accessor functions
// might be a good idea....
union
{
union {
u32 cmdmem[256];
struct
{
struct {
u32 nop,
vaddr,
iaddr,
@ -439,20 +420,12 @@ struct GPUgstate
void Restore(u32_le *ptr);
};
enum SkipDrawReasonFlags {
SKIPDRAW_SKIPFRAME = 1,
SKIPDRAW_NON_DISPLAYED_FB = 2, // Skip drawing to FBO:s that have not been displayed.
SKIPDRAW_BAD_FB_TEXTURE = 4,
SKIPDRAW_WINDOW_MINIMIZED = 8, // Don't draw when the host window is minimized.
};
bool vertTypeIsSkinningEnabled(u32 vertType);
inline int vertTypeGetNumBoneWeights(u32 vertType) { return 1 + ((vertType & GE_VTYPE_WEIGHTCOUNT_MASK) >> GE_VTYPE_WEIGHTCOUNT_SHIFT); }
inline int vertTypeGetWeightMask(u32 vertType) { return vertType & GE_VTYPE_WEIGHT_MASK; }
inline int vertTypeGetTexCoordMask(u32 vertType) { return vertType & GE_VTYPE_TC_MASK; }
// The rest is cached simplified/converted data for fast access.
// Does not need to be saved when saving/restoring context.
//
@ -519,66 +492,6 @@ struct GPUStateCache {
void DoState(PointerWrap &p);
};
// TODO: Implement support for these.
struct GPUStatistics {
void Reset() {
// Never add a vtable :)
memset(this, 0, sizeof(*this));
}
void ResetFrame() {
numDrawCalls = 0;
numCachedDrawCalls = 0;
numVertsSubmitted = 0;
numCachedVertsDrawn = 0;
numUncachedVertsDrawn = 0;
numTrackedVertexArrays = 0;
numTextureInvalidations = 0;
numTextureSwitches = 0;
numShaderSwitches = 0;
numFlushes = 0;
numTexturesDecoded = 0;
numAlphaTestedDraws = 0;
numNonAlphaTestedDraws = 0;
msProcessingDisplayLists = 0;
vertexGPUCycles = 0;
otherGPUCycles = 0;
memset(gpuCommandsAtCallLevel, 0, sizeof(gpuCommandsAtCallLevel));
}
// Per frame statistics
int numDrawCalls;
int numCachedDrawCalls;
int numFlushes;
int numVertsSubmitted;
int numCachedVertsDrawn;
int numUncachedVertsDrawn;
int numTrackedVertexArrays;
int numTextureInvalidations;
int numTextureSwitches;
int numShaderSwitches;
int numTexturesDecoded;
double msProcessingDisplayLists;
int vertexGPUCycles;
int otherGPUCycles;
int gpuCommandsAtCallLevel[4];
int numAlphaTestedDraws;
int numNonAlphaTestedDraws;
// Total statistics, updated by the GPU core in UpdateStats
int numVBlanks;
int numFlips;
int numTextures;
int numVertexShaders;
int numFragmentShaders;
int numShaders;
int numFBOs;
};
bool GPU_Init();
void GPU_Shutdown();
void GPU_Reinitialize();
void InitGfxState();
void ShutdownGfxState();
void ReapplyGfxState();
@ -588,9 +501,6 @@ class GPUDebugInterface;
extern GPUgstate gstate;
extern GPUStateCache gstate_c;
extern GPUInterface *gpu;
extern GPUDebugInterface *gpuDebug;
extern GPUStatistics gpuStats;
inline u32 GPUStateCache::getRelativeAddress(u32 data) const {
u32 baseExtended = ((gstate.base & 0x000F0000) << 8) | data;

View File

@ -15,10 +15,11 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "../Core/MemMap.h"
#include "Core/MemMap.h"
#include "GPUState.h"
#include "ge_constants.h"
#include "GPU/GPU.h"
#include "GPU/GPUState.h"
void GeDescribeVertexType(u32 op, char *buffer, int len) {
bool through = (op & GE_VTYPE_THROUGH_MASK) == GE_VTYPE_THROUGH;

View File

@ -17,7 +17,8 @@
#pragma once
#include "../GPUCommon.h"
#include "GPU/GPUState.h"
#include "GPU/GPUCommon.h"
class ShaderManager;

View File

@ -22,6 +22,7 @@ win32 {
}
SOURCES += $$P/GPU/GeDisasm.cpp \ # GPU
$$P/GPU/GPU.cpp \
$$P/GPU/GPUCommon.cpp \
$$P/GPU/GPUState.cpp \
$$P/GPU/Math3D.cpp \

View File

@ -66,7 +66,6 @@
#include "Windows/RawInput.h"
#include "Windows/TouchInputHandler.h"
#include "GPU/GPUInterface.h"
#include "GPU/GPUState.h"
#include "gfx_es2/gpu_features.h"
#include "GPU/GLES/TextureScaler.h"
#include "GPU/GLES/TextureCache.h"

2
android/dbg.sh Normal file
View File

@ -0,0 +1,2 @@
export NDK=/c/AndroidNDK
$NDK/ndk-gdb --nowait

View File

@ -148,6 +148,7 @@ EXEC_AND_LIB_FILES := \
$(SRC)/Common/Timer.cpp \
$(SRC)/Common/Misc.cpp \
$(SRC)/GPU/Math3D.cpp \
$(SRC)/GPU/GPU.cpp \
$(SRC)/GPU/GPUCommon.cpp \
$(SRC)/GPU/GPUState.cpp \
$(SRC)/GPU/GeDisasm.cpp \