rend: get rid of globals for fog/palette updates & tex cache flush

Add state vars to Renderer
Use events to detect loading a state and terminating the game.
Don't present last rendered frame after game terminated.
This commit is contained in:
Flyinghead 2024-12-14 17:00:51 +01:00
parent 825778445a
commit d789b57412
18 changed files with 93 additions and 50 deletions

View File

@ -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)

View File

@ -1,6 +1,7 @@
#pragma once
#include "types.h"
#include "ta_ctx.h"
#include "emulator.h"
#include <vector>
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<Renderer*>(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;
}

View File

@ -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);

View File

@ -6,7 +6,6 @@
#include <map>
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;

View File

@ -281,7 +281,6 @@ void dc_loadstate(int index)
}
free(data);
EventManager::event(Event::LoadState);
}
time_t dc_getStateCreationDate(int index)

View File

@ -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))
{

View File

@ -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 @@ public:
texture.Delete();
cache.clear();
KillTex = false;
INFO_LOG(RENDERER, "Texture cache cleared");
}

View File

@ -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);

View File

@ -45,6 +45,7 @@ struct DX11Renderer : public Renderer
if (!frameRendered)
return false;
frameRendered = false;
clearLastFrame = false;
#ifndef LIBRETRO
imguiDriver->setFrameRendered();
#else

View File

@ -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);

View File

@ -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;

View File

@ -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();

View File

@ -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);
}

View File

@ -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;
}

View File

@ -105,6 +105,7 @@ public:
bool Present() override
{
clearLastFrame = false;
if (config::EmulateFramebuffer || framebufferRendered)
return presentFramebuffer();
else

View File

@ -56,7 +56,8 @@ public:
if (!rendering || newFrameStarted)
{
context->BeginRenderPass();
context->PresentLastFrame();
if (renderer->RenderLastFrame())
context->PresentLastFrame();
}
if (!justStarted)
{

View File

@ -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<Texture>();
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<Texture>();
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 @@ public:
bool Present() override
{
clearLastFrame = false;
if (config::EmulateFramebuffer || framebufferRendered)
return presentFramebuffer();
else

View File

@ -41,6 +41,9 @@ public:
void RenderFramebuffer(const FramebufferInfo& info) override;
void RenderVideoRouting();
bool RenderLastFrame() override {
return !clearLastFrame;
}
bool GetLastFrame(std::vector<u8>& data, int& width, int& height) override {
return GetContext()->GetLastFrame(data, width, height);
}