mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-21 02:09:05 +02:00
The depth draws were queued and rasterized on the emu thread at each render target change, in Wipeout about 40 small batches a frame, and around 40% of that thread's time. Now a render target change hands the batch to a worker thread and carries on. Waiting for it is left to whatever reads the depth buffers: DrawSync and ListSync, block transfers, framebuffer copies, showing a frame, savestates and shutdown, and the texture cache when the texture or CLUT it reads overlaps a depth buffer still being written. Batches grow as needed instead of being preallocated at full size. A full batch is now handed over and a new one started, where the draw used to be dropped. Wipeout headless, output unchanged: 16% less wall time on a Galaxy S8 (8.2 s to 6.9 s for 10 emulated seconds). On an M1, where headless waits on the GPU, the emu thread uses 38% less CPU time. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
111 lines
4.0 KiB
C++
111 lines
4.0 KiB
C++
#pragma once
|
|
|
|
#include "GPUCommon.h"
|
|
|
|
class StringWriter;
|
|
|
|
// Shared GPUCommon implementation for the HW backends.
|
|
// Things that are irrelevant for SoftGPU should live here.
|
|
class GPUCommonHW : public GPUCommon {
|
|
public:
|
|
GPUCommonHW(GraphicsContext *gfxCtx, Draw::DrawContext *draw);
|
|
~GPUCommonHW() override;
|
|
|
|
// This can fail, and if so no render pass is active.
|
|
void SetCurFramebufferDirty(bool dirty) override { curFramebufferDirty_ = dirty; }
|
|
void PrepareCopyDisplayToOutput(const DisplayLayoutConfig &config) override;
|
|
void CopyDisplayToOutput(const DisplayLayoutConfig &config) override;
|
|
void DoState(PointerWrap &p) override;
|
|
void DeviceLost() override;
|
|
void DeviceRestore(Draw::DrawContext *draw) override;
|
|
|
|
u32 CheckGPUFeatures() const override;
|
|
|
|
// From GPUDebugInterface.
|
|
bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) override;
|
|
bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) override;
|
|
bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) override;
|
|
bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override;
|
|
std::vector<const VirtualFramebuffer *> GetFramebufferList() const override;
|
|
bool GetCurrentTexture(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) override;
|
|
bool GetCurrentClut(GPUDebugBuffer &buffer) override;
|
|
|
|
FramebufferManagerCommon *GetFramebufferManagerCommon() override {
|
|
return framebufferManager_;
|
|
}
|
|
TextureCacheCommon *GetTextureCacheCommon() override {
|
|
return textureCache_;
|
|
}
|
|
|
|
// Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend.
|
|
std::vector<std::string> DebugGetShaderIDs(DebugShaderType shader) override;
|
|
std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override;
|
|
|
|
void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override;
|
|
void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override;
|
|
|
|
u32 DrawSync(int mode) override;
|
|
void FlushPendingDrawing() override;
|
|
int ListSync(int listid, int mode) override;
|
|
|
|
bool FramebufferDirty() override;
|
|
bool FramebufferReallyDirty() override;
|
|
|
|
void Execute_VertexTypeSkinning(u32 op, u32 diff);
|
|
|
|
void Execute_Prim(u32 op, u32 diff);
|
|
void Execute_Bezier(u32 op, u32 diff);
|
|
void Execute_Spline(u32 op, u32 diff);
|
|
void Execute_BlockTransferStart(u32 op, u32 diff);
|
|
|
|
void Execute_TexSize0(u32 op, u32 diff);
|
|
void Execute_TexLevel(u32 op, u32 diff);
|
|
void Execute_LoadClut(u32 op, u32 diff);
|
|
|
|
void Execute_WorldMtxNum(u32 op, u32 diff);
|
|
void Execute_WorldMtxData(u32 op, u32 diff);
|
|
void Execute_ViewMtxNum(u32 op, u32 diff);
|
|
void Execute_ViewMtxData(u32 op, u32 diff);
|
|
void Execute_ProjMtxNum(u32 op, u32 diff);
|
|
void Execute_ProjMtxData(u32 op, u32 diff);
|
|
void Execute_TgenMtxNum(u32 op, u32 diff);
|
|
void Execute_TgenMtxData(u32 op, u32 diff);
|
|
void Execute_BoneMtxNum(u32 op, u32 diff);
|
|
void Execute_BoneMtxData(u32 op, u32 diff);
|
|
|
|
void Execute_TexFlush(u32 op, u32 diff);
|
|
|
|
// TODO: Have these return an error code if they jump to a bad address. If bad, stop the FastRunLoop.
|
|
typedef void (GPUCommonHW::*CmdFunc)(u32 op, u32 diff);
|
|
|
|
void FastRunLoop(DisplayList &list) override;
|
|
void ExecuteOp(u32 op, u32 diff) override;
|
|
|
|
bool PresentedThisFrame() const override;
|
|
|
|
private:
|
|
void CheckDepthUsage(VirtualFramebuffer *vfb) override;
|
|
void CheckFlushOp(int cmd, u32 diff);
|
|
|
|
protected:
|
|
void FormatGPUStatsCommon(StringWriter &w);
|
|
void UpdateCmdInfo() override;
|
|
|
|
void PreExecuteOp(u32 op, u32 diff) override;
|
|
void ClearCacheNextFrame() override;
|
|
|
|
// Needs to be called on GPU thread, not reporting thread.
|
|
void BuildReportingInfo() override;
|
|
void UpdateMSAALevel(Draw::DrawContext *draw) override;
|
|
|
|
void CheckDisplayResized() override;
|
|
void CheckRenderResized(const DisplayLayoutConfig &config) override;
|
|
void CheckConfigChanged(const DisplayLayoutConfig &config) override;
|
|
|
|
u32 CheckGPUFeaturesLate(u32 features) const;
|
|
|
|
int msaaLevel_ = 0;
|
|
ShaderManagerCommon *shaderManager_ = nullptr;
|
|
bool curFramebufferDirty_ = false;
|
|
};
|