Merge pull request #9179 from hrydgard/more-gpu-centralization

More gpu centralization
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2016-12-22 10:43:32 +01:00
commit e3bca489be
15 files changed
+470 -1033

No files matched your search

+2
View File
@@ -236,6 +236,8 @@ public:
void SetRenderSize(VirtualFramebuffer *vfb);
void SetSafeSize(u16 w, u16 h);
virtual void Resized() = 0;
protected:
void UpdateSize();
-4
View File
@@ -63,10 +63,6 @@ TextureCacheCommon::~TextureCacheCommon() {
FreeAlignedMemory(clutBufRaw_);
}
bool TextureCacheCommon::SetOffsetTexture(u32 offset) {
return false;
}
int TextureCacheCommon::AttachedDrawingHeight() {
if (nextTexture_) {
if (nextTexture_->framebuffer) {
+3 -1
View File
@@ -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);
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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_;
+1 -1
View File
@@ -86,7 +86,7 @@ public:
virtual void Init() override;
void EndFrame();
void Resized();
void Resized() override;
void DeviceLost();
void CopyDisplayToOutput();
void SetLineWidth();
+52 -324
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
+33
View File
@@ -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_;
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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_;
+2 -2
View File
@@ -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();