diff --git a/CMakeLists.txt b/CMakeLists.txt index 4694274ce5..07ee2c1d5d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/Core/HLE/ReplaceTables.cpp b/Core/HLE/ReplaceTables.cpp index 6fae1c03a8..f4164dc2f2 100644 --- a/Core/HLE/ReplaceTables.cpp +++ b/Core/HLE/ReplaceTables.cpp @@ -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; } diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 43d5b5b472..7d3b595c8b 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -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) { diff --git a/GPU/CMakeLists.txt b/GPU/CMakeLists.txt deleted file mode 100644 index 1e0a3d7688..0000000000 --- a/GPU/CMakeLists.txt +++ /dev/null @@ -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) - diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index 086317c5be..798fe680da 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -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(dstX * dstXFactor), dstY, srcBase, dstBuffer->format, static_cast(srcStride * dstXFactor), static_cast(dstWidth * dstXFactor), dstHeight); - SetColorUpdated(dstBuffer); + SetColorUpdated(dstBuffer, gstate_c.skipDrawReason); RebindFramebuffer(); } } diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index c42d11fc09..220fc2e30c 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -19,9 +19,10 @@ #include #include + #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; } diff --git a/GPU/Common/GPUDebugInterface.h b/GPU/Common/GPUDebugInterface.h index 0c7bb2afb6..c062777260 100644 --- a/GPU/Common/GPUDebugInterface.h +++ b/GPU/Common/GPUDebugInterface.h @@ -20,6 +20,7 @@ #include #include +#include "GPU/GPU.h" #include "GPU/GPUInterface.h" #include "Core/MemMap.h" diff --git a/GPU/Common/TextureDecoder.cpp b/GPU/Common/TextureDecoder.cpp index 298b93954a..53d3968c0e 100644 --- a/GPU/Common/TextureDecoder.cpp +++ b/GPU/Common/TextureDecoder.cpp @@ -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; diff --git a/GPU/Common/TextureDecoder.h b/GPU/Common/TextureDecoder.h index ec99c69d43..f10e35f5c0 100644 --- a/GPU/Common/TextureDecoder.h +++ b/GPU/Common/TextureDecoder.h @@ -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 inline void DeIndexTexture(ClutT *dest, const IndexT *indexed, int length, const ClutT *clut) { diff --git a/GPU/Directx9/FramebufferDX9.cpp b/GPU/Directx9/FramebufferDX9.cpp index f98e27654f..b49ea0e04c 100644 --- a/GPU/Directx9/FramebufferDX9.cpp +++ b/GPU/Directx9/FramebufferDX9.cpp @@ -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(); } diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 900f9873b0..9ecef98f75 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -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; diff --git a/GPU/Directx9/TextureCacheDX9.h b/GPU/Directx9/TextureCacheDX9.h index 25cb5d82b7..eb25632717 100644 --- a/GPU/Directx9/TextureCacheDX9.h +++ b/GPU/Directx9/TextureCacheDX9.h @@ -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" diff --git a/GPU/Directx9/TransformPipelineDX9.cpp b/GPU/Directx9/TransformPipelineDX9.cpp index 6b7eb88252..2856af7297 100644 --- a/GPU/Directx9/TransformPipelineDX9.cpp +++ b/GPU/Directx9/TransformPipelineDX9.cpp @@ -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(); } diff --git a/GPU/Directx9/TransformPipelineDX9.h b/GPU/Directx9/TransformPipelineDX9.h index fcb7bfe13f..c698cccfe7 100644 --- a/GPU/Directx9/TransformPipelineDX9.h +++ b/GPU/Directx9/TransformPipelineDX9.h @@ -21,6 +21,7 @@ #include +#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 { diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index e750787e82..1dd10ed02b 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -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(); } diff --git a/GPU/GLES/GLES_GPU.cpp b/GPU/GLES/GLES_GPU.cpp index 4fab1d65fb..8d2edb8d4a 100644 --- a/GPU/GLES/GLES_GPU.cpp +++ b/GPU/GLES/GLES_GPU.cpp @@ -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; diff --git a/GPU/GLES/ShaderManager.cpp b/GPU/GLES/ShaderManager.cpp index 503e4a0ba8..e9a64d026f 100644 --- a/GPU/GLES/ShaderManager.cpp +++ b/GPU/GLES/ShaderManager.cpp @@ -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; diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index f34be585f9..2994fe26bd 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -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(); diff --git a/GPU/GLES/TransformPipeline.h b/GPU/GLES/TransformPipeline.h index 3e18d5c930..b93a6c992a 100644 --- a/GPU/GLES/TransformPipeline.h +++ b/GPU/GLES/TransformPipeline.h @@ -18,6 +18,8 @@ #pragma once #include + +#include "GPU/GPUState.h" #include "GPU/Common/GPUDebugInterface.h" #include "GPU/Common/IndexGenerator.h" #include "GPU/Common/VertexDecoderCommon.h" diff --git a/GPU/GPU.cpp b/GPU/GPU.cpp new file mode 100644 index 0000000000..f4f4a54f6e --- /dev/null +++ b/GPU/GPU.cpp @@ -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 +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(); +} diff --git a/GPU/GPU.h b/GPU/GPU.h new file mode 100644 index 0000000000..ff504ae47c --- /dev/null +++ b/GPU/GPU.h @@ -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 + +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(); diff --git a/GPU/GPU.vcxproj b/GPU/GPU.vcxproj index 8870207a94..0e92a7c33d 100644 --- a/GPU/GPU.vcxproj +++ b/GPU/GPU.vcxproj @@ -227,6 +227,7 @@ + @@ -300,6 +301,7 @@ + diff --git a/GPU/GPU.vcxproj.filters b/GPU/GPU.vcxproj.filters index 0348eb8683..1ef4f62305 100644 --- a/GPU/GPU.vcxproj.filters +++ b/GPU/GPU.vcxproj.filters @@ -183,6 +183,7 @@ Common + @@ -350,8 +351,9 @@ Common + - + \ No newline at end of file diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 6822ed7471..cb97da1071 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -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; diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index fe09c08edd..cc60d15080 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -14,11 +14,10 @@ typedef ThreadEventQueue 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; diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index dbcbe8214e..15a57fed3c 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -21,6 +21,7 @@ #include #include +#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; diff --git a/GPU/GPUState.cpp b/GPU/GPUState.cpp index 8a6422bea7..50320303b3 100644 --- a/GPU/GPUState.cpp +++ b/GPU/GPUState.cpp @@ -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 #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 -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; diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 0e1f68f739..cc8e3d339d 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -19,38 +19,19 @@ #include -#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; diff --git a/GPU/GeDisasm.cpp b/GPU/GeDisasm.cpp index deb00fb397..69d307a2b4 100644 --- a/GPU/GeDisasm.cpp +++ b/GPU/GeDisasm.cpp @@ -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; diff --git a/GPU/Null/NullGpu.h b/GPU/Null/NullGpu.h index c9e8f493d5..db6f9000ed 100644 --- a/GPU/Null/NullGpu.h +++ b/GPU/Null/NullGpu.h @@ -17,7 +17,8 @@ #pragma once -#include "../GPUCommon.h" +#include "GPU/GPUState.h" +#include "GPU/GPUCommon.h" class ShaderManager; diff --git a/Qt/GPU.pro b/Qt/GPU.pro index 3c94228c6b..34729febf6 100644 --- a/Qt/GPU.pro +++ b/Qt/GPU.pro @@ -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 \ diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index 35f3945b99..ea470ea04c 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -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" diff --git a/android/dbg.sh b/android/dbg.sh new file mode 100644 index 0000000000..359d47d40e --- /dev/null +++ b/android/dbg.sh @@ -0,0 +1,2 @@ +export NDK=/c/AndroidNDK +$NDK/ndk-gdb --nowait diff --git a/android/jni/Android.mk b/android/jni/Android.mk index ac498f1bf6..b4361662d9 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -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 \