diff --git a/core/emulator.cpp b/core/emulator.cpp index c6d765528..0e716e770 100644 --- a/core/emulator.cpp +++ b/core/emulator.cpp @@ -880,7 +880,7 @@ void Emulator::loadstate(Deserializer& deser) mmu_set_state(); getSh4Executor()->ResetCache(); - KillTex = true; + EventManager::event(Event::LoadState); } void Emulator::setNetworkState(bool online) diff --git a/core/hw/pvr/Renderer_if.h b/core/hw/pvr/Renderer_if.h index 369498ce3..c9a5e29af 100644 --- a/core/hw/pvr/Renderer_if.h +++ b/core/hw/pvr/Renderer_if.h @@ -1,6 +1,7 @@ #pragma once #include "types.h" #include "ta_ctx.h" +#include "emulator.h" #include extern u32 FrameCount; @@ -22,6 +23,8 @@ void rend_enable_renderer(bool enabled); bool rend_is_enabled(); void rend_serialize(Serializer& ser); void rend_deserialize(Deserializer& deser); +static void rend_updatePalette(); +static void rend_updateFogTable(); /////// extern TA_context* _pvrrc; @@ -54,7 +57,14 @@ struct FramebufferInfo struct Renderer { - virtual ~Renderer() = default; + Renderer() { + EventManager::listen(Event::Terminate, onEvent, this); + EventManager::listen(Event::LoadState, onEvent, this); + } + virtual ~Renderer() { + EventManager::unlisten(Event::Terminate, onEvent, this); + EventManager::unlisten(Event::LoadState, onEvent, this); + } virtual bool Init() = 0; virtual void Term() = 0; @@ -72,6 +82,25 @@ struct Renderer virtual bool Present() { return true; } virtual BaseTextureCacheData *GetTexture(TSP tsp, TCW tcw) { return nullptr; } + +protected: + bool resetTextureCache = false; + bool clearLastFrame = false; + bool updatePalette = true; + bool updateFogTable = true; + +private: + static void onEvent(Event event, void *arg) + { + Renderer *renderer = static_cast(arg); + renderer->resetTextureCache = true; + renderer->updatePalette = true; + renderer->updateFogTable = true; + if (event == Event::Terminate) + renderer->clearLastFrame = true; + } + friend void rend_updatePalette(); + friend void rend_updateFogTable(); }; extern Renderer* renderer; @@ -81,3 +110,11 @@ extern u32 fb_watch_addr_end; extern bool fb_dirty; void check_framebuffer_write(); +static inline void rend_updatePalette() { + if (renderer != nullptr) + renderer->updatePalette = true; +} +static inline void rend_updateFogTable() { + if (renderer != nullptr) + renderer->updateFogTable = true; +} diff --git a/core/hw/pvr/pvr.cpp b/core/hw/pvr/pvr.cpp index 22bead33e..92e325ef5 100644 --- a/core/hw/pvr/pvr.cpp +++ b/core/hw/pvr/pvr.cpp @@ -31,7 +31,6 @@ extern u8 ta_fsm[2049]; //[2048] stores the current state extern u32 ta_fsm_cl; extern u32 taRenderPass; // pvr_regs.cpp -extern bool fog_needs_update; extern bool pal_needs_update; namespace pvr @@ -39,7 +38,6 @@ namespace pvr void reset(bool hard) { - KillTex = true; Regs_Reset(hard); spg_Reset(hard); if (hard) @@ -92,7 +90,7 @@ void deserialize(Deserializer& deser) YUV_deserialize(deser); deser >> pvr_regs; - fog_needs_update = true; + rend_updateFogTable(); spg_Deserialize(deser); diff --git a/core/hw/pvr/pvr_regs.cpp b/core/hw/pvr/pvr_regs.cpp index 235c728fb..67eb5e714 100644 --- a/core/hw/pvr/pvr_regs.cpp +++ b/core/hw/pvr/pvr_regs.cpp @@ -6,7 +6,6 @@ #include bool pal_needs_update=true; -bool fog_needs_update=true; u8 pvr_regs[pvr_RegSize]; @@ -221,7 +220,7 @@ void pvr_WriteReg(u32 paddr,u32 data) if (addr >= PALETTE_RAM_START_addr && PvrReg(addr,u32) != data) pal_needs_update = true; else if (addr >= FOG_TABLE_START_addr && addr <= FOG_TABLE_END_addr && PvrReg(addr,u32) != data) - fog_needs_update = true; + rend_updateFogTable(); break; } PvrReg(addr, u32) = data; diff --git a/core/nullDC.cpp b/core/nullDC.cpp index 893df5c3f..8e60388a3 100644 --- a/core/nullDC.cpp +++ b/core/nullDC.cpp @@ -281,7 +281,6 @@ void dc_loadstate(int index) } free(data); - EventManager::event(Event::LoadState); } time_t dc_getStateCreationDate(int index) diff --git a/core/rend/TexCache.cpp b/core/rend/TexCache.cpp index 63fb44bf0..35191ea1f 100644 --- a/core/rend/TexCache.cpp +++ b/core/rend/TexCache.cpp @@ -14,12 +14,10 @@ const u8 *vq_codebook; u32 palette_index; -bool KillTex=false; u32 palette16_ram[1024]; u32 palette32_ram[1024]; u32 pal_hash_256[4]; u32 pal_hash_16[64]; -bool palette_updated; extern bool pal_needs_update; // Rough approximation of LoD bias from D adjust param, only used to increase LoD @@ -87,7 +85,7 @@ void palette_update() if (!pal_needs_update) return; pal_needs_update = false; - palette_updated = true; + rend_updatePalette(); if (!isDirectX(config::RendererType)) { diff --git a/core/rend/TexCache.h b/core/rend/TexCache.h index 827d71015..9fedcc679 100644 --- a/core/rend/TexCache.h +++ b/core/rend/TexCache.h @@ -16,11 +16,8 @@ constexpr int VQ_CODEBOOK_SIZE = 256 * 8; extern u32 palette_index; extern u32 palette16_ram[1024]; extern u32 palette32_ram[1024]; -extern bool fog_needs_update; extern u32 pal_hash_256[4]; extern u32 pal_hash_16[64]; -extern bool KillTex; -extern bool palette_updated; extern u32 detwiddle[2][11][1024]; @@ -818,7 +815,6 @@ class BaseTextureCache texture.Delete(); cache.clear(); - KillTex = false; INFO_LOG(RENDERER, "Texture cache cleared"); } diff --git a/core/rend/dx11/dx11_renderer.cpp b/core/rend/dx11/dx11_renderer.cpp index c4246e388..199c586f1 100644 --- a/core/rend/dx11/dx11_renderer.cpp +++ b/core/rend/dx11/dx11_renderer.cpp @@ -158,7 +158,7 @@ bool DX11Renderer::Init() quad->init(device, deviceContext, shaders); n2Helper.init(device, deviceContext); - fog_needs_update = true; + updateFogTable = true; if (!success) { @@ -318,8 +318,10 @@ BaseTextureCacheData *DX11Renderer::GetTexture(TSP tsp, TCW tcw) void DX11Renderer::Process(TA_context* ctx) { - if (KillTex) + if (resetTextureCache) { texCache.Clear(); + resetTextureCache = false; + } texCache.Cleanup(); ta_parse(ctx, true); @@ -936,7 +938,7 @@ void DX11Renderer::drawStrips() bool DX11Renderer::RenderLastFrame() { - if (!frameRenderedOnce) + if (!frameRenderedOnce || clearLastFrame) return false; displayFramebuffer(); return true; @@ -1222,9 +1224,9 @@ void DX11Renderer::readRttRenderTarget(u32 texAddress) void DX11Renderer::updatePaletteTexture() { - if (palette_updated) + if (updatePalette) { - palette_updated = false; + updatePalette = false; deviceContext->UpdateSubresource(paletteTexture, 0, nullptr, palette32_ram, 32 * sizeof(u32), 32 * sizeof(u32) * 32); } deviceContext->PSSetShaderResources(1, 1, &paletteTextureView.get()); @@ -1235,9 +1237,9 @@ void DX11Renderer::updateFogTexture() { if (!config::Fog) return; - if (fog_needs_update) + if (updateFogTable) { - fog_needs_update = false; + updateFogTable = false; u8 temp_tex_buffer[256]; MakeFogTexture(temp_tex_buffer); diff --git a/core/rend/dx11/dx11_renderer.h b/core/rend/dx11/dx11_renderer.h index c14678a87..c6d0ca63e 100644 --- a/core/rend/dx11/dx11_renderer.h +++ b/core/rend/dx11/dx11_renderer.h @@ -45,6 +45,7 @@ struct DX11Renderer : public Renderer if (!frameRendered) return false; frameRendered = false; + clearLastFrame = false; #ifndef LIBRETRO imguiDriver->setFrameRendered(); #else diff --git a/core/rend/dx9/d3d_renderer.cpp b/core/rend/dx9/d3d_renderer.cpp index e3530ab2e..ec77cb1c5 100644 --- a/core/rend/dx9/d3d_renderer.cpp +++ b/core/rend/dx9/d3d_renderer.cpp @@ -139,7 +139,7 @@ bool D3DRenderer::Init() success &= (bool)shaders.getVertexShader(true); success &= SUCCEEDED(device->CreateTexture(32, 32, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &paletteTexture.get(), 0)); success &= SUCCEEDED(device->CreateTexture(128, 2, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8, D3DPOOL_DEFAULT, &fogTexture.get(), 0)); - fog_needs_update = true; + updateFogTable = true; if (!success) { @@ -199,8 +199,8 @@ void D3DRenderer::postReset() verify(rc); rc = SUCCEEDED(device->CreateTexture(128, 2, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8, D3DPOOL_DEFAULT, &fogTexture.get(), 0)); verify(rc); - fog_needs_update = true; - palette_updated = true; + updateFogTable = true; + updatePalette = true; } void D3DRenderer::Term() @@ -315,8 +315,10 @@ void D3DRenderer::Process(TA_context* ctx) if (settings.platform.isNaomi2()) throw FlycastException("DirectX 9 doesn't support Naomi 2 games. Select a different graphics API"); - if (KillTex) + if (resetTextureCache) { texCache.Clear(); + resetTextureCache = false; + } texCache.Cleanup(); ta_parse(ctx, false); @@ -1279,7 +1281,7 @@ void D3DRenderer::displayFramebuffer() bool D3DRenderer::RenderLastFrame() { - if (!frameRenderedOnce || !theDXContext.isReady()) + if (clearLastFrame || !frameRenderedOnce || !theDXContext.isReady()) return false; backbuffer.reset(); bool rc = SUCCEEDED(device->GetRenderTarget(0, &backbuffer.get())); @@ -1292,9 +1294,9 @@ bool D3DRenderer::RenderLastFrame() void D3DRenderer::updatePaletteTexture() { - if (!palette_updated) + if (!updatePalette) return; - palette_updated = false; + updatePalette = false; D3DLOCKED_RECT rect; bool rc = SUCCEEDED(paletteTexture->LockRect(0, &rect, nullptr, 0)); @@ -1316,9 +1318,9 @@ void D3DRenderer::updatePaletteTexture() void D3DRenderer::updateFogTexture() { - if (!fog_needs_update || !config::Fog) + if (!updateFogTable || !config::Fog) return; - fog_needs_update = false; + updateFogTable = false; u8 temp_tex_buffer[256]; MakeFogTexture(temp_tex_buffer); diff --git a/core/rend/dx9/d3d_renderer.h b/core/rend/dx9/d3d_renderer.h index a7e5d71b2..e6392131b 100644 --- a/core/rend/dx9/d3d_renderer.h +++ b/core/rend/dx9/d3d_renderer.h @@ -110,6 +110,7 @@ struct D3DRenderer : public Renderer return false; imguiDriver->setFrameRendered(); frameRendered = false; + clearLastFrame = false; return true; } BaseTextureCacheData *GetTexture(TSP tsp, TCW tcw) override; diff --git a/core/rend/gl4/gles.cpp b/core/rend/gl4/gles.cpp index e28e3e6a0..5cd12b6aa 100644 --- a/core/rend/gl4/gles.cpp +++ b/core/rend/gl4/gles.cpp @@ -763,7 +763,7 @@ bool OpenGL4Renderer::Init() u32 dst[16]; UpscalexBRZ(2, src, dst, 2, 2, false); } - fog_needs_update = true; + updateFogTable = true; TextureCacheData::SetDirectXColorOrder(false); TextureCacheData::setUploadToGPUFlavor(); diff --git a/core/rend/gles/gles.cpp b/core/rend/gles/gles.cpp index eabcdcca1..ad14b9009 100644 --- a/core/rend/gles/gles.cpp +++ b/core/rend/gles/gles.cpp @@ -982,7 +982,7 @@ bool OpenGLRenderer::Init() u32 dst[16]; UpscalexBRZ(2, src, dst, 2, 2, false); } - fog_needs_update = true; + updateFogTable = true; TextureCacheData::SetDirectXColorOrder(false); TextureCacheData::setUploadToGPUFlavor(); @@ -1049,19 +1049,19 @@ void OpenGLRenderer::Process(TA_context* ctx) if (gl.gl_major < 3 && settings.platform.isNaomi2()) throw FlycastException("OpenGL ES 3.0+ required for Naomi 2"); - if (KillTex) + if (resetTextureCache) { TexCache.Clear(); + resetTextureCache = false; + } TexCache.Cleanup(); - if (fog_needs_update && config::Fog) - { - fog_needs_update = false; + if (updateFogTable && config::Fog) { + updateFogTable = false; updateFogTexture((u8 *)FOG_TABLE, getFogTextureSlot(), gl.single_channel_format); } - if (palette_updated) - { + if (updatePalette) { updatePaletteTexture(getPaletteTextureSlot()); - palette_updated = false; + updatePalette = false; } ta_parse(ctx, gl.prim_restart_fixed_supported || gl.prim_restart_supported); } diff --git a/core/rend/gles/gles.h b/core/rend/gles/gles.h index 3a887feea..d5bb74252 100755 --- a/core/rend/gles/gles.h +++ b/core/rend/gles/gles.h @@ -502,6 +502,8 @@ struct OpenGLRenderer : Renderer bool RenderLastFrame() override { + if (clearLastFrame) + return false; saveCurrentFramebuffer(); bool ret = renderLastFrame(); restoreCurrentFramebuffer(); @@ -519,6 +521,7 @@ struct OpenGLRenderer : Renderer #ifndef LIBRETRO imguiDriver->setFrameRendered(); #endif + clearLastFrame = false; frameRendered = false; return true; } diff --git a/core/rend/vulkan/oit/oit_renderer.cpp b/core/rend/vulkan/oit/oit_renderer.cpp index e5e0bc7e0..8422f47d4 100644 --- a/core/rend/vulkan/oit/oit_renderer.cpp +++ b/core/rend/vulkan/oit/oit_renderer.cpp @@ -105,6 +105,7 @@ class OITVulkanRenderer final : public BaseVulkanRenderer bool Present() override { + clearLastFrame = false; if (config::EmulateFramebuffer || framebufferRendered) return presentFramebuffer(); else diff --git a/core/rend/vulkan/vulkan_driver.h b/core/rend/vulkan/vulkan_driver.h index e48359289..3c00d0aa9 100644 --- a/core/rend/vulkan/vulkan_driver.h +++ b/core/rend/vulkan/vulkan_driver.h @@ -56,7 +56,8 @@ class VulkanDriver final : public ImGuiDriver if (!rendering || newFrameStarted) { context->BeginRenderPass(); - context->PresentLastFrame(); + if (renderer->RenderLastFrame()) + context->PresentLastFrame(); } if (!justStarted) { diff --git a/core/rend/vulkan/vulkan_renderer.cpp b/core/rend/vulkan/vulkan_renderer.cpp index 5935f9d44..108073901 100644 --- a/core/rend/vulkan/vulkan_renderer.cpp +++ b/core/rend/vulkan/vulkan_renderer.cpp @@ -87,8 +87,10 @@ BaseTextureCacheData *BaseVulkanRenderer::GetTexture(TSP tsp, TCW tcw) void BaseVulkanRenderer::Process(TA_context* ctx) { framebufferRendered = false; - if (KillTex) + if (resetTextureCache) { textureCache.Clear(); + resetTextureCache = false; + } texCommandPool.BeginFrame(); textureCache.SetCurrentIndex(texCommandPool.GetIndex()); @@ -184,11 +186,11 @@ void BaseVulkanRenderer::CheckFogTexture() { fogTexture = std::make_unique(); fogTexture->tex_type = TextureType::_8; - fog_needs_update = true; + updateFogTable = true; } - if (!fog_needs_update || !config::Fog) + if (!updateFogTable || !config::Fog) return; - fog_needs_update = false; + updateFogTable = false; u8 texData[256]; MakeFogTexture(texData); @@ -199,15 +201,14 @@ void BaseVulkanRenderer::CheckFogTexture() void BaseVulkanRenderer::CheckPaletteTexture() { - if (!paletteTexture) - { + if (!paletteTexture) { paletteTexture = std::make_unique(); paletteTexture->tex_type = TextureType::_8888; - palette_updated = true; } - if (!palette_updated) + else if (!updatePalette) { return; - palette_updated = false; + } + updatePalette = false; paletteTexture->SetCommandBuffer(texCommandBuffer); paletteTexture->UploadToGPU(1024, 1, (u8 *)palette32_ram, false); @@ -299,6 +300,7 @@ class VulkanRenderer final : public BaseVulkanRenderer bool Present() override { + clearLastFrame = false; if (config::EmulateFramebuffer || framebufferRendered) return presentFramebuffer(); else diff --git a/core/rend/vulkan/vulkan_renderer.h b/core/rend/vulkan/vulkan_renderer.h index 0780d5799..f24ff3c00 100644 --- a/core/rend/vulkan/vulkan_renderer.h +++ b/core/rend/vulkan/vulkan_renderer.h @@ -41,6 +41,9 @@ class BaseVulkanRenderer : public Renderer void RenderFramebuffer(const FramebufferInfo& info) override; void RenderVideoRouting(); + bool RenderLastFrame() override { + return !clearLastFrame; + } bool GetLastFrame(std::vector& data, int& width, int& height) override { return GetContext()->GetLastFrame(data, width, height); }