mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-15 10:40:01 +01:00
Merge pull request #9179 from hrydgard/more-gpu-centralization
More gpu centralization
This commit is contained in:
commit
e3bca489be
15 files changed
+470
-1033
No files matched your search
@@ -236,6 +236,8 @@ public:
|
||||
void SetRenderSize(VirtualFramebuffer *vfb);
|
||||
void SetSafeSize(u16 w, u16 h);
|
||||
|
||||
virtual void Resized() = 0;
|
||||
|
||||
protected:
|
||||
void UpdateSize();
|
||||
|
||||
|
||||
@@ -63,10 +63,6 @@ TextureCacheCommon::~TextureCacheCommon() {
|
||||
FreeAlignedMemory(clutBufRaw_);
|
||||
}
|
||||
|
||||
bool TextureCacheCommon::SetOffsetTexture(u32 offset) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int TextureCacheCommon::AttachedDrawingHeight() {
|
||||
if (nextTexture_) {
|
||||
if (nextTexture_->framebuffer) {
|
||||
|
||||
@@ -50,7 +50,9 @@ public:
|
||||
void LoadClut(u32 clutAddr, u32 loadBytes);
|
||||
bool GetCurrentClutBuffer(GPUDebugBuffer &buffer);
|
||||
|
||||
virtual bool SetOffsetTexture(u32 offset);
|
||||
virtual bool SetOffsetTexture(u32 offset) = 0;
|
||||
virtual void Invalidate(u32 addr, int size, GPUInvalidationType type) = 0;
|
||||
virtual void InvalidateAll(GPUInvalidationType type) = 0;
|
||||
|
||||
// FramebufferManager keeps TextureCache updated about what regions of memory are being rendered to.
|
||||
void NotifyFramebuffer(u32 address, VirtualFramebuffer *framebuffer, FramebufferNotification msg);
|
||||
|
||||
@@ -63,7 +63,7 @@ public:
|
||||
void DestroyAllFBOs(bool forceDelete);
|
||||
|
||||
void EndFrame();
|
||||
void Resized();
|
||||
void Resized() override;
|
||||
void DeviceLost();
|
||||
void CopyDisplayToOutput();
|
||||
void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old);
|
||||
|
||||
+43
-304
@@ -394,21 +394,26 @@ static const CommandTableEntry commandTable[] = {
|
||||
GPU_DX9::CommandInfo GPU_DX9::cmdInfo_[256];
|
||||
|
||||
GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx)
|
||||
: resized_(false), gfxCtx_(gfxCtx) {
|
||||
: gfxCtx_(gfxCtx) {
|
||||
lastVsync_ = g_Config.bVSync ? 1 : 0;
|
||||
dxstate.SetVSyncInterval(g_Config.bVSync);
|
||||
|
||||
framebufferManagerDX9_ = new FramebufferManagerDX9();
|
||||
framebufferManager_ = framebufferManagerDX9_;
|
||||
textureCacheDX9_ = new TextureCacheDX9();
|
||||
textureCache_ = textureCacheDX9_;
|
||||
|
||||
shaderManager_ = new ShaderManagerDX9();
|
||||
drawEngine_.SetShaderManager(shaderManager_);
|
||||
drawEngine_.SetTextureCache(&textureCache_);
|
||||
drawEngine_.SetFramebufferManager(&framebufferManager_);
|
||||
framebufferManager_.Init();
|
||||
framebufferManager_.SetTextureCache(&textureCache_);
|
||||
framebufferManager_.SetShaderManager(shaderManager_);
|
||||
framebufferManager_.SetTransformDrawEngine(&drawEngine_);
|
||||
textureCache_.SetFramebufferManager(&framebufferManager_);
|
||||
textureCache_.SetDepalShaderCache(&depalShaderCache_);
|
||||
textureCache_.SetShaderManager(shaderManager_);
|
||||
drawEngine_.SetTextureCache(textureCacheDX9_);
|
||||
drawEngine_.SetFramebufferManager(framebufferManagerDX9_);
|
||||
framebufferManagerDX9_->Init();
|
||||
framebufferManagerDX9_->SetTextureCache(textureCacheDX9_);
|
||||
framebufferManagerDX9_->SetShaderManager(shaderManager_);
|
||||
framebufferManagerDX9_->SetTransformDrawEngine(&drawEngine_);
|
||||
textureCacheDX9_->SetFramebufferManager(framebufferManagerDX9_);
|
||||
textureCacheDX9_->SetDepalShaderCache(&depalShaderCache_);
|
||||
textureCacheDX9_->SetShaderManager(shaderManager_);
|
||||
|
||||
// Sanity check gstate
|
||||
if ((int *)&gstate.transferstart - (int *)&gstate != 0xEA) {
|
||||
@@ -447,7 +452,7 @@ GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx)
|
||||
// Some of our defaults are different from hw defaults, let's assert them.
|
||||
// We restore each frame anyway, but here is convenient for tests.
|
||||
dxstate.Restore();
|
||||
textureCache_.NotifyConfigChanged();
|
||||
textureCache_->NotifyConfigChanged();
|
||||
}
|
||||
|
||||
void GPU_DX9::UpdateCmdInfo() {
|
||||
@@ -500,7 +505,7 @@ void GPU_DX9::CheckGPUFeatures() {
|
||||
}
|
||||
|
||||
GPU_DX9::~GPU_DX9() {
|
||||
framebufferManager_.DestroyAllFBOs(true);
|
||||
framebufferManagerDX9_->DestroyAllFBOs(true);
|
||||
shaderManager_->ClearCache(true);
|
||||
delete shaderManager_;
|
||||
}
|
||||
@@ -519,18 +524,14 @@ void GPU_DX9::DeviceLost() {
|
||||
// Simply drop all caches and textures.
|
||||
// FBOs appear to survive? Or no?
|
||||
shaderManager_->ClearCache(false);
|
||||
textureCache_.Clear(false);
|
||||
framebufferManager_.DeviceLost();
|
||||
textureCacheDX9_->Clear(false);
|
||||
framebufferManagerDX9_->DeviceLost();
|
||||
}
|
||||
|
||||
void GPU_DX9::DeviceRestore() {
|
||||
// Nothing needed.
|
||||
}
|
||||
|
||||
void GPU_DX9::InitClear() {
|
||||
ScheduleEvent(GPU_EVENT_INIT_CLEAR);
|
||||
}
|
||||
|
||||
void GPU_DX9::InitClearInternal() {
|
||||
bool useNonBufferedRendering = g_Config.iRenderingMode == FB_NON_BUFFERED_MODE;
|
||||
if (useNonBufferedRendering) {
|
||||
@@ -557,7 +558,7 @@ void GPU_DX9::BeginFrameInternal() {
|
||||
if (resized_) {
|
||||
UpdateCmdInfo();
|
||||
drawEngine_.Resized();
|
||||
textureCache_.NotifyConfigChanged();
|
||||
textureCacheDX9_->NotifyConfigChanged();
|
||||
resized_ = false;
|
||||
}
|
||||
|
||||
@@ -570,7 +571,7 @@ void GPU_DX9::BeginFrameInternal() {
|
||||
lastVsync_ = desiredVSyncInterval;
|
||||
}
|
||||
|
||||
textureCache_.StartFrame();
|
||||
textureCacheDX9_->StartFrame();
|
||||
drawEngine_.DecimateTrackedVertexArrays();
|
||||
depalShaderCache_.Decimate();
|
||||
// fragmentTestCache_.Decimate();
|
||||
@@ -584,12 +585,12 @@ void GPU_DX9::BeginFrameInternal() {
|
||||
}
|
||||
shaderManager_->DirtyShader();
|
||||
|
||||
framebufferManager_.BeginFrame();
|
||||
framebufferManagerDX9_->BeginFrame();
|
||||
}
|
||||
|
||||
void GPU_DX9::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) {
|
||||
host->GPUNotifyDisplay(framebuf, stride, format);
|
||||
framebufferManager_.SetDisplayFramebuffer(framebuf, stride, format);
|
||||
framebufferManagerDX9_->SetDisplayFramebuffer(framebuf, stride, format);
|
||||
}
|
||||
|
||||
bool GPU_DX9::FramebufferDirty() {
|
||||
@@ -600,7 +601,7 @@ bool GPU_DX9::FramebufferDirty() {
|
||||
// Allow it to process fully before deciding if it's dirty.
|
||||
SyncThread();
|
||||
}
|
||||
VirtualFramebuffer *vfb = framebufferManager_.GetDisplayVFB();
|
||||
VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB();
|
||||
if (vfb) {
|
||||
bool dirty = vfb->dirtyAfterDisplay;
|
||||
vfb->dirtyAfterDisplay = false;
|
||||
@@ -617,7 +618,7 @@ bool GPU_DX9::FramebufferReallyDirty() {
|
||||
SyncThread();
|
||||
}
|
||||
|
||||
VirtualFramebuffer *vfb = framebufferManager_.GetDisplayVFB();
|
||||
VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB();
|
||||
if (vfb) {
|
||||
bool dirty = vfb->reallyDirtyAfterDisplay;
|
||||
vfb->reallyDirtyAfterDisplay = false;
|
||||
@@ -626,18 +627,14 @@ bool GPU_DX9::FramebufferReallyDirty() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void GPU_DX9::CopyDisplayToOutput() {
|
||||
ScheduleEvent(GPU_EVENT_COPY_DISPLAY_TO_OUTPUT);
|
||||
}
|
||||
|
||||
void GPU_DX9::CopyDisplayToOutputInternal() {
|
||||
dxstate.depthWrite.set(true);
|
||||
dxstate.colorMask.set(true, true, true, true);
|
||||
|
||||
drawEngine_.Flush();
|
||||
|
||||
framebufferManager_.CopyDisplayToOutput();
|
||||
framebufferManager_.EndFrame();
|
||||
framebufferManagerDX9_->CopyDisplayToOutput();
|
||||
framebufferManagerDX9_->EndFrame();
|
||||
|
||||
// shaderManager_->EndFrame();
|
||||
shaderManager_->DirtyLastShader();
|
||||
@@ -673,41 +670,6 @@ void GPU_DX9::FinishDeferred() {
|
||||
drawEngine_.FinishDeferred();
|
||||
}
|
||||
|
||||
void GPU_DX9::ProcessEvent(GPUEvent ev) {
|
||||
switch (ev.type) {
|
||||
case GPU_EVENT_INIT_CLEAR:
|
||||
InitClearInternal();
|
||||
break;
|
||||
|
||||
case GPU_EVENT_BEGIN_FRAME:
|
||||
BeginFrameInternal();
|
||||
break;
|
||||
|
||||
case GPU_EVENT_COPY_DISPLAY_TO_OUTPUT:
|
||||
CopyDisplayToOutputInternal();
|
||||
break;
|
||||
|
||||
case GPU_EVENT_INVALIDATE_CACHE:
|
||||
InvalidateCacheInternal(ev.invalidate_cache.addr, ev.invalidate_cache.size, ev.invalidate_cache.type);
|
||||
break;
|
||||
|
||||
case GPU_EVENT_FB_MEMCPY:
|
||||
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;
|
||||
|
||||
case GPU_EVENT_FB_STENCIL_UPLOAD:
|
||||
PerformStencilUploadInternal(ev.fb_stencil_upload.dst, ev.fb_stencil_upload.size);
|
||||
break;
|
||||
|
||||
default:
|
||||
GPUCommon::ProcessEvent(ev);
|
||||
}
|
||||
}
|
||||
|
||||
inline void GPU_DX9::CheckFlushOp(int cmd, u32 diff) {
|
||||
const u8 cmdFlags = cmdInfo_[cmd].flags;
|
||||
if ((cmdFlags & FLAG_FLUSHBEFORE) || (diff && (cmdFlags & FLAG_FLUSHBEFOREONCHANGE))) {
|
||||
@@ -787,7 +749,7 @@ void GPU_DX9::Execute_Prim(u32 op, u32 diff) {
|
||||
}
|
||||
|
||||
// This also make skipping drawing very effective.
|
||||
framebufferManager_.SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason);
|
||||
framebufferManagerDX9_->SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason);
|
||||
if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) {
|
||||
drawEngine_.SetupVertexDecoder(gstate.vertType);
|
||||
// Rough estimate, not sure what's correct.
|
||||
@@ -835,7 +797,7 @@ void GPU_DX9::Execute_Prim(u32 op, u32 diff) {
|
||||
|
||||
void GPU_DX9::Execute_Bezier(u32 op, u32 diff) {
|
||||
// This also make skipping drawing very effective.
|
||||
framebufferManager_.SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason);
|
||||
framebufferManagerDX9_->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;
|
||||
@@ -878,7 +840,7 @@ void GPU_DX9::Execute_Bezier(u32 op, u32 diff) {
|
||||
|
||||
void GPU_DX9::Execute_Spline(u32 op, u32 diff) {
|
||||
// This also make skipping drawing very effective.
|
||||
framebufferManager_.SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason);
|
||||
framebufferManagerDX9_->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;
|
||||
@@ -1060,7 +1022,7 @@ void GPU_DX9::Execute_TexLevel(u32 op, u32 diff) {
|
||||
|
||||
void GPU_DX9::Execute_LoadClut(u32 op, u32 diff) {
|
||||
gstate_c.textureChanged |= TEXCHANGE_PARAMSONLY;
|
||||
textureCache_.LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes());
|
||||
textureCacheDX9_->LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes());
|
||||
// This could be used to "dirty" textures with clut.
|
||||
}
|
||||
|
||||
@@ -1876,8 +1838,8 @@ void GPU_DX9::GetStats(char *buffer, size_t bufsize) {
|
||||
gpuStats.numVertsSubmitted,
|
||||
gpuStats.numCachedVertsDrawn,
|
||||
gpuStats.numUncachedVertsDrawn,
|
||||
(int)framebufferManager_.NumVFBs(),
|
||||
(int)textureCache_.NumLoadedTextures(),
|
||||
(int)framebufferManagerDX9_->NumVFBs(),
|
||||
(int)textureCacheDX9_->NumLoadedTextures(),
|
||||
gpuStats.numTexturesDecoded,
|
||||
gpuStats.numTextureInvalidations,
|
||||
shaderManager_->NumVertexShaders(),
|
||||
@@ -1885,231 +1847,8 @@ void GPU_DX9::GetStats(char *buffer, size_t bufsize) {
|
||||
);
|
||||
}
|
||||
|
||||
void GPU_DX9::DoBlockTransfer(u32 skipDrawReason) {
|
||||
// TODO: This is used a lot to copy data around between render targets and textures,
|
||||
// and also to quickly load textures from RAM to VRAM. So we should do checks like the following:
|
||||
// * Does dstBasePtr point to an existing texture? If so maybe reload it immediately.
|
||||
//
|
||||
// * Does srcBasePtr point to a render target, and dstBasePtr to a texture? If so
|
||||
// either copy between rt and texture or reassign the texture to point to the render target
|
||||
//
|
||||
// etc....
|
||||
|
||||
u32 srcBasePtr = gstate.getTransferSrcAddress();
|
||||
u32 srcStride = gstate.getTransferSrcStride();
|
||||
|
||||
u32 dstBasePtr = gstate.getTransferDstAddress();
|
||||
u32 dstStride = gstate.getTransferDstStride();
|
||||
|
||||
int srcX = gstate.getTransferSrcX();
|
||||
int srcY = gstate.getTransferSrcY();
|
||||
|
||||
int dstX = gstate.getTransferDstX();
|
||||
int dstY = gstate.getTransferDstY();
|
||||
|
||||
int width = gstate.getTransferWidth();
|
||||
int height = gstate.getTransferHeight();
|
||||
|
||||
int bpp = gstate.getTransferBpp();
|
||||
|
||||
DEBUG_LOG(G3D, "Block transfer: %08x/%x -> %08x/%x, %ix%ix%i (%i,%i)->(%i,%i)", srcBasePtr, srcStride, dstBasePtr, dstStride, width, height, bpp, srcX, srcY, dstX, dstY);
|
||||
|
||||
if (!Memory::IsValidAddress(srcBasePtr)) {
|
||||
ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad source transfer address %08x!", srcBasePtr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Memory::IsValidAddress(dstBasePtr)) {
|
||||
ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad destination transfer address %08x!", dstBasePtr);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that the last address of both source and dest are valid addresses
|
||||
|
||||
u32 srcLastAddr = srcBasePtr + ((height - 1 + srcY) * srcStride + (srcX + width - 1)) * bpp;
|
||||
u32 dstLastAddr = dstBasePtr + ((height - 1 + dstY) * dstStride + (dstX + width - 1)) * bpp;
|
||||
|
||||
if (!Memory::IsValidAddress(srcLastAddr)) {
|
||||
ERROR_LOG_REPORT(G3D, "Bottom-right corner of source of block transfer is at an invalid address: %08x", srcLastAddr);
|
||||
return;
|
||||
}
|
||||
if (!Memory::IsValidAddress(dstLastAddr)) {
|
||||
ERROR_LOG_REPORT(G3D, "Bottom-right corner of destination of block transfer is at an invalid address: %08x", srcLastAddr);
|
||||
return;
|
||||
}
|
||||
|
||||
// Tell the framebuffer manager to take action if possible. If it does the entire thing, let's just return.
|
||||
if (!framebufferManager_.NotifyBlockTransferBefore(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason)) {
|
||||
// Do the copy! (Hm, if we detect a drawn video frame (see below) then we could maybe skip this?)
|
||||
// Can use GetPointerUnchecked because we checked the addresses above. We could also avoid them
|
||||
// entirely by walking a couple of pointers...
|
||||
if (srcStride == dstStride && (u32)width == srcStride) {
|
||||
// Common case in God of War, let's do it all in one chunk.
|
||||
u32 srcLineStartAddr = srcBasePtr + (srcY * srcStride + srcX) * bpp;
|
||||
u32 dstLineStartAddr = dstBasePtr + (dstY * dstStride + dstX) * bpp;
|
||||
const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr);
|
||||
u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr);
|
||||
memcpy(dst, src, width * height * bpp);
|
||||
} else {
|
||||
for (int y = 0; y < height; y++) {
|
||||
u32 srcLineStartAddr = srcBasePtr + ((y + srcY) * srcStride + srcX) * bpp;
|
||||
u32 dstLineStartAddr = dstBasePtr + ((y + dstY) * dstStride + dstX) * bpp;
|
||||
|
||||
const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr);
|
||||
u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr);
|
||||
memcpy(dst, src, width * bpp);
|
||||
}
|
||||
}
|
||||
|
||||
textureCache_.Invalidate(dstBasePtr + (dstY * dstStride + dstX) * bpp, height * dstStride * bpp, GPU_INVALIDATE_HINT);
|
||||
framebufferManager_.NotifyBlockTransferAfter(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason);
|
||||
}
|
||||
|
||||
CBreakPoints::ExecMemCheck(srcBasePtr + (srcY * srcStride + srcX) * bpp, false, height * srcStride * bpp, currentMIPS->pc);
|
||||
CBreakPoints::ExecMemCheck(dstBasePtr + (srcY * dstStride + srcX) * bpp, true, height * dstStride * bpp, currentMIPS->pc);
|
||||
|
||||
// TODO: Correct timing appears to be 1.9, but erring a bit low since some of our other timing is inaccurate.
|
||||
cyclesExecuted += ((height * width * bpp) * 16) / 10;
|
||||
}
|
||||
|
||||
void GPU_DX9::InvalidateCache(u32 addr, int size, GPUInvalidationType type) {
|
||||
GPUEvent ev(GPU_EVENT_INVALIDATE_CACHE);
|
||||
ev.invalidate_cache.addr = addr;
|
||||
ev.invalidate_cache.size = size;
|
||||
ev.invalidate_cache.type = type;
|
||||
ScheduleEvent(ev);
|
||||
}
|
||||
|
||||
void GPU_DX9::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type) {
|
||||
if (size > 0)
|
||||
textureCache_.Invalidate(addr, size, type);
|
||||
else
|
||||
textureCache_.InvalidateAll(type);
|
||||
|
||||
if (type != GPU_INVALIDATE_ALL && framebufferManager_.MayIntersectFramebuffer(addr)) {
|
||||
// If we're doing block transfers, we shouldn't need this, and it'll only confuse us.
|
||||
// Vempire invalidates (with writeback) after drawing, but before blitting.
|
||||
if (!g_Config.bBlockTransferGPU || type == GPU_INVALIDATE_SAFE) {
|
||||
framebufferManager_.UpdateFromMemory(addr, size, type == GPU_INVALIDATE_SAFE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GPU_DX9::NotifyVideoUpload(u32 addr, int size, int width, int format) {
|
||||
if (Memory::IsVRAMAddress(addr)) {
|
||||
framebufferManager_.NotifyVideoUpload(addr, size, width, (GEBufferFormat)format);
|
||||
}
|
||||
textureCache_.NotifyVideoUpload(addr, size, width, (GEBufferFormat)format);
|
||||
InvalidateCache(addr, size, GPU_INVALIDATE_SAFE);
|
||||
}
|
||||
|
||||
void GPU_DX9::PerformMemoryCopyInternal(u32 dest, u32 src, int size) {
|
||||
if (!framebufferManager_.NotifyFramebufferCopy(src, dest, size, false, gstate_c.skipDrawReason)) {
|
||||
// We use a little hack for Download/Upload using a VRAM mirror.
|
||||
// Since they're identical we don't need to copy.
|
||||
if (!Memory::IsVRAMAddress(dest) || (dest ^ 0x00400000) != src) {
|
||||
Memory::Memcpy(dest, src, size);
|
||||
}
|
||||
}
|
||||
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
|
||||
}
|
||||
|
||||
void GPU_DX9::PerformMemorySetInternal(u32 dest, u8 v, int size) {
|
||||
if (!framebufferManager_.NotifyFramebufferCopy(dest, dest, size, true, gstate_c.skipDrawReason)) {
|
||||
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
|
||||
}
|
||||
}
|
||||
|
||||
void GPU_DX9::PerformStencilUploadInternal(u32 dest, int size) {
|
||||
framebufferManager_.NotifyStencilUpload(dest, size);
|
||||
}
|
||||
|
||||
bool GPU_DX9::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()) {
|
||||
GPUEvent ev(GPU_EVENT_FB_MEMCPY);
|
||||
ev.fb_memcpy.dst = dest;
|
||||
ev.fb_memcpy.src = src;
|
||||
ev.fb_memcpy.size = size;
|
||||
ScheduleEvent(ev);
|
||||
|
||||
// This is a memcpy, so we need to wait for it to complete.
|
||||
SyncThread();
|
||||
} else {
|
||||
PerformMemoryCopyInternal(dest, src, size);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GPU_DX9::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;
|
||||
}
|
||||
|
||||
bool GPU_DX9::PerformMemoryDownload(u32 dest, int size) {
|
||||
// Cheat a bit to force a download of the framebuffer.
|
||||
// VRAM + 0x00400000 is simply a VRAM mirror.
|
||||
if (Memory::IsVRAMAddress(dest)) {
|
||||
return PerformMemoryCopy(dest ^ 0x00400000, dest, size);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GPU_DX9::PerformMemoryUpload(u32 dest, int size) {
|
||||
// Cheat a bit to force an upload of the framebuffer.
|
||||
// VRAM + 0x00400000 is simply a VRAM mirror.
|
||||
if (Memory::IsVRAMAddress(dest)) {
|
||||
return PerformMemoryCopy(dest, dest ^ 0x00400000, size);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GPU_DX9::PerformStencilUpload(u32 dest, int size) {
|
||||
if (framebufferManager_.MayIntersectFramebuffer(dest)) {
|
||||
if (IsOnSeparateCPUThread()) {
|
||||
GPUEvent ev(GPU_EVENT_FB_STENCIL_UPLOAD);
|
||||
ev.fb_stencil_upload.dst = dest;
|
||||
ev.fb_stencil_upload.size = size;
|
||||
ScheduleEvent(ev);
|
||||
} else {
|
||||
PerformStencilUploadInternal(dest, size);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GPU_DX9::ClearCacheNextFrame() {
|
||||
textureCache_.ClearNextFrame();
|
||||
}
|
||||
|
||||
void GPU_DX9::Resized() {
|
||||
resized_ = true;
|
||||
framebufferManager_.Resized();
|
||||
textureCacheDX9_->ClearNextFrame();
|
||||
}
|
||||
|
||||
void GPU_DX9::ClearShaderCache() {
|
||||
@@ -2117,7 +1856,7 @@ void GPU_DX9::ClearShaderCache() {
|
||||
}
|
||||
|
||||
std::vector<FramebufferInfo> GPU_DX9::GetFramebufferList() {
|
||||
return framebufferManager_.GetFramebufferList();
|
||||
return framebufferManagerDX9_->GetFramebufferList();
|
||||
}
|
||||
|
||||
void GPU_DX9::DoState(PointerWrap &p) {
|
||||
@@ -2126,25 +1865,25 @@ void GPU_DX9::DoState(PointerWrap &p) {
|
||||
// TODO: Some of these things may not be necessary.
|
||||
// None of these are necessary when saving.
|
||||
if (p.mode == p.MODE_READ) {
|
||||
textureCache_.Clear(true);
|
||||
textureCacheDX9_->Clear(true);
|
||||
drawEngine_.ClearTrackedVertexArrays();
|
||||
|
||||
gstate_c.textureChanged = TEXCHANGE_UPDATED;
|
||||
framebufferManager_.DestroyAllFBOs(true);
|
||||
framebufferManagerDX9_->DestroyAllFBOs(true);
|
||||
shaderManager_->ClearCache(true);
|
||||
}
|
||||
}
|
||||
|
||||
bool GPU_DX9::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) {
|
||||
return framebufferManager_.GetCurrentFramebuffer(buffer, type, maxRes);
|
||||
return framebufferManagerDX9_->GetCurrentFramebuffer(buffer, type, maxRes);
|
||||
}
|
||||
|
||||
bool GPU_DX9::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) {
|
||||
return framebufferManager_.GetCurrentDepthbuffer(buffer);
|
||||
return framebufferManagerDX9_->GetCurrentDepthbuffer(buffer);
|
||||
}
|
||||
|
||||
bool GPU_DX9::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) {
|
||||
return framebufferManager_.GetCurrentStencilbuffer(buffer);
|
||||
return framebufferManagerDX9_->GetCurrentStencilbuffer(buffer);
|
||||
}
|
||||
|
||||
bool GPU_DX9::GetCurrentTexture(GPUDebugBuffer &buffer, int level) {
|
||||
@@ -2152,8 +1891,8 @@ bool GPU_DX9::GetCurrentTexture(GPUDebugBuffer &buffer, int level) {
|
||||
return false;
|
||||
}
|
||||
|
||||
textureCache_.SetTexture(true);
|
||||
textureCache_.ApplyTexture();
|
||||
textureCacheDX9_->SetTexture(true);
|
||||
textureCacheDX9_->ApplyTexture();
|
||||
int w = gstate.getTextureWidth(level);
|
||||
int h = gstate.getTextureHeight(level);
|
||||
|
||||
@@ -2237,7 +1976,7 @@ bool GPU_DX9::GetCurrentTexture(GPUDebugBuffer &buffer, int level) {
|
||||
}
|
||||
|
||||
bool GPU_DX9::GetCurrentClut(GPUDebugBuffer &buffer) {
|
||||
return textureCache_.GetCurrentClutBuffer(buffer);
|
||||
return textureCacheDX9_->GetCurrentClutBuffer(buffer);
|
||||
}
|
||||
|
||||
bool GPU_DX9::GetOutputFramebuffer(GPUDebugBuffer &buffer) {
|
||||
|
||||
+9
-25
@@ -37,23 +37,15 @@ class GPU_DX9 : public GPUCommon {
|
||||
public:
|
||||
GPU_DX9(GraphicsContext *gfxCtx);
|
||||
~GPU_DX9();
|
||||
|
||||
void CheckGPUFeatures();
|
||||
void InitClear() override;
|
||||
void PreExecuteOp(u32 op, u32 diff) override;
|
||||
void ExecuteOp(u32 op, u32 diff) override;
|
||||
|
||||
void ReapplyGfxStateInternal() override;
|
||||
void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override;
|
||||
void CopyDisplayToOutput() override;
|
||||
void BeginFrame() override;
|
||||
void GetStats(char *buffer, size_t bufsize) override;
|
||||
void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override;
|
||||
void NotifyVideoUpload(u32 addr, int size, int width, int format) override;
|
||||
bool PerformMemoryCopy(u32 dest, u32 src, int size) override;
|
||||
bool PerformMemorySet(u32 dest, u8 v, int size) override;
|
||||
bool PerformMemoryDownload(u32 dest, int size) override;
|
||||
bool PerformMemoryUpload(u32 dest, int size) override;
|
||||
bool PerformStencilUpload(u32 dest, int size) override;
|
||||
void ClearCacheNextFrame() override;
|
||||
void DeviceLost() override; // Only happens on Android. Drop all textures and shaders.
|
||||
void DeviceRestore() override;
|
||||
@@ -61,11 +53,9 @@ public:
|
||||
void DumpNextFrame() override;
|
||||
void DoState(PointerWrap &p) override;
|
||||
|
||||
// Called by the window system if the window size changed. This will be reflected in PSPCoreParam.pixel*.
|
||||
void Resized() override;
|
||||
void ClearShaderCache() override;
|
||||
bool DecodeTexture(u8 *dest, const GPUgstate &state) override {
|
||||
return textureCache_.DecodeTexture(dest, state);
|
||||
return textureCacheDX9_->DecodeTexture(dest, state);
|
||||
}
|
||||
bool FramebufferDirty() override;
|
||||
bool FramebufferReallyDirty() override;
|
||||
@@ -153,7 +143,6 @@ public:
|
||||
|
||||
protected:
|
||||
void FastRunLoop(DisplayList &list) override;
|
||||
void ProcessEvent(GPUEvent ev) override;
|
||||
void FastLoadBoneMatrix(u32 target) override;
|
||||
void FinishDeferred() override;
|
||||
|
||||
@@ -163,27 +152,22 @@ private:
|
||||
void Flush() {
|
||||
drawEngine_.Flush();
|
||||
}
|
||||
void DoBlockTransfer(u32 skipDrawReason);
|
||||
void ApplyDrawState(int prim);
|
||||
// void ApplyDrawState(int prim);
|
||||
void CheckFlushOp(int cmd, u32 diff);
|
||||
void BuildReportingInfo();
|
||||
void InitClearInternal();
|
||||
void BeginFrameInternal();
|
||||
void CopyDisplayToOutputInternal();
|
||||
void PerformMemoryCopyInternal(u32 dest, u32 src, int size);
|
||||
void PerformMemorySetInternal(u32 dest, u8 v, int size);
|
||||
void PerformStencilUploadInternal(u32 dest, int size);
|
||||
void InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type);
|
||||
|
||||
FramebufferManagerDX9 framebufferManager_;
|
||||
TextureCacheDX9 textureCache_;
|
||||
void InitClearInternal() override;
|
||||
void BeginFrameInternal() override;
|
||||
void CopyDisplayToOutputInternal() override;
|
||||
|
||||
FramebufferManagerDX9 *framebufferManagerDX9_;
|
||||
TextureCacheDX9 *textureCacheDX9_;
|
||||
DepalShaderCacheDX9 depalShaderCache_;
|
||||
DrawEngineDX9 drawEngine_;
|
||||
ShaderManagerDX9 *shaderManager_;
|
||||
|
||||
static CommandInfo cmdInfo_[256];
|
||||
|
||||
bool resized_;
|
||||
int lastVsync_;
|
||||
|
||||
std::string reportingPrimaryInfo_;
|
||||
|
||||
@@ -86,7 +86,7 @@ public:
|
||||
|
||||
virtual void Init() override;
|
||||
void EndFrame();
|
||||
void Resized();
|
||||
void Resized() override;
|
||||
void DeviceLost();
|
||||
void CopyDisplayToOutput();
|
||||
void SetLineWidth();
|
||||
|
||||
+52
-324
@@ -397,24 +397,29 @@ static const CommandTableEntry commandTable[] = {
|
||||
GPU_GLES::CommandInfo GPU_GLES::cmdInfo_[256];
|
||||
|
||||
GPU_GLES::GPU_GLES(GraphicsContext *ctx)
|
||||
: resized_(false), gfxCtx_(ctx) {
|
||||
: gfxCtx_(ctx) {
|
||||
UpdateVsyncInterval(true);
|
||||
CheckGPUFeatures();
|
||||
|
||||
shaderManager_ = new ShaderManager();
|
||||
framebufferManagerGL_ = new FramebufferManager();
|
||||
framebufferManager_ = framebufferManagerGL_;
|
||||
textureCacheGL_ = new TextureCache();
|
||||
textureCache_ = textureCacheGL_;
|
||||
|
||||
drawEngine_.SetShaderManager(shaderManager_);
|
||||
drawEngine_.SetTextureCache(&textureCache_);
|
||||
drawEngine_.SetFramebufferManager(&framebufferManager_);
|
||||
drawEngine_.SetTextureCache(textureCacheGL_);
|
||||
drawEngine_.SetFramebufferManager(framebufferManagerGL_);
|
||||
drawEngine_.SetFragmentTestCache(&fragmentTestCache_);
|
||||
framebufferManager_.Init();
|
||||
framebufferManager_.SetTextureCache(&textureCache_);
|
||||
framebufferManager_.SetShaderManager(shaderManager_);
|
||||
framebufferManager_.SetTransformDrawEngine(&drawEngine_);
|
||||
textureCache_.SetFramebufferManager(&framebufferManager_);
|
||||
textureCache_.SetDepalShaderCache(&depalShaderCache_);
|
||||
textureCache_.SetShaderManager(shaderManager_);
|
||||
textureCache_.SetTransformDrawEngine(&drawEngine_);
|
||||
fragmentTestCache_.SetTextureCache(&textureCache_);
|
||||
framebufferManagerGL_->Init();
|
||||
framebufferManagerGL_->SetTextureCache(textureCacheGL_);
|
||||
framebufferManagerGL_->SetShaderManager(shaderManager_);
|
||||
framebufferManagerGL_->SetTransformDrawEngine(&drawEngine_);
|
||||
textureCacheGL_->SetFramebufferManager(framebufferManagerGL_);
|
||||
textureCacheGL_->SetDepalShaderCache(&depalShaderCache_);
|
||||
textureCacheGL_->SetShaderManager(shaderManager_);
|
||||
textureCacheGL_->SetTransformDrawEngine(&drawEngine_);
|
||||
fragmentTestCache_.SetTextureCache(textureCacheGL_);
|
||||
|
||||
// Sanity check gstate
|
||||
if ((int *)&gstate.transferstart - (int *)&gstate != 0xEA) {
|
||||
@@ -457,7 +462,7 @@ GPU_GLES::GPU_GLES(GraphicsContext *ctx)
|
||||
// We restore each frame anyway, but here is convenient for tests.
|
||||
glstate.Restore();
|
||||
drawEngine_.RestoreVAO();
|
||||
textureCache_.NotifyConfigChanged();
|
||||
textureCacheGL_->NotifyConfigChanged();
|
||||
|
||||
// Load shader cache.
|
||||
std::string discID = g_paramSFO.GetValueString("DISC_ID");
|
||||
@@ -469,7 +474,7 @@ GPU_GLES::GPU_GLES(GraphicsContext *ctx)
|
||||
}
|
||||
|
||||
GPU_GLES::~GPU_GLES() {
|
||||
framebufferManager_.DestroyAllFBOs(true);
|
||||
framebufferManagerGL_->DestroyAllFBOs(true);
|
||||
shaderManager_->ClearCache(true);
|
||||
depalShaderCache_.Clear();
|
||||
fragmentTestCache_.Clear();
|
||||
@@ -647,10 +652,10 @@ void GPU_GLES::DeviceLost() {
|
||||
// FBOs appear to survive? Or no?
|
||||
// TransformDraw has registered as a GfxResourceHolder.
|
||||
shaderManager_->ClearCache(false);
|
||||
textureCache_.Clear(false);
|
||||
textureCacheGL_->Clear(false);
|
||||
fragmentTestCache_.Clear(false);
|
||||
depalShaderCache_.Clear();
|
||||
framebufferManager_.DeviceLost();
|
||||
framebufferManagerGL_->DeviceLost();
|
||||
}
|
||||
|
||||
void GPU_GLES::DeviceRestore() {
|
||||
@@ -659,20 +664,11 @@ void GPU_GLES::DeviceRestore() {
|
||||
UpdateVsyncInterval(true);
|
||||
}
|
||||
|
||||
void GPU_GLES::InitClear() {
|
||||
ScheduleEvent(GPU_EVENT_INIT_CLEAR);
|
||||
}
|
||||
|
||||
void GPU_GLES::Reinitialize() {
|
||||
GPUCommon::Reinitialize();
|
||||
ScheduleEvent(GPU_EVENT_REINITIALIZE);
|
||||
}
|
||||
|
||||
void GPU_GLES::ReinitializeInternal() {
|
||||
textureCache_.Clear(true);
|
||||
textureCacheGL_->Clear(true);
|
||||
depalShaderCache_.Clear();
|
||||
framebufferManager_.DestroyAllFBOs(true);
|
||||
framebufferManager_.Resized();
|
||||
framebufferManagerGL_->DestroyAllFBOs(true);
|
||||
framebufferManagerGL_->Resized();
|
||||
}
|
||||
|
||||
void GPU_GLES::InitClearInternal() {
|
||||
@@ -742,12 +738,12 @@ void GPU_GLES::BeginFrameInternal() {
|
||||
CheckGPUFeatures();
|
||||
UpdateCmdInfo();
|
||||
drawEngine_.Resized();
|
||||
textureCache_.NotifyConfigChanged();
|
||||
textureCacheGL_->NotifyConfigChanged();
|
||||
}
|
||||
UpdateVsyncInterval(resized_);
|
||||
resized_ = false;
|
||||
|
||||
textureCache_.StartFrame();
|
||||
textureCacheGL_->StartFrame();
|
||||
drawEngine_.DecimateTrackedVertexArrays();
|
||||
drawEngine_.DecimateBuffers();
|
||||
depalShaderCache_.Decimate();
|
||||
@@ -771,12 +767,12 @@ void GPU_GLES::BeginFrameInternal() {
|
||||
// Not sure if this is really needed.
|
||||
shaderManager_->DirtyUniform(DIRTY_ALL);
|
||||
|
||||
framebufferManager_.BeginFrame();
|
||||
framebufferManagerGL_->BeginFrame();
|
||||
}
|
||||
|
||||
void GPU_GLES::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) {
|
||||
host->GPUNotifyDisplay(framebuf, stride, format);
|
||||
framebufferManager_.SetDisplayFramebuffer(framebuf, stride, format);
|
||||
framebufferManagerGL_->SetDisplayFramebuffer(framebuf, stride, format);
|
||||
}
|
||||
|
||||
bool GPU_GLES::FramebufferDirty() {
|
||||
@@ -785,7 +781,7 @@ bool GPU_GLES::FramebufferDirty() {
|
||||
SyncThread();
|
||||
}
|
||||
|
||||
VirtualFramebuffer *vfb = framebufferManager_.GetDisplayVFB();
|
||||
VirtualFramebuffer *vfb = framebufferManagerGL_->GetDisplayVFB();
|
||||
if (vfb) {
|
||||
bool dirty = vfb->dirtyAfterDisplay;
|
||||
vfb->dirtyAfterDisplay = false;
|
||||
@@ -800,7 +796,7 @@ bool GPU_GLES::FramebufferReallyDirty() {
|
||||
SyncThread();
|
||||
}
|
||||
|
||||
VirtualFramebuffer *vfb = framebufferManager_.GetDisplayVFB();
|
||||
VirtualFramebuffer *vfb = framebufferManagerGL_->GetDisplayVFB();
|
||||
if (vfb) {
|
||||
bool dirty = vfb->reallyDirtyAfterDisplay;
|
||||
vfb->reallyDirtyAfterDisplay = false;
|
||||
@@ -809,13 +805,9 @@ bool GPU_GLES::FramebufferReallyDirty() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void GPU_GLES::CopyDisplayToOutput() {
|
||||
ScheduleEvent(GPU_EVENT_COPY_DISPLAY_TO_OUTPUT);
|
||||
}
|
||||
|
||||
void GPU_GLES::CopyDisplayToOutputInternal() {
|
||||
// Flush anything left over.
|
||||
framebufferManager_.RebindFramebuffer();
|
||||
framebufferManagerGL_->RebindFramebuffer();
|
||||
drawEngine_.Flush();
|
||||
|
||||
shaderManager_->DirtyLastShader();
|
||||
@@ -823,8 +815,8 @@ void GPU_GLES::CopyDisplayToOutputInternal() {
|
||||
glstate.depthWrite.set(GL_TRUE);
|
||||
glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
|
||||
framebufferManager_.CopyDisplayToOutput();
|
||||
framebufferManager_.EndFrame();
|
||||
framebufferManagerGL_->CopyDisplayToOutput();
|
||||
framebufferManagerGL_->EndFrame();
|
||||
|
||||
// If buffered, discard the depth buffer of the backbuffer. Don't even know if we need one.
|
||||
#if 0
|
||||
@@ -871,45 +863,6 @@ void GPU_GLES::FinishDeferred() {
|
||||
drawEngine_.FinishDeferred();
|
||||
}
|
||||
|
||||
void GPU_GLES::ProcessEvent(GPUEvent ev) {
|
||||
switch (ev.type) {
|
||||
case GPU_EVENT_INIT_CLEAR:
|
||||
InitClearInternal();
|
||||
break;
|
||||
|
||||
case GPU_EVENT_BEGIN_FRAME:
|
||||
BeginFrameInternal();
|
||||
break;
|
||||
|
||||
case GPU_EVENT_COPY_DISPLAY_TO_OUTPUT:
|
||||
CopyDisplayToOutputInternal();
|
||||
break;
|
||||
|
||||
case GPU_EVENT_INVALIDATE_CACHE:
|
||||
InvalidateCacheInternal(ev.invalidate_cache.addr, ev.invalidate_cache.size, ev.invalidate_cache.type);
|
||||
break;
|
||||
|
||||
case GPU_EVENT_FB_MEMCPY:
|
||||
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;
|
||||
|
||||
case GPU_EVENT_FB_STENCIL_UPLOAD:
|
||||
PerformStencilUploadInternal(ev.fb_stencil_upload.dst, ev.fb_stencil_upload.size);
|
||||
break;
|
||||
|
||||
case GPU_EVENT_REINITIALIZE:
|
||||
ReinitializeInternal();
|
||||
break;
|
||||
|
||||
default:
|
||||
GPUCommon::ProcessEvent(ev);
|
||||
}
|
||||
}
|
||||
|
||||
inline void GPU_GLES::CheckFlushOp(int cmd, u32 diff) {
|
||||
const u8 cmdFlags = cmdInfo_[cmd].flags;
|
||||
if ((cmdFlags & FLAG_FLUSHBEFORE) || (diff && (cmdFlags & FLAG_FLUSHBEFOREONCHANGE))) {
|
||||
@@ -965,7 +918,7 @@ void GPU_GLES::Execute_Prim(u32 op, u32 diff) {
|
||||
}
|
||||
|
||||
// This also makes skipping drawing very effective.
|
||||
framebufferManager_.SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason);
|
||||
framebufferManagerGL_->SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason);
|
||||
if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) {
|
||||
drawEngine_.SetupVertexDecoder(gstate.vertType);
|
||||
// Rough estimate, not sure what's correct.
|
||||
@@ -1034,7 +987,7 @@ void GPU_GLES::Execute_VertexTypeSkinning(u32 op, u32 diff) {
|
||||
|
||||
void GPU_GLES::Execute_Bezier(u32 op, u32 diff) {
|
||||
// This also make skipping drawing very effective.
|
||||
framebufferManager_.SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason);
|
||||
framebufferManagerGL_->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;
|
||||
@@ -1077,7 +1030,7 @@ void GPU_GLES::Execute_Bezier(u32 op, u32 diff) {
|
||||
|
||||
void GPU_GLES::Execute_Spline(u32 op, u32 diff) {
|
||||
// This also make skipping drawing very effective.
|
||||
framebufferManager_.SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason);
|
||||
framebufferManagerGL_->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;
|
||||
@@ -1257,7 +1210,7 @@ void GPU_GLES::Execute_TexLevel(u32 op, u32 diff) {
|
||||
|
||||
void GPU_GLES::Execute_LoadClut(u32 op, u32 diff) {
|
||||
gstate_c.textureChanged |= TEXCHANGE_PARAMSONLY;
|
||||
textureCache_.LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes());
|
||||
textureCacheGL_->LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes());
|
||||
// This could be used to "dirty" textures with clut.
|
||||
}
|
||||
|
||||
@@ -2135,8 +2088,8 @@ void GPU_GLES::GetStats(char *buffer, size_t bufsize) {
|
||||
gpuStats.numVertsSubmitted,
|
||||
gpuStats.numCachedVertsDrawn,
|
||||
gpuStats.numUncachedVertsDrawn,
|
||||
(int)framebufferManager_.NumVFBs(),
|
||||
(int)textureCache_.NumLoadedTextures(),
|
||||
(int)framebufferManagerGL_->NumVFBs(),
|
||||
(int)textureCacheGL_->NumLoadedTextures(),
|
||||
gpuStats.numTexturesDecoded,
|
||||
gpuStats.numTextureInvalidations,
|
||||
shaderManager_->NumVertexShaders(),
|
||||
@@ -2144,233 +2097,8 @@ void GPU_GLES::GetStats(char *buffer, size_t bufsize) {
|
||||
shaderManager_->NumPrograms());
|
||||
}
|
||||
|
||||
void GPU_GLES::DoBlockTransfer(u32 skipDrawReason) {
|
||||
// TODO: This is used a lot to copy data around between render targets and textures,
|
||||
// and also to quickly load textures from RAM to VRAM. So we should do checks like the following:
|
||||
// * Does dstBasePtr point to an existing texture? If so maybe reload it immediately.
|
||||
//
|
||||
// * Does srcBasePtr point to a render target, and dstBasePtr to a texture? If so
|
||||
// either copy between rt and texture or reassign the texture to point to the render target
|
||||
//
|
||||
// etc....
|
||||
|
||||
u32 srcBasePtr = gstate.getTransferSrcAddress();
|
||||
u32 srcStride = gstate.getTransferSrcStride();
|
||||
|
||||
u32 dstBasePtr = gstate.getTransferDstAddress();
|
||||
u32 dstStride = gstate.getTransferDstStride();
|
||||
|
||||
int srcX = gstate.getTransferSrcX();
|
||||
int srcY = gstate.getTransferSrcY();
|
||||
|
||||
int dstX = gstate.getTransferDstX();
|
||||
int dstY = gstate.getTransferDstY();
|
||||
|
||||
int width = gstate.getTransferWidth();
|
||||
int height = gstate.getTransferHeight();
|
||||
|
||||
int bpp = gstate.getTransferBpp();
|
||||
|
||||
DEBUG_LOG(G3D, "Block transfer: %08x/%x -> %08x/%x, %ix%ix%i (%i,%i)->(%i,%i)", srcBasePtr, srcStride, dstBasePtr, dstStride, width, height, bpp, srcX, srcY, dstX, dstY);
|
||||
|
||||
if (!Memory::IsValidAddress(srcBasePtr)) {
|
||||
ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad source transfer address %08x!", srcBasePtr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Memory::IsValidAddress(dstBasePtr)) {
|
||||
ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad destination transfer address %08x!", dstBasePtr);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that the last address of both source and dest are valid addresses
|
||||
|
||||
u32 srcLastAddr = srcBasePtr + ((srcY + height - 1) * srcStride + (srcX + width - 1)) * bpp;
|
||||
u32 dstLastAddr = dstBasePtr + ((dstY + height - 1) * dstStride + (dstX + width - 1)) * bpp;
|
||||
|
||||
if (!Memory::IsValidAddress(srcLastAddr)) {
|
||||
ERROR_LOG_REPORT(G3D, "Bottom-right corner of source of block transfer is at an invalid address: %08x", srcLastAddr);
|
||||
return;
|
||||
}
|
||||
if (!Memory::IsValidAddress(dstLastAddr)) {
|
||||
ERROR_LOG_REPORT(G3D, "Bottom-right corner of destination of block transfer is at an invalid address: %08x", srcLastAddr);
|
||||
return;
|
||||
}
|
||||
|
||||
// Tell the framebuffer manager to take action if possible. If it does the entire thing, let's just return.
|
||||
if (!framebufferManager_.NotifyBlockTransferBefore(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason)) {
|
||||
// Do the copy! (Hm, if we detect a drawn video frame (see below) then we could maybe skip this?)
|
||||
// Can use GetPointerUnchecked because we checked the addresses above. We could also avoid them
|
||||
// entirely by walking a couple of pointers...
|
||||
if (srcStride == dstStride && (u32)width == srcStride) {
|
||||
// Common case in God of War, let's do it all in one chunk.
|
||||
u32 srcLineStartAddr = srcBasePtr + (srcY * srcStride + srcX) * bpp;
|
||||
u32 dstLineStartAddr = dstBasePtr + (dstY * dstStride + dstX) * bpp;
|
||||
const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr);
|
||||
u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr);
|
||||
memcpy(dst, src, width * height * bpp);
|
||||
} else {
|
||||
for (int y = 0; y < height; y++) {
|
||||
u32 srcLineStartAddr = srcBasePtr + ((y + srcY) * srcStride + srcX) * bpp;
|
||||
u32 dstLineStartAddr = dstBasePtr + ((y + dstY) * dstStride + dstX) * bpp;
|
||||
|
||||
const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr);
|
||||
u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr);
|
||||
memcpy(dst, src, width * bpp);
|
||||
}
|
||||
}
|
||||
|
||||
textureCache_.Invalidate(dstBasePtr + (dstY * dstStride + dstX) * bpp, height * dstStride * bpp, GPU_INVALIDATE_HINT);
|
||||
framebufferManager_.NotifyBlockTransferAfter(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason);
|
||||
}
|
||||
|
||||
#ifndef MOBILE_DEVICE
|
||||
CBreakPoints::ExecMemCheck(srcBasePtr + (srcY * srcStride + srcX) * bpp, false, height * srcStride * bpp, currentMIPS->pc);
|
||||
CBreakPoints::ExecMemCheck(dstBasePtr + (srcY * dstStride + srcX) * bpp, true, height * dstStride * bpp, currentMIPS->pc);
|
||||
#endif
|
||||
|
||||
// TODO: Correct timing appears to be 1.9, but erring a bit low since some of our other timing is inaccurate.
|
||||
cyclesExecuted += ((height * width * bpp) * 16) / 10;
|
||||
}
|
||||
|
||||
void GPU_GLES::InvalidateCache(u32 addr, int size, GPUInvalidationType type) {
|
||||
GPUEvent ev(GPU_EVENT_INVALIDATE_CACHE);
|
||||
ev.invalidate_cache.addr = addr;
|
||||
ev.invalidate_cache.size = size;
|
||||
ev.invalidate_cache.type = type;
|
||||
ScheduleEvent(ev);
|
||||
}
|
||||
|
||||
void GPU_GLES::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type) {
|
||||
if (size > 0)
|
||||
textureCache_.Invalidate(addr, size, type);
|
||||
else
|
||||
textureCache_.InvalidateAll(type);
|
||||
|
||||
if (type != GPU_INVALIDATE_ALL && framebufferManager_.MayIntersectFramebuffer(addr)) {
|
||||
// If we're doing block transfers, we shouldn't need this, and it'll only confuse us.
|
||||
// Vempire invalidates (with writeback) after drawing, but before blitting.
|
||||
if (!g_Config.bBlockTransferGPU || type == GPU_INVALIDATE_SAFE) {
|
||||
framebufferManager_.UpdateFromMemory(addr, size, type == GPU_INVALIDATE_SAFE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GPU_GLES::NotifyVideoUpload(u32 addr, int size, int width, int format) {
|
||||
if (Memory::IsVRAMAddress(addr)) {
|
||||
framebufferManager_.NotifyVideoUpload(addr, size, width, (GEBufferFormat)format);
|
||||
}
|
||||
textureCache_.NotifyVideoUpload(addr, size, width, (GEBufferFormat)format);
|
||||
InvalidateCache(addr, size, GPU_INVALIDATE_SAFE);
|
||||
}
|
||||
|
||||
void GPU_GLES::PerformMemoryCopyInternal(u32 dest, u32 src, int size) {
|
||||
if (!framebufferManager_.NotifyFramebufferCopy(src, dest, size, false, gstate_c.skipDrawReason)) {
|
||||
// We use a little hack for Download/Upload using a VRAM mirror.
|
||||
// Since they're identical we don't need to copy.
|
||||
if (!Memory::IsVRAMAddress(dest) || (dest ^ 0x00400000) != src) {
|
||||
Memory::Memcpy(dest, src, size);
|
||||
}
|
||||
}
|
||||
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
|
||||
}
|
||||
|
||||
void GPU_GLES::PerformMemorySetInternal(u32 dest, u8 v, int size) {
|
||||
if (!framebufferManager_.NotifyFramebufferCopy(dest, dest, size, true, gstate_c.skipDrawReason)) {
|
||||
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
|
||||
}
|
||||
}
|
||||
|
||||
void GPU_GLES::PerformStencilUploadInternal(u32 dest, int size) {
|
||||
framebufferManager_.NotifyStencilUpload(dest, size);
|
||||
}
|
||||
|
||||
bool GPU_GLES::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()) {
|
||||
GPUEvent ev(GPU_EVENT_FB_MEMCPY);
|
||||
ev.fb_memcpy.dst = dest;
|
||||
ev.fb_memcpy.src = src;
|
||||
ev.fb_memcpy.size = size;
|
||||
ScheduleEvent(ev);
|
||||
|
||||
// This is a memcpy, so we need to wait for it to complete.
|
||||
SyncThread();
|
||||
} else {
|
||||
PerformMemoryCopyInternal(dest, src, size);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GPU_GLES::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;
|
||||
}
|
||||
|
||||
bool GPU_GLES::PerformMemoryDownload(u32 dest, int size) {
|
||||
// Cheat a bit to force a download of the framebuffer.
|
||||
// VRAM + 0x00400000 is simply a VRAM mirror.
|
||||
if (Memory::IsVRAMAddress(dest)) {
|
||||
return PerformMemoryCopy(dest ^ 0x00400000, dest, size);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GPU_GLES::PerformMemoryUpload(u32 dest, int size) {
|
||||
// Cheat a bit to force an upload of the framebuffer.
|
||||
// VRAM + 0x00400000 is simply a VRAM mirror.
|
||||
if (Memory::IsVRAMAddress(dest)) {
|
||||
return PerformMemoryCopy(dest, dest ^ 0x00400000, size);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GPU_GLES::PerformStencilUpload(u32 dest, int size) {
|
||||
if (framebufferManager_.MayIntersectFramebuffer(dest)) {
|
||||
if (IsOnSeparateCPUThread()) {
|
||||
GPUEvent ev(GPU_EVENT_FB_STENCIL_UPLOAD);
|
||||
ev.fb_stencil_upload.dst = dest;
|
||||
ev.fb_stencil_upload.size = size;
|
||||
ScheduleEvent(ev);
|
||||
} else {
|
||||
PerformStencilUploadInternal(dest, size);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GPU_GLES::ClearCacheNextFrame() {
|
||||
textureCache_.ClearNextFrame();
|
||||
}
|
||||
|
||||
void GPU_GLES::Resized() {
|
||||
resized_ = true;
|
||||
framebufferManager_.Resized();
|
||||
textureCacheGL_->ClearNextFrame();
|
||||
}
|
||||
|
||||
void GPU_GLES::ClearShaderCache() {
|
||||
@@ -2385,7 +2113,7 @@ void GPU_GLES::CleanupBeforeUI() {
|
||||
}
|
||||
|
||||
std::vector<FramebufferInfo> GPU_GLES::GetFramebufferList() {
|
||||
return framebufferManager_.GetFramebufferList();
|
||||
return framebufferManagerGL_->GetFramebufferList();
|
||||
}
|
||||
|
||||
void GPU_GLES::DoState(PointerWrap &p) {
|
||||
@@ -2395,21 +2123,21 @@ void GPU_GLES::DoState(PointerWrap &p) {
|
||||
// None of these are necessary when saving.
|
||||
// In Freeze-Frame mode, we don't want to do any of this.
|
||||
if (p.mode == p.MODE_READ && !PSP_CoreParameter().frozen) {
|
||||
textureCache_.Clear(true);
|
||||
textureCacheGL_->Clear(true);
|
||||
depalShaderCache_.Clear();
|
||||
drawEngine_.ClearTrackedVertexArrays();
|
||||
|
||||
gstate_c.textureChanged = TEXCHANGE_UPDATED;
|
||||
framebufferManager_.DestroyAllFBOs(true);
|
||||
framebufferManagerGL_->DestroyAllFBOs(true);
|
||||
shaderManager_->ClearCache(true);
|
||||
}
|
||||
}
|
||||
|
||||
bool GPU_GLES::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) {
|
||||
u32 fb_address = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.getFrameBufRawAddress() : framebufferManager_.DisplayFramebufAddr();
|
||||
int fb_stride = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufStride() : framebufferManager_.DisplayFramebufStride();
|
||||
GEBufferFormat format = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufFormat() : framebufferManager_.DisplayFramebufFormat();
|
||||
return framebufferManager_.GetFramebuffer(fb_address, fb_stride, format, buffer, maxRes);
|
||||
u32 fb_address = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.getFrameBufRawAddress() : framebufferManagerGL_->DisplayFramebufAddr();
|
||||
int fb_stride = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufStride() : framebufferManagerGL_->DisplayFramebufStride();
|
||||
GEBufferFormat format = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufFormat() : framebufferManagerGL_->DisplayFramebufFormat();
|
||||
return framebufferManagerGL_->GetFramebuffer(fb_address, fb_stride, format, buffer, maxRes);
|
||||
}
|
||||
|
||||
bool GPU_GLES::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) {
|
||||
@@ -2419,14 +2147,14 @@ bool GPU_GLES::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) {
|
||||
u32 z_address = gstate.getDepthBufRawAddress();
|
||||
int z_stride = gstate.DepthBufStride();
|
||||
|
||||
return framebufferManager_.GetDepthbuffer(fb_address, fb_stride, z_address, z_stride, buffer);
|
||||
return framebufferManagerGL_->GetDepthbuffer(fb_address, fb_stride, z_address, z_stride, buffer);
|
||||
}
|
||||
|
||||
bool GPU_GLES::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) {
|
||||
u32 fb_address = gstate.getFrameBufRawAddress();
|
||||
int fb_stride = gstate.FrameBufStride();
|
||||
|
||||
return framebufferManager_.GetStencilbuffer(fb_address, fb_stride, buffer);
|
||||
return framebufferManagerGL_->GetStencilbuffer(fb_address, fb_stride, buffer);
|
||||
}
|
||||
|
||||
bool GPU_GLES::GetCurrentTexture(GPUDebugBuffer &buffer, int level) {
|
||||
@@ -2445,8 +2173,8 @@ bool GPU_GLES::GetCurrentTexture(GPUDebugBuffer &buffer, int level) {
|
||||
gstate.texbufwidth[0] = gstate.texbufwidth[level];
|
||||
}
|
||||
|
||||
textureCache_.SetTexture(true);
|
||||
textureCache_.ApplyTexture();
|
||||
textureCacheGL_->SetTexture(true);
|
||||
textureCacheGL_->ApplyTexture();
|
||||
int w = gstate.getTextureWidth(level);
|
||||
int h = gstate.getTextureHeight(level);
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
|
||||
@@ -2467,7 +2195,7 @@ bool GPU_GLES::GetCurrentTexture(GPUDebugBuffer &buffer, int level) {
|
||||
}
|
||||
|
||||
bool GPU_GLES::GetCurrentClut(GPUDebugBuffer &buffer) {
|
||||
return textureCache_.GetCurrentClutBuffer(buffer);
|
||||
return textureCacheGL_->GetCurrentClutBuffer(buffer);
|
||||
}
|
||||
|
||||
bool GPU_GLES::GetOutputFramebuffer(GPUDebugBuffer &buffer) {
|
||||
|
||||
+10
-26
@@ -40,24 +40,15 @@ public:
|
||||
// This gets called on startup and when we get back from settings.
|
||||
void CheckGPUFeatures();
|
||||
|
||||
void InitClear() override;
|
||||
void Reinitialize() override;
|
||||
void PreExecuteOp(u32 op, u32 diff) override;
|
||||
void Execute_Generic(u32 op, u32 diff);
|
||||
void ExecuteOp(u32 op, u32 diff) override;
|
||||
|
||||
void ReapplyGfxStateInternal() override;
|
||||
void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override;
|
||||
void CopyDisplayToOutput() override;
|
||||
void BeginFrame() override;
|
||||
void GetStats(char *buffer, size_t bufsize) override;
|
||||
void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override;
|
||||
void NotifyVideoUpload(u32 addr, int size, int width, int format) override;
|
||||
bool PerformMemoryCopy(u32 dest, u32 src, int size) override;
|
||||
bool PerformMemorySet(u32 dest, u8 v, int size) override;
|
||||
bool PerformMemoryDownload(u32 dest, int size) override;
|
||||
bool PerformMemoryUpload(u32 dest, int size) override;
|
||||
bool PerformStencilUpload(u32 dest, int size) override;
|
||||
|
||||
void ClearCacheNextFrame() override;
|
||||
void DeviceLost() override; // Only happens on Android. Drop all textures and shaders.
|
||||
void DeviceRestore() override;
|
||||
@@ -65,12 +56,10 @@ public:
|
||||
void DumpNextFrame() override;
|
||||
void DoState(PointerWrap &p) override;
|
||||
|
||||
// Called by the window system if the window size changed. This will be reflected in PSPCoreParam.pixel*.
|
||||
void Resized() override;
|
||||
void ClearShaderCache() override;
|
||||
void CleanupBeforeUI() override;
|
||||
bool DecodeTexture(u8 *dest, const GPUgstate &state) override {
|
||||
return textureCache_.DecodeTexture(dest, state);
|
||||
return textureCacheGL_->DecodeTexture(dest, state);
|
||||
}
|
||||
bool FramebufferDirty() override;
|
||||
bool FramebufferReallyDirty() override;
|
||||
@@ -160,7 +149,6 @@ public:
|
||||
|
||||
protected:
|
||||
void FastRunLoop(DisplayList &list) override;
|
||||
void ProcessEvent(GPUEvent ev) override;
|
||||
void FastLoadBoneMatrix(u32 target) override;
|
||||
void FinishDeferred() override;
|
||||
|
||||
@@ -168,30 +156,26 @@ private:
|
||||
void Flush() {
|
||||
drawEngine_.Flush();
|
||||
}
|
||||
void DoBlockTransfer(u32 skipDrawReason);
|
||||
void CheckFlushOp(int cmd, u32 diff);
|
||||
void BuildReportingInfo();
|
||||
void InitClearInternal();
|
||||
void BeginFrameInternal();
|
||||
void CopyDisplayToOutputInternal();
|
||||
void PerformMemoryCopyInternal(u32 dest, u32 src, int size);
|
||||
void PerformMemorySetInternal(u32 dest, u8 v, int size);
|
||||
void PerformStencilUploadInternal(u32 dest, int size);
|
||||
void InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type);
|
||||
void ReinitializeInternal();
|
||||
|
||||
void InitClearInternal() override;
|
||||
void BeginFrameInternal() override;
|
||||
void CopyDisplayToOutputInternal() override;
|
||||
void ReinitializeInternal() override;
|
||||
|
||||
inline void UpdateVsyncInterval(bool force);
|
||||
void UpdateCmdInfo();
|
||||
|
||||
static CommandInfo cmdInfo_[256];
|
||||
|
||||
FramebufferManager framebufferManager_;
|
||||
TextureCache textureCache_;
|
||||
FramebufferManager *framebufferManagerGL_;
|
||||
TextureCache *textureCacheGL_;
|
||||
DepalShaderCache depalShaderCache_;
|
||||
DrawEngineGLES drawEngine_;
|
||||
FragmentTestCache fragmentTestCache_;
|
||||
ShaderManager *shaderManager_;
|
||||
|
||||
bool resized_;
|
||||
int lastVsync_;
|
||||
|
||||
std::string reportingPrimaryInfo_;
|
||||
|
||||
+272
-1
@@ -19,10 +19,16 @@
|
||||
#include "Core/HLE/sceKernelInterrupt.h"
|
||||
#include "Core/HLE/sceKernelThread.h"
|
||||
#include "Core/HLE/sceGe.h"
|
||||
#include "Core/Debugger/Breakpoints.h"
|
||||
#include "Core/MemMapHelpers.h"
|
||||
#include "GPU/Common/FramebufferCommon.h"
|
||||
#include "GPU/Common/TextureCacheCommon.h"
|
||||
|
||||
GPUCommon::GPUCommon() :
|
||||
dumpNextFrame_(false),
|
||||
dumpThisFrame_(false)
|
||||
dumpThisFrame_(false),
|
||||
framebufferManager_(nullptr),
|
||||
resized_(false)
|
||||
{
|
||||
// This assert failed on GCC x86 32-bit (but not MSVC 32-bit!) before adding the
|
||||
// "padding" field at the end. This is important for save state compatibility.
|
||||
@@ -39,6 +45,7 @@ GPUCommon::GPUCommon() :
|
||||
}
|
||||
|
||||
GPUCommon::~GPUCommon() {
|
||||
delete framebufferManager_;
|
||||
}
|
||||
|
||||
void GPUCommon::BeginHostFrame() {
|
||||
@@ -49,6 +56,14 @@ void GPUCommon::EndHostFrame() {
|
||||
|
||||
}
|
||||
|
||||
void GPUCommon::InitClear() {
|
||||
ScheduleEvent(GPU_EVENT_INIT_CLEAR);
|
||||
}
|
||||
|
||||
void GPUCommon::CopyDisplayToOutput() {
|
||||
ScheduleEvent(GPU_EVENT_COPY_DISPLAY_TO_OUTPUT);
|
||||
}
|
||||
|
||||
void GPUCommon::Reinitialize() {
|
||||
easy_guard guard(listLock);
|
||||
memset(dls, 0, sizeof(dls));
|
||||
@@ -65,6 +80,7 @@ void GPUCommon::Reinitialize() {
|
||||
timeSpentStepping_ = 0.0;
|
||||
interruptsEnabled_ = true;
|
||||
UpdateTickEstimate(0);
|
||||
ScheduleEvent(GPU_EVENT_REINITIALIZE);
|
||||
}
|
||||
|
||||
void GPUCommon::PopDLQueue() {
|
||||
@@ -93,6 +109,11 @@ bool GPUCommon::BusyDrawing() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void GPUCommon::Resized() {
|
||||
resized_ = true;
|
||||
framebufferManager_->Resized();
|
||||
}
|
||||
|
||||
u32 GPUCommon::DrawSync(int mode) {
|
||||
if (ThreadEnabled()) {
|
||||
// Sync first, because the CPU is usually faster than the emulated GPU.
|
||||
@@ -677,8 +698,37 @@ void GPUCommon::ProcessEvent(GPUEvent ev) {
|
||||
ReapplyGfxStateInternal();
|
||||
break;
|
||||
|
||||
case GPU_EVENT_INIT_CLEAR:
|
||||
InitClearInternal();
|
||||
break;
|
||||
|
||||
case GPU_EVENT_BEGIN_FRAME:
|
||||
BeginFrameInternal();
|
||||
break;
|
||||
|
||||
case GPU_EVENT_COPY_DISPLAY_TO_OUTPUT:
|
||||
CopyDisplayToOutputInternal();
|
||||
break;
|
||||
|
||||
case GPU_EVENT_INVALIDATE_CACHE:
|
||||
InvalidateCacheInternal(ev.invalidate_cache.addr, ev.invalidate_cache.size, ev.invalidate_cache.type);
|
||||
break;
|
||||
|
||||
case GPU_EVENT_FB_MEMCPY:
|
||||
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;
|
||||
|
||||
case GPU_EVENT_FB_STENCIL_UPLOAD:
|
||||
PerformStencilUploadInternal(ev.fb_stencil_upload.dst, ev.fb_stencil_upload.size);
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR_LOG_REPORT(G3D, "Unexpected GPU event type: %d", (int)ev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1312,3 +1362,224 @@ void GPUCommon::AdvanceVerts(u32 vertType, int count, int bytesRead) {
|
||||
gstate_c.vertexAddr += bytesRead;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GPUCommon::DoBlockTransfer(u32 skipDrawReason) {
|
||||
// TODO: This is used a lot to copy data around between render targets and textures,
|
||||
// and also to quickly load textures from RAM to VRAM. So we should do checks like the following:
|
||||
// * Does dstBasePtr point to an existing texture? If so maybe reload it immediately.
|
||||
//
|
||||
// * Does srcBasePtr point to a render target, and dstBasePtr to a texture? If so
|
||||
// either copy between rt and texture or reassign the texture to point to the render target
|
||||
//
|
||||
// etc....
|
||||
|
||||
u32 srcBasePtr = gstate.getTransferSrcAddress();
|
||||
u32 srcStride = gstate.getTransferSrcStride();
|
||||
|
||||
u32 dstBasePtr = gstate.getTransferDstAddress();
|
||||
u32 dstStride = gstate.getTransferDstStride();
|
||||
|
||||
int srcX = gstate.getTransferSrcX();
|
||||
int srcY = gstate.getTransferSrcY();
|
||||
|
||||
int dstX = gstate.getTransferDstX();
|
||||
int dstY = gstate.getTransferDstY();
|
||||
|
||||
int width = gstate.getTransferWidth();
|
||||
int height = gstate.getTransferHeight();
|
||||
|
||||
int bpp = gstate.getTransferBpp();
|
||||
|
||||
DEBUG_LOG(G3D, "Block transfer: %08x/%x -> %08x/%x, %ix%ix%i (%i,%i)->(%i,%i)", srcBasePtr, srcStride, dstBasePtr, dstStride, width, height, bpp, srcX, srcY, dstX, dstY);
|
||||
|
||||
if (!Memory::IsValidAddress(srcBasePtr)) {
|
||||
ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad source transfer address %08x!", srcBasePtr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Memory::IsValidAddress(dstBasePtr)) {
|
||||
ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad destination transfer address %08x!", dstBasePtr);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that the last address of both source and dest are valid addresses
|
||||
|
||||
u32 srcLastAddr = srcBasePtr + ((srcY + height - 1) * srcStride + (srcX + width - 1)) * bpp;
|
||||
u32 dstLastAddr = dstBasePtr + ((dstY + height - 1) * dstStride + (dstX + width - 1)) * bpp;
|
||||
|
||||
if (!Memory::IsValidAddress(srcLastAddr)) {
|
||||
ERROR_LOG_REPORT(G3D, "Bottom-right corner of source of block transfer is at an invalid address: %08x", srcLastAddr);
|
||||
return;
|
||||
}
|
||||
if (!Memory::IsValidAddress(dstLastAddr)) {
|
||||
ERROR_LOG_REPORT(G3D, "Bottom-right corner of destination of block transfer is at an invalid address: %08x", srcLastAddr);
|
||||
return;
|
||||
}
|
||||
|
||||
// Tell the framebuffer manager to take action if possible. If it does the entire thing, let's just return.
|
||||
if (!framebufferManager_->NotifyBlockTransferBefore(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason)) {
|
||||
// Do the copy! (Hm, if we detect a drawn video frame (see below) then we could maybe skip this?)
|
||||
// Can use GetPointerUnchecked because we checked the addresses above. We could also avoid them
|
||||
// entirely by walking a couple of pointers...
|
||||
if (srcStride == dstStride && (u32)width == srcStride) {
|
||||
// Common case in God of War, let's do it all in one chunk.
|
||||
u32 srcLineStartAddr = srcBasePtr + (srcY * srcStride + srcX) * bpp;
|
||||
u32 dstLineStartAddr = dstBasePtr + (dstY * dstStride + dstX) * bpp;
|
||||
const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr);
|
||||
u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr);
|
||||
memcpy(dst, src, width * height * bpp);
|
||||
} else {
|
||||
for (int y = 0; y < height; y++) {
|
||||
u32 srcLineStartAddr = srcBasePtr + ((y + srcY) * srcStride + srcX) * bpp;
|
||||
u32 dstLineStartAddr = dstBasePtr + ((y + dstY) * dstStride + dstX) * bpp;
|
||||
|
||||
const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr);
|
||||
u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr);
|
||||
memcpy(dst, src, width * bpp);
|
||||
}
|
||||
}
|
||||
|
||||
textureCache_->Invalidate(dstBasePtr + (dstY * dstStride + dstX) * bpp, height * dstStride * bpp, GPU_INVALIDATE_HINT);
|
||||
framebufferManager_->NotifyBlockTransferAfter(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason);
|
||||
}
|
||||
|
||||
#ifndef MOBILE_DEVICE
|
||||
CBreakPoints::ExecMemCheck(srcBasePtr + (srcY * srcStride + srcX) * bpp, false, height * srcStride * bpp, currentMIPS->pc);
|
||||
CBreakPoints::ExecMemCheck(dstBasePtr + (srcY * dstStride + srcX) * bpp, true, height * dstStride * bpp, currentMIPS->pc);
|
||||
#endif
|
||||
|
||||
// TODO: Correct timing appears to be 1.9, but erring a bit low since some of our other timing is inaccurate.
|
||||
cyclesExecuted += ((height * width * bpp) * 16) / 10;
|
||||
}
|
||||
|
||||
void GPUCommon::PerformMemoryCopyInternal(u32 dest, u32 src, int size) {
|
||||
if (!framebufferManager_->NotifyFramebufferCopy(src, dest, size, false, gstate_c.skipDrawReason)) {
|
||||
// We use a little hack for Download/Upload using a VRAM mirror.
|
||||
// Since they're identical we don't need to copy.
|
||||
if (!Memory::IsVRAMAddress(dest) || (dest ^ 0x00400000) != src) {
|
||||
Memory::Memcpy(dest, src, size);
|
||||
}
|
||||
}
|
||||
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
|
||||
}
|
||||
|
||||
void GPUCommon::PerformMemorySetInternal(u32 dest, u8 v, int size) {
|
||||
if (!framebufferManager_->NotifyFramebufferCopy(dest, dest, size, true, gstate_c.skipDrawReason)) {
|
||||
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
|
||||
}
|
||||
}
|
||||
|
||||
bool GPUCommon::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()) {
|
||||
GPUEvent ev(GPU_EVENT_FB_MEMCPY);
|
||||
ev.fb_memcpy.dst = dest;
|
||||
ev.fb_memcpy.src = src;
|
||||
ev.fb_memcpy.size = size;
|
||||
ScheduleEvent(ev);
|
||||
|
||||
// This is a memcpy, so we need to wait for it to complete.
|
||||
SyncThread();
|
||||
} else {
|
||||
PerformMemoryCopyInternal(dest, src, size);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GPUCommon::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;
|
||||
}
|
||||
|
||||
bool GPUCommon::PerformMemoryDownload(u32 dest, int size) {
|
||||
// Cheat a bit to force a download of the framebuffer.
|
||||
// VRAM + 0x00400000 is simply a VRAM mirror.
|
||||
if (Memory::IsVRAMAddress(dest)) {
|
||||
return PerformMemoryCopy(dest ^ 0x00400000, dest, size);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GPUCommon::PerformMemoryUpload(u32 dest, int size) {
|
||||
// Cheat a bit to force an upload of the framebuffer.
|
||||
// VRAM + 0x00400000 is simply a VRAM mirror.
|
||||
if (Memory::IsVRAMAddress(dest)) {
|
||||
return PerformMemoryCopy(dest, dest ^ 0x00400000, size);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GPUCommon::InvalidateCache(u32 addr, int size, GPUInvalidationType type) {
|
||||
GPUEvent ev(GPU_EVENT_INVALIDATE_CACHE);
|
||||
ev.invalidate_cache.addr = addr;
|
||||
ev.invalidate_cache.size = size;
|
||||
ev.invalidate_cache.type = type;
|
||||
ScheduleEvent(ev);
|
||||
}
|
||||
|
||||
void GPUCommon::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type) {
|
||||
if (size > 0)
|
||||
textureCache_->Invalidate(addr, size, type);
|
||||
else
|
||||
textureCache_->InvalidateAll(type);
|
||||
|
||||
if (type != GPU_INVALIDATE_ALL && framebufferManager_->MayIntersectFramebuffer(addr)) {
|
||||
// If we're doing block transfers, we shouldn't need this, and it'll only confuse us.
|
||||
// Vempire invalidates (with writeback) after drawing, but before blitting.
|
||||
if (!g_Config.bBlockTransferGPU || type == GPU_INVALIDATE_SAFE) {
|
||||
framebufferManager_->UpdateFromMemory(addr, size, type == GPU_INVALIDATE_SAFE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GPUCommon::NotifyVideoUpload(u32 addr, int size, int width, int format) {
|
||||
if (Memory::IsVRAMAddress(addr)) {
|
||||
framebufferManager_->NotifyVideoUpload(addr, size, width, (GEBufferFormat)format);
|
||||
}
|
||||
textureCache_->NotifyVideoUpload(addr, size, width, (GEBufferFormat)format);
|
||||
InvalidateCache(addr, size, GPU_INVALIDATE_SAFE);
|
||||
}
|
||||
|
||||
bool GPUCommon::PerformStencilUpload(u32 dest, int size) {
|
||||
if (framebufferManager_->MayIntersectFramebuffer(dest)) {
|
||||
if (IsOnSeparateCPUThread()) {
|
||||
GPUEvent ev(GPU_EVENT_FB_STENCIL_UPLOAD);
|
||||
ev.fb_stencil_upload.dst = dest;
|
||||
ev.fb_stencil_upload.size = size;
|
||||
ScheduleEvent(ev);
|
||||
} else {
|
||||
PerformStencilUploadInternal(dest, size);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GPUCommon::PerformStencilUploadInternal(u32 dest, int size) {
|
||||
framebufferManager_->NotifyStencilUpload(dest, size);
|
||||
}
|
||||
@@ -14,6 +14,9 @@
|
||||
|
||||
typedef ThreadEventQueue<GPUInterface, GPUEvent, GPUEventType, GPU_EVENT_INVALID, GPU_EVENT_SYNC_THREAD, GPU_EVENT_FINISH_EVENT_LOOP> GPUThreadEventQueue;
|
||||
|
||||
class FramebufferManagerCommon;
|
||||
class TextureCacheCommon;
|
||||
|
||||
class GPUCommon : public GPUThreadEventQueue, public GPUDebugInterface {
|
||||
public:
|
||||
GPUCommon();
|
||||
@@ -31,6 +34,8 @@ public:
|
||||
interruptsEnabled_ = enable;
|
||||
}
|
||||
|
||||
void Resized() override;
|
||||
|
||||
void ExecuteOp(u32 op, u32 diff) override;
|
||||
void PreExecuteOp(u32 op, u32 diff) override;
|
||||
bool InterpretList(DisplayList &list) override;
|
||||
@@ -55,6 +60,17 @@ public:
|
||||
u32 Break(int mode) override;
|
||||
void ReapplyGfxState() override;
|
||||
|
||||
void CopyDisplayToOutput() override;
|
||||
void InitClear() override;
|
||||
bool PerformMemoryCopy(u32 dest, u32 src, int size) override;
|
||||
bool PerformMemorySet(u32 dest, u8 v, int size) override;
|
||||
bool PerformMemoryDownload(u32 dest, int size) override;
|
||||
bool PerformMemoryUpload(u32 dest, int size) override;
|
||||
|
||||
void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override;
|
||||
void NotifyVideoUpload(u32 addr, int size, int width, int format) override;
|
||||
bool PerformStencilUpload(u32 dest, int size) override;
|
||||
|
||||
void Execute_OffsetAddr(u32 op, u32 diff);
|
||||
void Execute_Origin(u32 op, u32 diff);
|
||||
void Execute_Jump(u32 op, u32 diff);
|
||||
@@ -135,6 +151,11 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void InitClearInternal() {}
|
||||
virtual void BeginFrameInternal() {}
|
||||
virtual void CopyDisplayToOutputInternal() {}
|
||||
virtual void ReinitializeInternal() {}
|
||||
|
||||
// To avoid virtual calls to PreExecuteOp().
|
||||
virtual void FastRunLoop(DisplayList &list) = 0;
|
||||
void SlowRunLoop(DisplayList &list);
|
||||
@@ -156,8 +177,15 @@ protected:
|
||||
virtual void FinishDeferred() {
|
||||
}
|
||||
|
||||
void DoBlockTransfer(u32 skipDrawReason);
|
||||
|
||||
void AdvanceVerts(u32 vertType, int count, int bytesRead);
|
||||
|
||||
void PerformMemoryCopyInternal(u32 dest, u32 src, int size);
|
||||
void PerformMemorySetInternal(u32 dest, u8 v, int size);
|
||||
void PerformStencilUploadInternal(u32 dest, int size);
|
||||
void InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type);
|
||||
|
||||
// Allows early unlocking with a guard. Do not double unlock.
|
||||
class easy_guard {
|
||||
public:
|
||||
@@ -170,6 +198,9 @@ protected:
|
||||
bool locked_;
|
||||
};
|
||||
|
||||
FramebufferManagerCommon *framebufferManager_;
|
||||
TextureCacheCommon *textureCache_;
|
||||
|
||||
typedef std::list<int> DisplayListQueue;
|
||||
|
||||
int nextListID;
|
||||
@@ -192,8 +223,10 @@ protected:
|
||||
bool dumpNextFrame_;
|
||||
bool dumpThisFrame_;
|
||||
bool interruptsEnabled_;
|
||||
bool resized_;
|
||||
|
||||
private:
|
||||
|
||||
// For CPU/GPU sync.
|
||||
#ifdef __ANDROID__
|
||||
alignas(16) std::atomic<u64> curTickEst_;
|
||||
|
||||
@@ -102,7 +102,7 @@ public:
|
||||
void BeginFrameVulkan(); // there's a BeginFrame in the base class, which this calls
|
||||
void EndFrame();
|
||||
|
||||
void Resized();
|
||||
void Resized() override;
|
||||
void DeviceLost();
|
||||
void DeviceRestore(VulkanContext *vulkan);
|
||||
void CopyDisplayToOutput();
|
||||
|
||||
+35
-316
@@ -393,26 +393,28 @@ static const CommandTableEntry commandTable[] = {
|
||||
GPU_Vulkan::GPU_Vulkan(GraphicsContext *ctx)
|
||||
: vulkan_((VulkanContext *)ctx->GetAPIContext()),
|
||||
drawEngine_(vulkan_),
|
||||
textureCache_(vulkan_),
|
||||
resized_(false),
|
||||
gfxCtx_(ctx) {
|
||||
UpdateVsyncInterval(true);
|
||||
CheckGPUFeatures();
|
||||
|
||||
shaderManager_ = new ShaderManagerVulkan(vulkan_);
|
||||
pipelineManager_ = new PipelineManagerVulkan(vulkan_);
|
||||
framebufferManager_ = new FramebufferManagerVulkan(vulkan_);
|
||||
drawEngine_.SetTextureCache(&textureCache_);
|
||||
drawEngine_.SetFramebufferManager(framebufferManager_);
|
||||
framebufferManagerVulkan_ = new FramebufferManagerVulkan(vulkan_);
|
||||
framebufferManager_ = framebufferManagerVulkan_;
|
||||
textureCacheVulkan_ = new TextureCacheVulkan(vulkan_);
|
||||
textureCache_ = textureCacheVulkan_;
|
||||
|
||||
drawEngine_.SetTextureCache(textureCacheVulkan_);
|
||||
drawEngine_.SetFramebufferManager(framebufferManagerVulkan_);
|
||||
drawEngine_.SetShaderManager(shaderManager_);
|
||||
drawEngine_.SetPipelineManager(pipelineManager_);
|
||||
framebufferManager_->Init();
|
||||
framebufferManager_->SetTextureCache(&textureCache_);
|
||||
framebufferManager_->SetDrawEngine(&drawEngine_);
|
||||
textureCache_.SetFramebufferManager(framebufferManager_);
|
||||
textureCache_.SetDepalShaderCache(&depalShaderCache_);
|
||||
textureCache_.SetShaderManager(shaderManager_);
|
||||
textureCache_.SetTransformDrawEngine(&drawEngine_);
|
||||
framebufferManagerVulkan_->Init();
|
||||
framebufferManagerVulkan_->SetTextureCache(textureCacheVulkan_);
|
||||
framebufferManagerVulkan_->SetDrawEngine(&drawEngine_);
|
||||
textureCacheVulkan_->SetFramebufferManager(framebufferManagerVulkan_);
|
||||
textureCacheVulkan_->SetDepalShaderCache(&depalShaderCache_);
|
||||
textureCacheVulkan_->SetShaderManager(shaderManager_);
|
||||
textureCacheVulkan_->SetTransformDrawEngine(&drawEngine_);
|
||||
|
||||
// Sanity check gstate
|
||||
if ((int *)&gstate.transferstart - (int *)&gstate != 0xEA) {
|
||||
@@ -448,13 +450,12 @@ GPU_Vulkan::GPU_Vulkan(GraphicsContext *ctx)
|
||||
// Update again after init to be sure of any silly driver problems.
|
||||
UpdateVsyncInterval(true);
|
||||
|
||||
textureCache_.NotifyConfigChanged();
|
||||
textureCacheVulkan_->NotifyConfigChanged();
|
||||
}
|
||||
|
||||
GPU_Vulkan::~GPU_Vulkan() {
|
||||
framebufferManager_->DestroyAllFBOs(true);
|
||||
framebufferManagerVulkan_->DestroyAllFBOs(true);
|
||||
depalShaderCache_.Clear();
|
||||
delete framebufferManager_;
|
||||
delete pipelineManager_;
|
||||
delete shaderManager_;
|
||||
}
|
||||
@@ -495,14 +496,14 @@ void GPU_Vulkan::BeginHostFrame() {
|
||||
BuildReportingInfo();
|
||||
UpdateCmdInfo();
|
||||
drawEngine_.Resized();
|
||||
textureCache_.NotifyConfigChanged();
|
||||
textureCacheVulkan_->NotifyConfigChanged();
|
||||
}
|
||||
resized_ = false;
|
||||
|
||||
textureCache_.StartFrame();
|
||||
textureCacheVulkan_->StartFrame();
|
||||
depalShaderCache_.Decimate();
|
||||
|
||||
framebufferManager_->BeginFrameVulkan();
|
||||
framebufferManagerVulkan_->BeginFrameVulkan();
|
||||
|
||||
shaderManager_->DirtyShader();
|
||||
shaderManager_->DirtyUniform(DIRTY_ALL);
|
||||
@@ -518,8 +519,8 @@ void GPU_Vulkan::BeginHostFrame() {
|
||||
|
||||
void GPU_Vulkan::EndHostFrame() {
|
||||
drawEngine_.EndFrame();
|
||||
framebufferManager_->EndFrame();
|
||||
textureCache_.EndFrame();
|
||||
framebufferManagerVulkan_->EndFrame();
|
||||
textureCacheVulkan_->EndFrame();
|
||||
}
|
||||
|
||||
// Needs to be called on GPU thread, not reporting thread.
|
||||
@@ -600,20 +601,11 @@ void GPU_Vulkan::BuildReportingInfo() {
|
||||
Reporting::UpdateConfig();
|
||||
}
|
||||
|
||||
void GPU_Vulkan::InitClear() {
|
||||
ScheduleEvent(GPU_EVENT_INIT_CLEAR);
|
||||
}
|
||||
|
||||
void GPU_Vulkan::Reinitialize() {
|
||||
GPUCommon::Reinitialize();
|
||||
ScheduleEvent(GPU_EVENT_REINITIALIZE);
|
||||
}
|
||||
|
||||
void GPU_Vulkan::ReinitializeInternal() {
|
||||
textureCache_.Clear(true);
|
||||
textureCacheVulkan_->Clear(true);
|
||||
depalShaderCache_.Clear();
|
||||
framebufferManager_->DestroyAllFBOs(true);
|
||||
framebufferManager_->Resized();
|
||||
framebufferManagerVulkan_->DestroyAllFBOs(true);
|
||||
framebufferManagerVulkan_->Resized();
|
||||
}
|
||||
|
||||
void GPU_Vulkan::InitClearInternal() {
|
||||
@@ -651,10 +643,6 @@ void GPU_Vulkan::UpdateCmdInfo() {
|
||||
// }
|
||||
}
|
||||
|
||||
void GPU_Vulkan::ReapplyGfxStateInternal() {
|
||||
GPUCommon::ReapplyGfxStateInternal();
|
||||
}
|
||||
|
||||
void GPU_Vulkan::BeginFrameInternal() {
|
||||
}
|
||||
|
||||
@@ -693,17 +681,13 @@ bool GPU_Vulkan::FramebufferReallyDirty() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void GPU_Vulkan::CopyDisplayToOutput() {
|
||||
ScheduleEvent(GPU_EVENT_COPY_DISPLAY_TO_OUTPUT);
|
||||
}
|
||||
|
||||
void GPU_Vulkan::CopyDisplayToOutputInternal() {
|
||||
// Flush anything left over.
|
||||
drawEngine_.Flush(curCmd_);
|
||||
|
||||
shaderManager_->DirtyLastShader();
|
||||
|
||||
framebufferManager_->CopyDisplayToOutput();
|
||||
framebufferManagerVulkan_->CopyDisplayToOutput();
|
||||
|
||||
gstate_c.textureChanged = TEXCHANGE_UPDATED;
|
||||
}
|
||||
@@ -738,45 +722,6 @@ void GPU_Vulkan::FastRunLoop(DisplayList &list) {
|
||||
void GPU_Vulkan::FinishDeferred() {
|
||||
}
|
||||
|
||||
void GPU_Vulkan::ProcessEvent(GPUEvent ev) {
|
||||
switch (ev.type) {
|
||||
case GPU_EVENT_INIT_CLEAR:
|
||||
InitClearInternal();
|
||||
break;
|
||||
|
||||
case GPU_EVENT_BEGIN_FRAME:
|
||||
BeginFrameInternal();
|
||||
break;
|
||||
|
||||
case GPU_EVENT_COPY_DISPLAY_TO_OUTPUT:
|
||||
CopyDisplayToOutputInternal();
|
||||
break;
|
||||
|
||||
case GPU_EVENT_INVALIDATE_CACHE:
|
||||
InvalidateCacheInternal(ev.invalidate_cache.addr, ev.invalidate_cache.size, ev.invalidate_cache.type);
|
||||
break;
|
||||
|
||||
case GPU_EVENT_FB_MEMCPY:
|
||||
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;
|
||||
|
||||
case GPU_EVENT_FB_STENCIL_UPLOAD:
|
||||
PerformStencilUploadInternal(ev.fb_stencil_upload.dst, ev.fb_stencil_upload.size);
|
||||
break;
|
||||
|
||||
case GPU_EVENT_REINITIALIZE:
|
||||
ReinitializeInternal();
|
||||
break;
|
||||
|
||||
default:
|
||||
GPUCommon::ProcessEvent(ev);
|
||||
}
|
||||
}
|
||||
|
||||
inline void GPU_Vulkan::CheckFlushOp(int cmd, u32 diff) {
|
||||
const u8 cmdFlags = cmdInfo_[cmd].flags;
|
||||
if ((cmdFlags & FLAG_FLUSHBEFORE) || (diff && (cmdFlags & FLAG_FLUSHBEFOREONCHANGE))) {
|
||||
@@ -1107,7 +1052,7 @@ void GPU_Vulkan::Execute_TexLevel(u32 op, u32 diff) {
|
||||
|
||||
void GPU_Vulkan::Execute_LoadClut(u32 op, u32 diff) {
|
||||
gstate_c.textureChanged |= TEXCHANGE_PARAMSONLY;
|
||||
textureCache_.LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes());
|
||||
textureCacheVulkan_->LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes());
|
||||
// This could be used to "dirty" textures with clut.
|
||||
}
|
||||
|
||||
@@ -1936,10 +1881,10 @@ void GPU_Vulkan::FastLoadBoneMatrix(u32 target) {
|
||||
}
|
||||
|
||||
void GPU_Vulkan::DeviceLost() {
|
||||
framebufferManager_->DeviceLost();
|
||||
framebufferManagerVulkan_->DeviceLost();
|
||||
drawEngine_.DeviceLost();
|
||||
pipelineManager_->DeviceLost();
|
||||
textureCache_.DeviceLost();
|
||||
textureCacheVulkan_->DeviceLost();
|
||||
depalShaderCache_.Clear();
|
||||
shaderManager_->ClearShaders();
|
||||
}
|
||||
@@ -1950,10 +1895,10 @@ void GPU_Vulkan::DeviceRestore() {
|
||||
BuildReportingInfo();
|
||||
UpdateCmdInfo();
|
||||
|
||||
framebufferManager_->DeviceRestore(vulkan_);
|
||||
framebufferManagerVulkan_->DeviceRestore(vulkan_);
|
||||
drawEngine_.DeviceRestore(vulkan_);
|
||||
pipelineManager_->DeviceRestore(vulkan_);
|
||||
textureCache_.DeviceRestore(vulkan_);
|
||||
textureCacheVulkan_->DeviceRestore(vulkan_);
|
||||
shaderManager_->DeviceRestore(vulkan_);
|
||||
}
|
||||
|
||||
@@ -1985,7 +1930,7 @@ void GPU_Vulkan::GetStats(char *buffer, size_t bufsize) {
|
||||
gpuStats.numCachedVertsDrawn,
|
||||
gpuStats.numUncachedVertsDrawn,
|
||||
(int)framebufferManager_->NumVFBs(),
|
||||
(int)textureCache_.NumLoadedTextures(),
|
||||
(int)textureCacheVulkan_->NumLoadedTextures(),
|
||||
gpuStats.numTexturesDecoded,
|
||||
gpuStats.numTextureInvalidations,
|
||||
shaderManager_->GetNumVertexShaders(),
|
||||
@@ -1997,234 +1942,8 @@ void GPU_Vulkan::GetStats(char *buffer, size_t bufsize) {
|
||||
);
|
||||
}
|
||||
|
||||
void GPU_Vulkan::DoBlockTransfer(u32 skipDrawReason) {
|
||||
// TODO: This is used a lot to copy data around between render targets and textures,
|
||||
// and also to quickly load textures from RAM to VRAM. So we should do checks like the following:
|
||||
// * Does dstBasePtr point to an existing texture? If so maybe reload it immediately.
|
||||
//
|
||||
// * Does srcBasePtr point to a render target, and dstBasePtr to a texture? If so
|
||||
// either copy between rt and texture or reassign the texture to point to the render target
|
||||
//
|
||||
// etc....
|
||||
|
||||
u32 srcBasePtr = gstate.getTransferSrcAddress();
|
||||
u32 srcStride = gstate.getTransferSrcStride();
|
||||
|
||||
u32 dstBasePtr = gstate.getTransferDstAddress();
|
||||
u32 dstStride = gstate.getTransferDstStride();
|
||||
|
||||
int srcX = gstate.getTransferSrcX();
|
||||
int srcY = gstate.getTransferSrcY();
|
||||
|
||||
int dstX = gstate.getTransferDstX();
|
||||
int dstY = gstate.getTransferDstY();
|
||||
|
||||
int width = gstate.getTransferWidth();
|
||||
int height = gstate.getTransferHeight();
|
||||
|
||||
int bpp = gstate.getTransferBpp();
|
||||
|
||||
DEBUG_LOG(G3D, "Block transfer: %08x/%x -> %08x/%x, %ix%ix%i (%i,%i)->(%i,%i)", srcBasePtr, srcStride, dstBasePtr, dstStride, width, height, bpp, srcX, srcY, dstX, dstY);
|
||||
|
||||
if (!Memory::IsValidAddress(srcBasePtr)) {
|
||||
ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad source transfer address %08x!", srcBasePtr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Memory::IsValidAddress(dstBasePtr)) {
|
||||
ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad destination transfer address %08x!", dstBasePtr);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that the last address of both source and dest are valid addresses
|
||||
|
||||
u32 srcLastAddr = srcBasePtr + ((srcY + height - 1) * srcStride + (srcX + width - 1)) * bpp;
|
||||
u32 dstLastAddr = dstBasePtr + ((dstY + height - 1) * dstStride + (dstX + width - 1)) * bpp;
|
||||
|
||||
if (!Memory::IsValidAddress(srcLastAddr)) {
|
||||
ERROR_LOG_REPORT(G3D, "Bottom-right corner of source of block transfer is at an invalid address: %08x", srcLastAddr);
|
||||
return;
|
||||
}
|
||||
if (!Memory::IsValidAddress(dstLastAddr)) {
|
||||
ERROR_LOG_REPORT(G3D, "Bottom-right corner of destination of block transfer is at an invalid address: %08x", srcLastAddr);
|
||||
return;
|
||||
}
|
||||
|
||||
// Tell the framebuffer manager to take action if possible. If it does the entire thing, let's just return.
|
||||
if (!framebufferManager_->NotifyBlockTransferBefore(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason)) {
|
||||
// Do the copy! (Hm, if we detect a drawn video frame (see below) then we could maybe skip this?)
|
||||
// Can use GetPointerUnchecked because we checked the addresses above. We could also avoid them
|
||||
// entirely by walking a couple of pointers...
|
||||
if (srcStride == dstStride && (u32)width == srcStride) {
|
||||
// Common case in God of War, let's do it all in one chunk.
|
||||
u32 srcLineStartAddr = srcBasePtr + (srcY * srcStride + srcX) * bpp;
|
||||
u32 dstLineStartAddr = dstBasePtr + (dstY * dstStride + dstX) * bpp;
|
||||
const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr);
|
||||
u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr);
|
||||
memcpy(dst, src, width * height * bpp);
|
||||
} else {
|
||||
for (int y = 0; y < height; y++) {
|
||||
u32 srcLineStartAddr = srcBasePtr + ((y + srcY) * srcStride + srcX) * bpp;
|
||||
u32 dstLineStartAddr = dstBasePtr + ((y + dstY) * dstStride + dstX) * bpp;
|
||||
|
||||
const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr);
|
||||
u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr);
|
||||
memcpy(dst, src, width * bpp);
|
||||
}
|
||||
}
|
||||
|
||||
textureCache_.Invalidate(dstBasePtr + (dstY * dstStride + dstX) * bpp, height * dstStride * bpp, GPU_INVALIDATE_HINT);
|
||||
framebufferManager_->NotifyBlockTransferAfter(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason);
|
||||
}
|
||||
|
||||
#ifndef MOBILE_DEVICE
|
||||
CBreakPoints::ExecMemCheck(srcBasePtr + (srcY * srcStride + srcX) * bpp, false, height * srcStride * bpp, currentMIPS->pc);
|
||||
CBreakPoints::ExecMemCheck(dstBasePtr + (srcY * dstStride + srcX) * bpp, true, height * dstStride * bpp, currentMIPS->pc);
|
||||
#endif
|
||||
|
||||
// TODO: Correct timing appears to be 1.9, but erring a bit low since some of our other timing is inaccurate.
|
||||
cyclesExecuted += ((height * width * bpp) * 16) / 10;
|
||||
}
|
||||
|
||||
void GPU_Vulkan::InvalidateCache(u32 addr, int size, GPUInvalidationType type) {
|
||||
GPUEvent ev(GPU_EVENT_INVALIDATE_CACHE);
|
||||
ev.invalidate_cache.addr = addr;
|
||||
ev.invalidate_cache.size = size;
|
||||
ev.invalidate_cache.type = type;
|
||||
ScheduleEvent(ev);
|
||||
}
|
||||
|
||||
void GPU_Vulkan::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type) {
|
||||
if (size > 0)
|
||||
textureCache_.Invalidate(addr, size, type);
|
||||
else
|
||||
textureCache_.InvalidateAll(type);
|
||||
|
||||
if (type != GPU_INVALIDATE_ALL && framebufferManager_->MayIntersectFramebuffer(addr)) {
|
||||
// If we're doing block transfers, we shouldn't need this, and it'll only confuse us.
|
||||
// Vempire invalidates (with writeback) after drawing, but before blitting.
|
||||
if (!g_Config.bBlockTransferGPU || type == GPU_INVALIDATE_SAFE) {
|
||||
framebufferManager_->UpdateFromMemory(addr, size, type == GPU_INVALIDATE_SAFE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GPU_Vulkan::PerformMemoryCopyInternal(u32 dest, u32 src, int size) {
|
||||
if (!framebufferManager_->NotifyFramebufferCopy(src, dest, size, false, gstate_c.skipDrawReason)) {
|
||||
// We use a little hack for Download/Upload using a VRAM mirror.
|
||||
// Since they're identical we don't need to copy.
|
||||
if (!Memory::IsVRAMAddress(dest) || (dest ^ 0x00400000) != src) {
|
||||
Memory::Memcpy(dest, src, size);
|
||||
}
|
||||
}
|
||||
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
|
||||
}
|
||||
|
||||
void GPU_Vulkan::PerformMemorySetInternal(u32 dest, u8 v, int size) {
|
||||
if (!framebufferManager_->NotifyFramebufferCopy(dest, dest, size, true, gstate_c.skipDrawReason)) {
|
||||
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
|
||||
}
|
||||
}
|
||||
|
||||
void GPU_Vulkan::PerformStencilUploadInternal(u32 dest, int size) {
|
||||
framebufferManager_->NotifyStencilUpload(dest, size);
|
||||
}
|
||||
|
||||
bool GPU_Vulkan::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()) {
|
||||
GPUEvent ev(GPU_EVENT_FB_MEMCPY);
|
||||
ev.fb_memcpy.dst = dest;
|
||||
ev.fb_memcpy.src = src;
|
||||
ev.fb_memcpy.size = size;
|
||||
ScheduleEvent(ev);
|
||||
|
||||
// This is a memcpy, so we need to wait for it to complete.
|
||||
SyncThread();
|
||||
} else {
|
||||
PerformMemoryCopyInternal(dest, src, size);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GPU_Vulkan::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 GPU_Vulkan::NotifyVideoUpload(u32 addr, int size, int width, int format) {
|
||||
if (Memory::IsVRAMAddress(addr)) {
|
||||
// TODO
|
||||
//framebufferManager_.NotifyVideoUpload(addr, size, width, (GEBufferFormat)format);
|
||||
}
|
||||
textureCache_.NotifyVideoUpload(addr, size, width, (GEBufferFormat)format);
|
||||
InvalidateCache(addr, size, GPU_INVALIDATE_SAFE);
|
||||
}
|
||||
|
||||
bool GPU_Vulkan::PerformMemoryDownload(u32 dest, int size) {
|
||||
// Cheat a bit to force a download of the framebuffer.
|
||||
// VRAM + 0x00400000 is simply a VRAM mirror.
|
||||
if (Memory::IsVRAMAddress(dest)) {
|
||||
return PerformMemoryCopy(dest ^ 0x00400000, dest, size);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GPU_Vulkan::PerformMemoryUpload(u32 dest, int size) {
|
||||
// Cheat a bit to force an upload of the framebuffer.
|
||||
// VRAM + 0x00400000 is simply a VRAM mirror.
|
||||
if (Memory::IsVRAMAddress(dest)) {
|
||||
return PerformMemoryCopy(dest, dest ^ 0x00400000, size);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GPU_Vulkan::PerformStencilUpload(u32 dest, int size) {
|
||||
if (framebufferManager_->MayIntersectFramebuffer(dest)) {
|
||||
if (IsOnSeparateCPUThread()) {
|
||||
GPUEvent ev(GPU_EVENT_FB_STENCIL_UPLOAD);
|
||||
ev.fb_stencil_upload.dst = dest;
|
||||
ev.fb_stencil_upload.size = size;
|
||||
ScheduleEvent(ev);
|
||||
} else {
|
||||
PerformStencilUploadInternal(dest, size);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GPU_Vulkan::ClearCacheNextFrame() {
|
||||
textureCache_.ClearNextFrame();
|
||||
}
|
||||
|
||||
void GPU_Vulkan::Resized() {
|
||||
resized_ = true;
|
||||
framebufferManager_->Resized();
|
||||
textureCacheVulkan_->ClearNextFrame();
|
||||
}
|
||||
|
||||
void GPU_Vulkan::ClearShaderCache() {
|
||||
@@ -2232,7 +1951,7 @@ void GPU_Vulkan::ClearShaderCache() {
|
||||
}
|
||||
|
||||
std::vector<FramebufferInfo> GPU_Vulkan::GetFramebufferList() {
|
||||
return framebufferManager_->GetFramebufferList();
|
||||
return framebufferManagerVulkan_->GetFramebufferList();
|
||||
}
|
||||
|
||||
void GPU_Vulkan::DoState(PointerWrap &p) {
|
||||
@@ -2242,11 +1961,11 @@ void GPU_Vulkan::DoState(PointerWrap &p) {
|
||||
// None of these are necessary when saving.
|
||||
// In Freeze-Frame mode, we don't want to do any of this.
|
||||
if (p.mode == p.MODE_READ && !PSP_CoreParameter().frozen) {
|
||||
textureCache_.Clear(true);
|
||||
textureCacheVulkan_->Clear(true);
|
||||
depalShaderCache_.Clear();
|
||||
|
||||
gstate_c.textureChanged = TEXCHANGE_UPDATED;
|
||||
framebufferManager_->DestroyAllFBOs(true);
|
||||
framebufferManagerVulkan_->DestroyAllFBOs(true);
|
||||
shaderManager_->ClearShaders();
|
||||
pipelineManager_->Clear();
|
||||
}
|
||||
|
||||
+6
-27
@@ -42,24 +42,13 @@ public:
|
||||
void BeginHostFrame() override;
|
||||
void EndHostFrame() override;
|
||||
|
||||
void InitClear() override;
|
||||
void Reinitialize() override;
|
||||
void PreExecuteOp(u32 op, u32 diff) override;
|
||||
void Execute_Generic(u32 op, u32 diff);
|
||||
void ExecuteOp(u32 op, u32 diff) override;
|
||||
|
||||
void ReapplyGfxStateInternal() override;
|
||||
void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override;
|
||||
void CopyDisplayToOutput() override;
|
||||
void NotifyVideoUpload(u32 addr, int size, int width, int format) override;
|
||||
void BeginFrame() override;
|
||||
void GetStats(char *buffer, size_t bufsize) override;
|
||||
void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override;
|
||||
bool PerformMemoryCopy(u32 dest, u32 src, int size) override;
|
||||
bool PerformMemorySet(u32 dest, u8 v, int size) override;
|
||||
bool PerformMemoryDownload(u32 dest, int size) override;
|
||||
bool PerformMemoryUpload(u32 dest, int size) override;
|
||||
bool PerformStencilUpload(u32 dest, int size) override;
|
||||
void ClearCacheNextFrame() override;
|
||||
void DeviceLost() override; // Only happens on Android. Drop all textures and shaders.
|
||||
void DeviceRestore() override;
|
||||
@@ -67,8 +56,6 @@ public:
|
||||
void DumpNextFrame() override;
|
||||
void DoState(PointerWrap &p) override;
|
||||
|
||||
// Called by the window system if the window size changed. This will be reflected in PSPCoreParam.pixel*.
|
||||
void Resized() override;
|
||||
void ClearShaderCache() override;
|
||||
bool DecodeTexture(u8 *dest, const GPUgstate &state) override {
|
||||
return false;
|
||||
@@ -150,10 +137,8 @@ public:
|
||||
bool GetCurrentSimpleVertices(int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices) override;
|
||||
bool DescribeCodePtr(const u8 *ptr, std::string &name) override;
|
||||
|
||||
|
||||
protected:
|
||||
void FastRunLoop(DisplayList &list) override;
|
||||
void ProcessEvent(GPUEvent ev) override;
|
||||
void FastLoadBoneMatrix(u32 target) override;
|
||||
void FinishDeferred() override;
|
||||
|
||||
@@ -161,25 +146,20 @@ private:
|
||||
void Flush() {
|
||||
drawEngine_.Flush(nullptr);
|
||||
}
|
||||
void DoBlockTransfer(u32 skipDrawReason);
|
||||
void CheckFlushOp(int cmd, u32 diff);
|
||||
void BuildReportingInfo();
|
||||
void InitClearInternal();
|
||||
void BeginFrameInternal();
|
||||
void CopyDisplayToOutputInternal();
|
||||
void PerformMemoryCopyInternal(u32 dest, u32 src, int size);
|
||||
void PerformMemorySetInternal(u32 dest, u8 v, int size);
|
||||
void PerformStencilUploadInternal(u32 dest, int size);
|
||||
void InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type);
|
||||
void ReinitializeInternal();
|
||||
void InitClearInternal() override;
|
||||
void BeginFrameInternal() override;
|
||||
void CopyDisplayToOutputInternal() override;
|
||||
void ReinitializeInternal() override;
|
||||
inline void UpdateVsyncInterval(bool force);
|
||||
void UpdateCmdInfo();
|
||||
static CommandInfo cmdInfo_[256];
|
||||
|
||||
GraphicsContext *gfxCtx_;
|
||||
VulkanContext *vulkan_;
|
||||
FramebufferManagerVulkan *framebufferManager_;
|
||||
TextureCacheVulkan textureCache_;
|
||||
FramebufferManagerVulkan *framebufferManagerVulkan_;
|
||||
TextureCacheVulkan *textureCacheVulkan_;
|
||||
DepalShaderCacheVulkan depalShaderCache_;
|
||||
DrawEngineVulkan drawEngine_;
|
||||
|
||||
@@ -189,7 +169,6 @@ private:
|
||||
// Manages state and pipeline objects
|
||||
PipelineManagerVulkan *pipelineManager_;
|
||||
|
||||
bool resized_;
|
||||
int lastVsync_;
|
||||
VkCommandBuffer curCmd_;
|
||||
|
||||
|
||||
@@ -95,8 +95,8 @@ public:
|
||||
void Clear(bool delete_them);
|
||||
void StartFrame();
|
||||
void EndFrame();
|
||||
void Invalidate(u32 addr, int size, GPUInvalidationType type);
|
||||
void InvalidateAll(GPUInvalidationType type);
|
||||
void Invalidate(u32 addr, int size, GPUInvalidationType type) override;
|
||||
void InvalidateAll(GPUInvalidationType type) override;
|
||||
void ClearNextFrame();
|
||||
|
||||
void DeviceLost();
|
||||
|
||||
Reference in new issue
Block a user