mirror of https://github.com/PCSX2/pcsx2.git
GS: Make renderer a global
This commit is contained in:
parent
568ebc6199
commit
6e84613a14
115
pcsx2/GS/GS.cpp
115
pcsx2/GS/GS.cpp
|
@ -73,7 +73,6 @@ static HRESULT s_hr = E_FAIL;
|
|||
|
||||
Pcsx2Config::GSOptions GSConfig;
|
||||
|
||||
static std::unique_ptr<GSRenderer> s_gs;
|
||||
static HostDisplay::RenderAPI s_render_api;
|
||||
|
||||
int GSinit()
|
||||
|
@ -118,10 +117,10 @@ void GSinitConfig()
|
|||
|
||||
void GSshutdown()
|
||||
{
|
||||
if (s_gs)
|
||||
if (g_gs_renderer)
|
||||
{
|
||||
s_gs->Destroy();
|
||||
s_gs.reset();
|
||||
g_gs_renderer->Destroy();
|
||||
g_gs_renderer.reset();
|
||||
}
|
||||
if (g_gs_device)
|
||||
{
|
||||
|
@ -143,10 +142,10 @@ void GSshutdown()
|
|||
|
||||
void GSclose()
|
||||
{
|
||||
if (s_gs)
|
||||
if (g_gs_renderer)
|
||||
{
|
||||
s_gs->Destroy();
|
||||
s_gs.reset();
|
||||
g_gs_renderer->Destroy();
|
||||
g_gs_renderer.reset();
|
||||
}
|
||||
if (g_gs_device)
|
||||
{
|
||||
|
@ -257,28 +256,28 @@ static bool DoGSOpen(GSRendererType renderer, u8* basemem)
|
|||
|
||||
if (renderer == GSRendererType::Null)
|
||||
{
|
||||
s_gs = std::make_unique<GSRendererNull>();
|
||||
g_gs_renderer = std::make_unique<GSRendererNull>();
|
||||
}
|
||||
else if (renderer != GSRendererType::SW)
|
||||
{
|
||||
s_gs = std::make_unique<GSRendererNew>();
|
||||
g_gs_renderer = std::make_unique<GSRendererNew>();
|
||||
}
|
||||
else
|
||||
{
|
||||
const int threads = theApp.GetConfigI("extrathreads");
|
||||
s_gs = std::make_unique<GSRendererSW>(threads);
|
||||
g_gs_renderer = std::make_unique<GSRendererSW>(threads);
|
||||
}
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
Host::ReportFormattedErrorAsync("GS", "GS error: Exception caught in GSopen: %s", ex.what());
|
||||
s_gs.reset();
|
||||
g_gs_renderer.reset();
|
||||
g_gs_device->Destroy();
|
||||
g_gs_device.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
s_gs->SetRegsMem(basemem);
|
||||
g_gs_renderer->SetRegsMem(basemem);
|
||||
|
||||
display->SetVSync(EmuConfig.GetEffectiveVsyncMode());
|
||||
display->SetGPUTimingEnabled(GSConfig.OsdShowGPU);
|
||||
|
@ -289,10 +288,10 @@ bool GSreopen(bool recreate_display)
|
|||
{
|
||||
Console.WriteLn("Reopening GS with %s display", recreate_display ? "new" : "existing");
|
||||
|
||||
s_gs->Flush();
|
||||
g_gs_renderer->Flush();
|
||||
|
||||
freezeData fd = {};
|
||||
if (s_gs->Freeze(&fd, true) != 0)
|
||||
if (g_gs_renderer->Freeze(&fd, true) != 0)
|
||||
{
|
||||
Console.Error("(GSreopen) Failed to get GS freeze size");
|
||||
return false;
|
||||
|
@ -300,7 +299,7 @@ bool GSreopen(bool recreate_display)
|
|||
|
||||
std::unique_ptr<u8[]> fd_data = std::make_unique<u8[]>(fd.size);
|
||||
fd.data = fd_data.get();
|
||||
if (s_gs->Freeze(&fd, false) != 0)
|
||||
if (g_gs_renderer->Freeze(&fd, false) != 0)
|
||||
{
|
||||
Console.Error("(GSreopen) Failed to freeze GS");
|
||||
return false;
|
||||
|
@ -313,11 +312,11 @@ bool GSreopen(bool recreate_display)
|
|||
Host::EndPresentFrame();
|
||||
}
|
||||
|
||||
u8* basemem = s_gs->GetRegsMem();
|
||||
const u32 gamecrc = s_gs->GetGameCRC();
|
||||
const int gamecrc_options = s_gs->GetGameCRCOptions();
|
||||
s_gs->Destroy();
|
||||
s_gs.reset();
|
||||
u8* basemem = g_gs_renderer->GetRegsMem();
|
||||
const u32 gamecrc = g_gs_renderer->GetGameCRC();
|
||||
const int gamecrc_options = g_gs_renderer->GetGameCRCOptions();
|
||||
g_gs_renderer->Destroy();
|
||||
g_gs_renderer.reset();
|
||||
g_gs_device->Destroy();
|
||||
g_gs_device.reset();
|
||||
|
||||
|
@ -337,13 +336,13 @@ bool GSreopen(bool recreate_display)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (s_gs->Defrost(&fd) != 0)
|
||||
if (g_gs_renderer->Defrost(&fd) != 0)
|
||||
{
|
||||
pxFailRel("(GSreopen) Failed to defrost");
|
||||
return false;
|
||||
}
|
||||
|
||||
s_gs->SetGameCRC(gamecrc, gamecrc_options);
|
||||
g_gs_renderer->SetGameCRC(gamecrc, gamecrc_options);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -374,7 +373,7 @@ void GSreset()
|
|||
{
|
||||
try
|
||||
{
|
||||
s_gs->Reset();
|
||||
g_gs_renderer->Reset();
|
||||
}
|
||||
catch (GSRecoverableError)
|
||||
{
|
||||
|
@ -385,7 +384,7 @@ void GSgifSoftReset(u32 mask)
|
|||
{
|
||||
try
|
||||
{
|
||||
s_gs->SoftReset(mask);
|
||||
g_gs_renderer->SoftReset(mask);
|
||||
}
|
||||
catch (GSRecoverableError)
|
||||
{
|
||||
|
@ -396,7 +395,7 @@ void GSwriteCSR(u32 csr)
|
|||
{
|
||||
try
|
||||
{
|
||||
s_gs->WriteCSR(csr);
|
||||
g_gs_renderer->WriteCSR(csr);
|
||||
}
|
||||
catch (GSRecoverableError)
|
||||
{
|
||||
|
@ -408,8 +407,8 @@ void GSInitAndReadFIFO(u8* mem, u32 size)
|
|||
GL_PERF("Init and read FIFO %u qwc", size);
|
||||
try
|
||||
{
|
||||
s_gs->InitReadFIFO(mem, size);
|
||||
s_gs->ReadFIFO(mem, size);
|
||||
g_gs_renderer->InitReadFIFO(mem, size);
|
||||
g_gs_renderer->ReadFIFO(mem, size);
|
||||
}
|
||||
catch (GSRecoverableError)
|
||||
{
|
||||
|
@ -424,7 +423,7 @@ void GSgifTransfer(const u8* mem, u32 size)
|
|||
{
|
||||
try
|
||||
{
|
||||
s_gs->Transfer<3>(mem, size);
|
||||
g_gs_renderer->Transfer<3>(mem, size);
|
||||
}
|
||||
catch (GSRecoverableError)
|
||||
{
|
||||
|
@ -435,7 +434,7 @@ void GSgifTransfer1(u8* mem, u32 addr)
|
|||
{
|
||||
try
|
||||
{
|
||||
s_gs->Transfer<0>(const_cast<u8*>(mem) + addr, (0x4000 - addr) / 16);
|
||||
g_gs_renderer->Transfer<0>(const_cast<u8*>(mem) + addr, (0x4000 - addr) / 16);
|
||||
}
|
||||
catch (GSRecoverableError)
|
||||
{
|
||||
|
@ -446,7 +445,7 @@ void GSgifTransfer2(u8* mem, u32 size)
|
|||
{
|
||||
try
|
||||
{
|
||||
s_gs->Transfer<1>(const_cast<u8*>(mem), size);
|
||||
g_gs_renderer->Transfer<1>(const_cast<u8*>(mem), size);
|
||||
}
|
||||
catch (GSRecoverableError)
|
||||
{
|
||||
|
@ -457,7 +456,7 @@ void GSgifTransfer3(u8* mem, u32 size)
|
|||
{
|
||||
try
|
||||
{
|
||||
s_gs->Transfer<2>(const_cast<u8*>(mem), size);
|
||||
g_gs_renderer->Transfer<2>(const_cast<u8*>(mem), size);
|
||||
}
|
||||
catch (GSRecoverableError)
|
||||
{
|
||||
|
@ -468,7 +467,7 @@ void GSvsync(u32 field, bool registers_written)
|
|||
{
|
||||
try
|
||||
{
|
||||
s_gs->VSync(field, registers_written);
|
||||
g_gs_renderer->VSync(field, registers_written);
|
||||
}
|
||||
catch (GSRecoverableError)
|
||||
{
|
||||
|
@ -495,12 +494,12 @@ u32 GSmakeSnapshot(char* path)
|
|||
std::transform(extension.begin(), extension.end(), extension.begin(), tolower);
|
||||
#endif
|
||||
if (extension == ".png")
|
||||
return s_gs->MakeSnapshot(s);
|
||||
return g_gs_renderer->MakeSnapshot(s);
|
||||
else if (s[s.length() - 1] != DIRECTORY_SEPARATOR)
|
||||
s = s + DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
return s_gs->MakeSnapshot(s + "gs");
|
||||
return g_gs_renderer->MakeSnapshot(s + "gs");
|
||||
}
|
||||
catch (GSRecoverableError)
|
||||
{
|
||||
|
@ -514,15 +513,15 @@ int GSfreeze(FreezeAction mode, freezeData* data)
|
|||
{
|
||||
if (mode == FreezeAction::Save)
|
||||
{
|
||||
return s_gs->Freeze(data, false);
|
||||
return g_gs_renderer->Freeze(data, false);
|
||||
}
|
||||
else if (mode == FreezeAction::Size)
|
||||
{
|
||||
return s_gs->Freeze(data, true);
|
||||
return g_gs_renderer->Freeze(data, true);
|
||||
}
|
||||
else if (mode == FreezeAction::Load)
|
||||
{
|
||||
return s_gs->Defrost(data);
|
||||
return g_gs_renderer->Defrost(data);
|
||||
}
|
||||
}
|
||||
catch (GSRecoverableError)
|
||||
|
@ -538,8 +537,8 @@ void GSkeyEvent(const HostKeyEvent& e)
|
|||
{
|
||||
try
|
||||
{
|
||||
if (s_gs)
|
||||
s_gs->KeyEvent(e);
|
||||
if (g_gs_renderer)
|
||||
g_gs_renderer->KeyEvent(e);
|
||||
}
|
||||
catch (GSRecoverableError)
|
||||
{
|
||||
|
@ -591,7 +590,7 @@ void pt(const char* str)
|
|||
|
||||
bool GSsetupRecording(std::string& filename)
|
||||
{
|
||||
if (s_gs == NULL)
|
||||
if (g_gs_renderer == NULL)
|
||||
{
|
||||
printf("GS: no s_gs for recording\n");
|
||||
return false;
|
||||
|
@ -604,7 +603,7 @@ bool GSsetupRecording(std::string& filename)
|
|||
}
|
||||
#endif
|
||||
printf("GS: Recording start command\n");
|
||||
if (s_gs->BeginCapture(filename))
|
||||
if (g_gs_renderer->BeginCapture(filename))
|
||||
{
|
||||
pt(" - Capture started\n");
|
||||
return true;
|
||||
|
@ -619,30 +618,30 @@ bool GSsetupRecording(std::string& filename)
|
|||
void GSendRecording()
|
||||
{
|
||||
printf("GS: Recording end command\n");
|
||||
s_gs->EndCapture();
|
||||
g_gs_renderer->EndCapture();
|
||||
pt(" - Capture ended\n");
|
||||
}
|
||||
|
||||
void GSsetGameCRC(u32 crc, int options)
|
||||
{
|
||||
s_gs->SetGameCRC(crc, options);
|
||||
g_gs_renderer->SetGameCRC(crc, options);
|
||||
}
|
||||
|
||||
void GSsetFrameSkip(int frameskip)
|
||||
{
|
||||
s_gs->SetFrameSkip(frameskip);
|
||||
g_gs_renderer->SetFrameSkip(frameskip);
|
||||
}
|
||||
|
||||
GSVideoMode GSgetDisplayMode()
|
||||
{
|
||||
GSRenderer* gs = s_gs.get();
|
||||
GSRenderer* gs = g_gs_renderer.get();
|
||||
|
||||
return gs->GetVideoMode();
|
||||
}
|
||||
|
||||
void GSgetInternalResolution(int* width, int* height)
|
||||
{
|
||||
GSRenderer* gs = s_gs.get();
|
||||
GSRenderer* gs = g_gs_renderer.get();
|
||||
if (!gs)
|
||||
{
|
||||
*width = 0;
|
||||
|
@ -684,7 +683,7 @@ void GSgetStats(std::string& info)
|
|||
{
|
||||
info = format("%s HW | HC: %d MB | %d P | %d D | %d DC | %d B | %d RB | %d TC | %d TU",
|
||||
api_name,
|
||||
(int)std::ceil(static_cast<GSRendererHW*>(s_gs.get())->GetTextureCache()->GetHashCacheMemoryUsage() / 1048576.0f),
|
||||
(int)std::ceil(GSRendererHW::GetInstance()->GetTextureCache()->GetHashCacheMemoryUsage() / 1048576.0f),
|
||||
(int)pm.Get(GSPerfMon::Prim),
|
||||
(int)pm.Get(GSPerfMon::Draw),
|
||||
(int)std::ceil(pm.Get(GSPerfMon::DrawCalls)),
|
||||
|
@ -731,7 +730,7 @@ void GSUpdateConfig(const Pcsx2Config::GSOptions& new_config)
|
|||
Pcsx2Config::GSOptions old_config(std::move(GSConfig));
|
||||
GSConfig = new_config;
|
||||
GSConfig.Renderer = (GSConfig.Renderer == GSRendererType::Auto) ? GSUtil::GetPreferredRenderer() : GSConfig.Renderer;
|
||||
if (!s_gs)
|
||||
if (!g_gs_renderer)
|
||||
return;
|
||||
|
||||
HostDisplay* display = Host::GetHostDisplay();
|
||||
|
@ -793,11 +792,11 @@ void GSUpdateConfig(const Pcsx2Config::GSOptions& new_config)
|
|||
GSConfig.PointListPalette != old_config.PointListPalette)
|
||||
{
|
||||
// for automatic mipmaps, we need to reload the crc
|
||||
s_gs->SetGameCRC(s_gs->GetGameCRC(), s_gs->GetGameCRCOptions());
|
||||
g_gs_renderer->SetGameCRC(g_gs_renderer->GetGameCRC(), g_gs_renderer->GetGameCRCOptions());
|
||||
}
|
||||
|
||||
// renderer-specific options (e.g. auto flush, TC offset)
|
||||
s_gs->UpdateSettings(old_config);
|
||||
g_gs_renderer->UpdateSettings(old_config);
|
||||
|
||||
// reload texture cache when trilinear filtering or TC options change
|
||||
if (
|
||||
|
@ -813,8 +812,8 @@ void GSUpdateConfig(const Pcsx2Config::GSOptions& new_config)
|
|||
GSConfig.UserHacks_DisablePartialInvalidation != old_config.UserHacks_DisablePartialInvalidation ||
|
||||
GSConfig.UserHacks_TextureInsideRt != old_config.UserHacks_TextureInsideRt)
|
||||
{
|
||||
s_gs->PurgeTextureCache();
|
||||
s_gs->PurgePool();
|
||||
g_gs_renderer->PurgeTextureCache();
|
||||
g_gs_renderer->PurgePool();
|
||||
}
|
||||
|
||||
// clear out the sampler cache when AF options change, since the anisotropy gets baked into them
|
||||
|
@ -829,7 +828,7 @@ void GSUpdateConfig(const Pcsx2Config::GSOptions& new_config)
|
|||
if (GSConfig.LoadTextureReplacements != old_config.LoadTextureReplacements ||
|
||||
GSConfig.DumpReplaceableTextures != old_config.DumpReplaceableTextures)
|
||||
{
|
||||
s_gs->PurgeTextureCache();
|
||||
g_gs_renderer->PurgeTextureCache();
|
||||
}
|
||||
|
||||
if (GSConfig.OsdShowGPU != old_config.OsdShowGPU)
|
||||
|
@ -844,7 +843,7 @@ void GSSwitchRenderer(GSRendererType new_renderer)
|
|||
if (new_renderer == GSRendererType::Auto)
|
||||
new_renderer = GSUtil::GetPreferredRenderer();
|
||||
|
||||
if (!s_gs || GSConfig.Renderer == new_renderer)
|
||||
if (!g_gs_renderer || GSConfig.Renderer == new_renderer)
|
||||
return;
|
||||
|
||||
HostDisplay::RenderAPI existing_api = Host::GetHostDisplay()->GetRenderAPI();
|
||||
|
@ -874,10 +873,10 @@ void GSRestoreAPIState()
|
|||
|
||||
bool GSSaveSnapshotToMemory(u32 width, u32 height, std::vector<u32>* pixels)
|
||||
{
|
||||
if (!s_gs)
|
||||
if (!g_gs_renderer)
|
||||
return false;
|
||||
|
||||
return s_gs->SaveSnapshotToMemory(width, height, pixels);
|
||||
return g_gs_renderer->SaveSnapshotToMemory(width, height, pixels);
|
||||
}
|
||||
|
||||
std::string format(const char* fmt, ...)
|
||||
|
@ -1613,8 +1612,8 @@ BEGIN_HOTKEY_LIST(g_gs_hotkeys){
|
|||
|
||||
GetMTGS().RunOnGSThread([new_level]() {
|
||||
GSConfig.HWMipmap = new_level;
|
||||
s_gs->PurgeTextureCache();
|
||||
s_gs->PurgePool();
|
||||
g_gs_renderer->PurgeTextureCache();
|
||||
g_gs_renderer->PurgePool();
|
||||
});
|
||||
}},
|
||||
{"CycleInterlaceMode", "Graphics", "Cycle Deinterlace Mode", [](bool pressed) {
|
||||
|
|
|
@ -52,6 +52,8 @@ static std::string GetDumpSerial()
|
|||
}
|
||||
#endif
|
||||
|
||||
std::unique_ptr<GSRenderer> g_gs_renderer;
|
||||
|
||||
GSRenderer::GSRenderer()
|
||||
: m_shift_key(false)
|
||||
, m_control_key(false)
|
||||
|
|
|
@ -60,3 +60,5 @@ public:
|
|||
|
||||
bool SaveSnapshotToMemory(u32 width, u32 height, std::vector<u32>* pixels);
|
||||
};
|
||||
|
||||
extern std::unique_ptr<GSRenderer> g_gs_renderer;
|
|
@ -23,7 +23,7 @@ GSRendererHW::GSRendererHW()
|
|||
: GSRenderer()
|
||||
, m_width(default_rt_size.x)
|
||||
, m_height(default_rt_size.y)
|
||||
, m_tc(new GSTextureCache(this))
|
||||
, m_tc(new GSTextureCache())
|
||||
, m_src(nullptr)
|
||||
, m_userhacks_tcoffset(false)
|
||||
, m_userhacks_tcoffset_x(0)
|
||||
|
|
|
@ -154,6 +154,7 @@ public:
|
|||
GSRendererHW();
|
||||
virtual ~GSRendererHW() override;
|
||||
|
||||
__fi static GSRendererHW* GetInstance() { return static_cast<GSRendererHW*>(g_gs_renderer.get()); }
|
||||
__fi GSTextureCache* GetTextureCache() const { return m_tc; }
|
||||
|
||||
void Destroy() override;
|
||||
|
|
|
@ -29,9 +29,7 @@
|
|||
|
||||
u8* GSTextureCache::m_temp;
|
||||
|
||||
GSTextureCache::GSTextureCache(GSRenderer* r)
|
||||
: m_renderer(r)
|
||||
, m_palette_map(r)
|
||||
GSTextureCache::GSTextureCache()
|
||||
{
|
||||
// In theory 4MB is enough but 9MB is safer for overflow (8MB
|
||||
// isn't enough in custom resolution)
|
||||
|
@ -143,7 +141,7 @@ GSTextureCache::Source* GSTextureCache::LookupDepthSource(const GIFRegTEX0& TEX0
|
|||
TEX0.TBP0, psm_str(psm));
|
||||
|
||||
// Create a shared texture source
|
||||
src = new Source(m_renderer, TEX0, TEXA, true);
|
||||
src = new Source(TEX0, TEXA, true);
|
||||
src->m_texture = dst->m_texture;
|
||||
src->m_shared_texture = true;
|
||||
src->m_target = true; // So renderer can check if a conversion is required
|
||||
|
@ -164,7 +162,7 @@ GSTextureCache::Source* GSTextureCache::LookupDepthSource(const GIFRegTEX0& TEX0
|
|||
|
||||
m_src.m_surfaces.insert(src);
|
||||
}
|
||||
else if (m_renderer->m_game.title == CRC::SVCChaos)
|
||||
else if (g_gs_renderer->m_game.title == CRC::SVCChaos)
|
||||
{
|
||||
// SVCChaos black screen on main menu, regardless of depth enabled or disabled.
|
||||
return LookupSource(TEX0, TEXA, r, nullptr);
|
||||
|
@ -199,9 +197,9 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
|
|||
|
||||
// Until DX is fixed
|
||||
if (psm_s.pal > 0)
|
||||
m_renderer->m_mem.m_clut.Read32(TEX0, TEXA);
|
||||
g_gs_renderer->m_mem.m_clut.Read32(TEX0, TEXA);
|
||||
|
||||
const u32* clut = m_renderer->m_mem.m_clut;
|
||||
const u32* clut = g_gs_renderer->m_mem.m_clut;
|
||||
|
||||
Source* src = NULL;
|
||||
|
||||
|
@ -417,7 +415,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
|
|||
GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, const GSVector2i& size, int type, bool used, u32 fbmask, const bool is_frame, const int real_h)
|
||||
{
|
||||
const GSLocalMemory::psm_t& psm_s = GSLocalMemory::m_psm[TEX0.PSM];
|
||||
const GSVector2& new_s = m_renderer->GetTextureScaleFactor();
|
||||
const GSVector2& new_s = g_gs_renderer->GetTextureScaleFactor();
|
||||
const u32 bp = TEX0.TBP0;
|
||||
GSVector2 res_size{ 0, 0 };
|
||||
GSVector2i new_size{ 0, 0 };
|
||||
|
@ -685,7 +683,7 @@ void GSTextureCache::InvalidateVideoMem(const GSOffset& off, const GSVector4i& r
|
|||
// Haunting ground write frame buffer 0x3000 and expect to write data to 0x3380
|
||||
// Note: the game only does a 0 direct write. If some games expect some real data
|
||||
// we are screwed.
|
||||
if (m_renderer->m_game.title == CRC::HauntingGround)
|
||||
if (g_gs_renderer->m_game.title == CRC::HauntingGround)
|
||||
{
|
||||
u32 end_block = GSLocalMemory::m_psm[psm].info.bn(rect.z - 1, rect.w - 1, bp, bw); // Valid only for color formats
|
||||
auto type = RenderTarget;
|
||||
|
@ -1168,7 +1166,7 @@ void GSTextureCache::IncAge()
|
|||
GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* dst, bool half_right, int x_offset, int y_offset, const GSVector2i* lod, const GSVector4i* src_range)
|
||||
{
|
||||
const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[TEX0.PSM];
|
||||
Source* src = new Source(m_renderer, TEX0, TEXA, false);
|
||||
Source* src = new Source(TEX0, TEXA, false);
|
||||
|
||||
int tw = 1 << TEX0.TW;
|
||||
int th = 1 << TEX0.TH;
|
||||
|
@ -1204,7 +1202,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
|
|||
AttachPaletteToSource(src, psm.pal, true);
|
||||
}
|
||||
}
|
||||
else if (dst && static_cast<GSRendererHW*>(m_renderer)->IsDummyTexture())
|
||||
else if (dst && GSRendererHW::GetInstance()->IsDummyTexture())
|
||||
{
|
||||
// This shortcut is a temporary solution. It isn't a good solution
|
||||
// as it won't work with Channel Shuffle/Texture Shuffle pattern
|
||||
|
@ -1366,12 +1364,12 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
|
|||
else if (src_range && dst->m_TEX0.TBW == TEX0.TBW && !is_8bits)
|
||||
{
|
||||
// optimization for TBP == FRAME
|
||||
const GSDrawingContext* const context = m_renderer->m_context;
|
||||
const GSDrawingContext* const context = g_gs_renderer->m_context;
|
||||
if (context->FRAME.Block() == TEX0.TBP0 || context->ZBUF.Block() == TEX0.TBP0)
|
||||
{
|
||||
// if it looks like a texture shuffle, we might read up to +/- 8 pixels on either side.
|
||||
GSVector4 adjusted_src_range(*src_range);
|
||||
if (static_cast<GSRendererHW*>(m_renderer)->IsPossibleTextureShuffle(src))
|
||||
if (GSRendererHW::GetInstance()->IsPossibleTextureShuffle(src))
|
||||
adjusted_src_range += GSVector4(-8.0f, 0.0f, 8.0f, 0.0f);
|
||||
|
||||
// don't forget to scale the copy range
|
||||
|
@ -1427,7 +1425,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
|
|||
|
||||
if (GSConfig.UserHacks_HalfPixelOffset == 1 && hack)
|
||||
{
|
||||
switch(m_renderer->GetUpscaleMultiplier())
|
||||
switch(g_gs_renderer->GetUpscaleMultiplier())
|
||||
{
|
||||
case 2: modx = 2.2f; mody = 2.2f; dst->m_texture->LikelyOffset = true; break;
|
||||
case 3: modx = 3.1f; mody = 3.1f; dst->m_texture->LikelyOffset = true; break;
|
||||
|
@ -1447,7 +1445,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
|
|||
{
|
||||
// maintain the clut even when paltex is on for the dump/replacement texture lookup
|
||||
bool paltex = (GSConfig.GPUPaletteConversion && psm.pal > 0);
|
||||
const u32* clut = (psm.pal > 0) ? static_cast<const u32*>(m_renderer->m_mem.m_clut) : nullptr;
|
||||
const u32* clut = (psm.pal > 0) ? static_cast<const u32*>(g_gs_renderer->m_mem.m_clut) : nullptr;
|
||||
|
||||
// try the hash cache
|
||||
if ((src->m_from_hash_cache = LookupHashCache(TEX0, TEXA, paltex, clut, lod)) != nullptr)
|
||||
|
@ -1473,7 +1471,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
|
|||
|
||||
ASSERT(src->m_texture);
|
||||
|
||||
m_src.Add(src, TEX0, m_renderer->m_context->offset.tex);
|
||||
m_src.Add(src, TEX0, g_gs_renderer->m_context->offset.tex);
|
||||
|
||||
return src;
|
||||
}
|
||||
|
@ -1492,13 +1490,13 @@ GSTextureCache::HashCacheEntry* GSTextureCache::LookupHashCache(const GIFRegTEX0
|
|||
|
||||
// need the hash either for replacing, dumping or caching.
|
||||
// if dumping/replacing is on, we compute the clut hash regardless, since replacements aren't indexed
|
||||
HashCacheKey key{HashCacheKey::Create(TEX0, TEXA, m_renderer, (dump || replace || !paltex) ? clut : nullptr, lod)};
|
||||
HashCacheKey key{HashCacheKey::Create(TEX0, TEXA, (dump || replace || !paltex) ? clut : nullptr, lod)};
|
||||
|
||||
// handle dumping first, this is mostly isolated.
|
||||
if (dump)
|
||||
{
|
||||
// dump base level
|
||||
GSTextureReplacements::DumpTexture(key, TEX0, TEXA, m_renderer->m_mem, 0);
|
||||
GSTextureReplacements::DumpTexture(key, TEX0, TEXA, g_gs_renderer->m_mem, 0);
|
||||
|
||||
// and the mips
|
||||
if (lod && GSConfig.DumpReplaceableMipmaps)
|
||||
|
@ -1507,8 +1505,8 @@ GSTextureCache::HashCacheEntry* GSTextureCache::LookupHashCache(const GIFRegTEX0
|
|||
const int nmips = lod->y - lod->x + 1;
|
||||
for (int mip = 1; mip < nmips; mip++)
|
||||
{
|
||||
const GIFRegTEX0 MIP_TEX0{m_renderer->GetTex0Layer(basemip + mip)};
|
||||
GSTextureReplacements::DumpTexture(key, MIP_TEX0, TEXA, m_renderer->m_mem, mip);
|
||||
const GIFRegTEX0 MIP_TEX0{g_gs_renderer->GetTex0Layer(basemip + mip)};
|
||||
GSTextureReplacements::DumpTexture(key, MIP_TEX0, TEXA, g_gs_renderer->m_mem, mip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1567,7 +1565,7 @@ GSTextureCache::HashCacheEntry* GSTextureCache::LookupHashCache(const GIFRegTEX0
|
|||
}
|
||||
|
||||
// upload base level
|
||||
PreloadTexture(TEX0, TEXA, m_renderer->m_mem, paltex, tex, 0);
|
||||
PreloadTexture(TEX0, TEXA, g_gs_renderer->m_mem, paltex, tex, 0);
|
||||
|
||||
// upload mips if present
|
||||
if (lod)
|
||||
|
@ -1576,8 +1574,8 @@ GSTextureCache::HashCacheEntry* GSTextureCache::LookupHashCache(const GIFRegTEX0
|
|||
const int nmips = lod->y - lod->x + 1;
|
||||
for (int mip = 1; mip < nmips; mip++)
|
||||
{
|
||||
const GIFRegTEX0 MIP_TEX0{m_renderer->GetTex0Layer(basemip + mip)};
|
||||
PreloadTexture(MIP_TEX0, TEXA, m_renderer->m_mem, paltex, tex, mip);
|
||||
const GIFRegTEX0 MIP_TEX0{g_gs_renderer->GetTex0Layer(basemip + mip)};
|
||||
PreloadTexture(MIP_TEX0, TEXA, g_gs_renderer->m_mem, paltex, tex, mip);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1595,7 +1593,7 @@ GSTextureCache::Target* GSTextureCache::CreateTarget(const GIFRegTEX0& TEX0, int
|
|||
{
|
||||
ASSERT(type == RenderTarget || type == DepthStencil);
|
||||
|
||||
Target* t = new Target(m_renderer, TEX0, !GSConfig.UserHacks_DisableDepthSupport, type);
|
||||
Target* t = new Target(TEX0, !GSConfig.UserHacks_DisableDepthSupport, type);
|
||||
|
||||
// FIXME: initial data should be unswizzled from local mem in Update() if dirty
|
||||
|
||||
|
@ -1610,7 +1608,7 @@ GSTextureCache::Target* GSTextureCache::CreateTarget(const GIFRegTEX0& TEX0, int
|
|||
t->m_texture = g_gs_device->CreateSparseDepthStencil(w, h, GSTexture::Format::DepthStencil, clear);
|
||||
}
|
||||
|
||||
t->m_texture->SetScale(m_renderer->GetTextureScaleFactor());
|
||||
t->m_texture->SetScale(g_gs_renderer->GetTextureScaleFactor());
|
||||
|
||||
m_dst[type].push_front(t);
|
||||
|
||||
|
@ -1674,23 +1672,23 @@ void GSTextureCache::Read(Target* t, const GSVector4i& r)
|
|||
|
||||
if (res)
|
||||
{
|
||||
const GSOffset off = m_renderer->m_mem.GetOffset(TEX0.TBP0, TEX0.TBW, TEX0.PSM);
|
||||
const GSOffset off = g_gs_renderer->m_mem.GetOffset(TEX0.TBP0, TEX0.TBW, TEX0.PSM);
|
||||
|
||||
switch (TEX0.PSM)
|
||||
{
|
||||
case PSM_PSMCT32:
|
||||
case PSM_PSMZ32:
|
||||
m_renderer->m_mem.WritePixel32(m.bits, m.pitch, off, r);
|
||||
g_gs_renderer->m_mem.WritePixel32(m.bits, m.pitch, off, r);
|
||||
break;
|
||||
case PSM_PSMCT24:
|
||||
case PSM_PSMZ24:
|
||||
m_renderer->m_mem.WritePixel24(m.bits, m.pitch, off, r);
|
||||
g_gs_renderer->m_mem.WritePixel24(m.bits, m.pitch, off, r);
|
||||
break;
|
||||
case PSM_PSMCT16:
|
||||
case PSM_PSMCT16S:
|
||||
case PSM_PSMZ16:
|
||||
case PSM_PSMZ16S:
|
||||
m_renderer->m_mem.WritePixel16(m.bits, m.pitch, off, r);
|
||||
g_gs_renderer->m_mem.WritePixel16(m.bits, m.pitch, off, r);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1708,8 +1706,8 @@ void GSTextureCache::Read(Source* t, const GSVector4i& r)
|
|||
GSTexture::GSMap m;
|
||||
if (g_gs_device->DownloadTexture(t->m_texture, r, m))
|
||||
{
|
||||
GSOffset off = m_renderer->m_mem.GetOffset(TEX0.TBP0, TEX0.TBW, TEX0.PSM);
|
||||
m_renderer->m_mem.WritePixel32(m.bits, m.pitch, off, r);
|
||||
GSOffset off = g_gs_renderer->m_mem.GetOffset(TEX0.TBP0, TEX0.TBW, TEX0.PSM);
|
||||
g_gs_renderer->m_mem.WritePixel32(m.bits, m.pitch, off, r);
|
||||
g_gs_device->DownloadTextureComplete();
|
||||
}
|
||||
}
|
||||
|
@ -1748,9 +1746,8 @@ void GSTextureCache::PrintMemoryUsage()
|
|||
|
||||
// GSTextureCache::Surface
|
||||
|
||||
GSTextureCache::Surface::Surface(GSRenderer* r)
|
||||
: m_renderer(r)
|
||||
, m_texture(NULL)
|
||||
GSTextureCache::Surface::Surface()
|
||||
: m_texture(NULL)
|
||||
, m_from_hash_cache(NULL)
|
||||
, m_age(0)
|
||||
, m_32_bits_fmt(false)
|
||||
|
@ -1790,9 +1787,8 @@ bool GSTextureCache::Surface::Overlaps(u32 bp, u32 bw, u32 psm, const GSVector4i
|
|||
|
||||
// GSTextureCache::Source
|
||||
|
||||
GSTextureCache::Source::Source(GSRenderer* r, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, bool dummy_container)
|
||||
: Surface(r)
|
||||
, m_palette_obj(nullptr)
|
||||
GSTextureCache::Source::Source(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, bool dummy_container)
|
||||
: m_palette_obj(nullptr)
|
||||
, m_palette(nullptr)
|
||||
, m_valid_rect(0, 0)
|
||||
, m_target(false)
|
||||
|
@ -1824,10 +1820,10 @@ GSTextureCache::Source::Source(GSRenderer* r, const GIFRegTEX0& TEX0, const GIFR
|
|||
|
||||
if (m_repeating && !CanPreload())
|
||||
{
|
||||
m_p2t = r->m_mem.GetPage2TileMap(m_TEX0);
|
||||
m_p2t = g_gs_renderer->m_mem.GetPage2TileMap(m_TEX0);
|
||||
}
|
||||
|
||||
m_pages = m_renderer->m_context->offset.tex.pageLooperForRect(GSVector4i(0, 0, 1 << TEX0.TW, 1 << TEX0.TH));
|
||||
m_pages = g_gs_renderer->m_context->offset.tex.pageLooperForRect(GSVector4i(0, 0, 1 << TEX0.TW, 1 << TEX0.TH));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1857,7 +1853,7 @@ void GSTextureCache::Source::Update(const GSVector4i& rect, int level)
|
|||
if (r.eq(GSVector4i(0, 0, tw, th)))
|
||||
m_complete_layers |= (1u << level);
|
||||
|
||||
const GSOffset& off = m_renderer->m_context->offset.tex;
|
||||
const GSOffset& off = g_gs_renderer->m_context->offset.tex;
|
||||
GSOffset::BNHelper bn = off.bnMulti(r.left, r.top);
|
||||
|
||||
u32 blocks = 0;
|
||||
|
@ -1998,9 +1994,9 @@ void GSTextureCache::Source::Flush(u32 count, int layer)
|
|||
|
||||
int pitch = std::max(tw, psm.bs.x) * sizeof(u32);
|
||||
|
||||
GSLocalMemory& mem = m_renderer->m_mem;
|
||||
GSLocalMemory& mem = g_gs_renderer->m_mem;
|
||||
|
||||
const GSOffset& off = m_renderer->m_context->offset.tex;
|
||||
const GSOffset& off = g_gs_renderer->m_context->offset.tex;
|
||||
|
||||
GSLocalMemory::readTexture rtx = psm.rtx;
|
||||
|
||||
|
@ -2053,7 +2049,7 @@ void GSTextureCache::Source::Flush(u32 count, int layer)
|
|||
void GSTextureCache::Source::PreloadLevel(int level)
|
||||
{
|
||||
// m_TEX0 is adjusted for mips (messy, should be changed).
|
||||
const HashType hash = HashTexture(m_renderer, m_TEX0, m_TEXA);
|
||||
const HashType hash = HashTexture(m_TEX0, m_TEXA);
|
||||
|
||||
// Layer is complete again, regardless of whether the hash matches or not (and we reupload).
|
||||
const u8 layer_bit = static_cast<u8>(1) << level;
|
||||
|
@ -2067,7 +2063,7 @@ void GSTextureCache::Source::PreloadLevel(int level)
|
|||
m_layer_hash[level] = hash;
|
||||
|
||||
// And upload the texture.
|
||||
PreloadTexture(m_TEX0, m_TEXA, m_renderer->m_mem, m_palette != nullptr, m_texture, level);
|
||||
PreloadTexture(m_TEX0, m_TEXA, g_gs_renderer->m_mem, m_palette != nullptr, m_texture, level);
|
||||
}
|
||||
|
||||
bool GSTextureCache::Source::ClutMatch(const PaletteKey& palette_key)
|
||||
|
@ -2077,9 +2073,8 @@ bool GSTextureCache::Source::ClutMatch(const PaletteKey& palette_key)
|
|||
|
||||
// GSTextureCache::Target
|
||||
|
||||
GSTextureCache::Target::Target(GSRenderer* r, const GIFRegTEX0& TEX0, const bool depth_supported, const int type)
|
||||
: Surface(r)
|
||||
, m_type(type)
|
||||
GSTextureCache::Target::Target(const GIFRegTEX0& TEX0, const bool depth_supported, const int type)
|
||||
: m_type(type)
|
||||
, m_used(false)
|
||||
, m_depth_supported(depth_supported)
|
||||
{
|
||||
|
@ -2115,7 +2110,7 @@ void GSTextureCache::Target::Update()
|
|||
|
||||
return;
|
||||
}
|
||||
else if (m_type == DepthStencil && m_renderer->m_game.title == CRC::FFX2)
|
||||
else if (m_type == DepthStencil && g_gs_renderer->m_game.title == CRC::FFX2)
|
||||
{
|
||||
GL_INS("ERROR: bad invalidation detected, depth buffer will be cleared");
|
||||
// FFX2 menu. Invalidation of the depth is wrongly done and only the first
|
||||
|
@ -2141,13 +2136,13 @@ void GSTextureCache::Target::Update()
|
|||
|
||||
GSTexture* t = g_gs_device->CreateTexture(w, h, false, GSTexture::Format::Color);
|
||||
|
||||
GSOffset off = m_renderer->m_mem.GetOffset(m_TEX0.TBP0, m_TEX0.TBW, m_TEX0.PSM);
|
||||
GSOffset off = g_gs_renderer->m_mem.GetOffset(m_TEX0.TBP0, m_TEX0.TBW, m_TEX0.PSM);
|
||||
|
||||
GSTexture::GSMap m;
|
||||
|
||||
if (t->Map(m))
|
||||
{
|
||||
m_renderer->m_mem.ReadTexture(off, r, m.bits, m.pitch, TEXA);
|
||||
g_gs_renderer->m_mem.ReadTexture(off, r, m.bits, m.pitch, TEXA);
|
||||
|
||||
t->Unmap();
|
||||
}
|
||||
|
@ -2155,7 +2150,7 @@ void GSTextureCache::Target::Update()
|
|||
{
|
||||
int pitch = ((w + 3) & ~3) * 4;
|
||||
|
||||
m_renderer->m_mem.ReadTexture(off, r, m_temp, pitch, TEXA);
|
||||
g_gs_renderer->m_mem.ReadTexture(off, r, m_temp, pitch, TEXA);
|
||||
|
||||
t->Update(r.rsize(), m_temp, pitch);
|
||||
}
|
||||
|
@ -2498,14 +2493,13 @@ void GSTextureCache::InjectHashCacheTexture(const HashCacheKey& key, GSTexture*
|
|||
|
||||
// GSTextureCache::Palette
|
||||
|
||||
GSTextureCache::Palette::Palette(const GSRenderer* renderer, u16 pal, bool need_gs_texture)
|
||||
GSTextureCache::Palette::Palette(u16 pal, bool need_gs_texture)
|
||||
: m_pal(pal)
|
||||
, m_tex_palette(nullptr)
|
||||
, m_renderer(renderer)
|
||||
{
|
||||
u16 palette_size = pal * sizeof(u32);
|
||||
m_clut = (u32*)_aligned_malloc(palette_size, 64);
|
||||
memcpy(m_clut, (const u32*)m_renderer->m_mem.m_clut, palette_size);
|
||||
memcpy(m_clut, (const u32*)g_gs_renderer->m_mem.m_clut, palette_size);
|
||||
if (need_gs_texture)
|
||||
{
|
||||
InitializeTexture();
|
||||
|
@ -2566,8 +2560,7 @@ bool GSTextureCache::PaletteKeyEqual::operator()(const PaletteKey& lhs, const Pa
|
|||
|
||||
// GSTextureCache::PaletteMap
|
||||
|
||||
GSTextureCache::PaletteMap::PaletteMap(const GSRenderer* renderer)
|
||||
: m_renderer(renderer)
|
||||
GSTextureCache::PaletteMap::PaletteMap()
|
||||
{
|
||||
for (auto& map : m_maps)
|
||||
{
|
||||
|
@ -2584,7 +2577,7 @@ std::shared_ptr<GSTextureCache::Palette> GSTextureCache::PaletteMap::LookupPalet
|
|||
// pal == 256 : index 1
|
||||
auto& map = m_maps[pal == 16 ? 0 : 1];
|
||||
|
||||
const u32* clut = (const u32*)m_renderer->m_mem.m_clut;
|
||||
const u32* clut = (const u32*)g_gs_renderer->m_mem.m_clut;
|
||||
|
||||
// Create PaletteKey for searching into map (clut is actually not copied, so do not store this key into the map)
|
||||
const PaletteKey palette_key = {clut, pal};
|
||||
|
@ -2640,7 +2633,7 @@ std::shared_ptr<GSTextureCache::Palette> GSTextureCache::PaletteMap::LookupPalet
|
|||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Palette> palette = std::make_shared<Palette>(m_renderer, pal, need_gs_texture);
|
||||
std::shared_ptr<Palette> palette = std::make_shared<Palette>(pal, need_gs_texture);
|
||||
|
||||
map.emplace(palette->GetPaletteKey(), palette);
|
||||
|
||||
|
@ -2714,7 +2707,7 @@ __fi static GSTextureCache::HashType FinishBlockHash(BlockHashState& st)
|
|||
return XXH3_64bits_digest(&st);
|
||||
}
|
||||
|
||||
static void HashTextureLevel(GSRenderer* renderer, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, BlockHashState& hash_st, u8* temp)
|
||||
static void HashTextureLevel(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, BlockHashState& hash_st, u8* temp)
|
||||
{
|
||||
const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[TEX0.PSM];
|
||||
const GSVector2i& bs = psm.bs;
|
||||
|
@ -2725,7 +2718,7 @@ static void HashTextureLevel(GSRenderer* renderer, const GIFRegTEX0& TEX0, const
|
|||
// We want to hash the exact same blocks here.
|
||||
const GSVector4i rect(0, 0, tw, th);
|
||||
const GSVector4i block_rect(rect.ralign<Align_Outside>(bs));
|
||||
GSLocalMemory& mem = renderer->m_mem;
|
||||
GSLocalMemory& mem = g_gs_renderer->m_mem;
|
||||
GSOffset off = mem.GetOffset(TEX0.TBP0, TEX0.TBW, TEX0.PSM);
|
||||
|
||||
// For textures which are smaller than the block size, we expand and then hash.
|
||||
|
@ -2738,7 +2731,7 @@ static void HashTextureLevel(GSRenderer* renderer, const GIFRegTEX0& TEX0, const
|
|||
const GSLocalMemory::readTexture rtx = psm.rtxP;
|
||||
|
||||
// Use temp buffer for expanding, since we may not need to update.
|
||||
(renderer->m_mem.*rtx)(off, block_rect, temp, pitch, TEXA);
|
||||
(mem.*rtx)(off, block_rect, temp, pitch, TEXA);
|
||||
|
||||
// Hash the expanded texture.
|
||||
u8* ptr = temp;
|
||||
|
@ -2771,11 +2764,11 @@ static void HashTextureLevel(GSRenderer* renderer, const GIFRegTEX0& TEX0, const
|
|||
}
|
||||
}
|
||||
|
||||
GSTextureCache::HashType GSTextureCache::HashTexture(GSRenderer* renderer, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
GSTextureCache::HashType GSTextureCache::HashTexture(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
{
|
||||
BlockHashState hash_st;
|
||||
BlockHashReset(hash_st);
|
||||
HashTextureLevel(renderer, TEX0, TEXA, hash_st, m_temp);
|
||||
HashTextureLevel(TEX0, TEXA, hash_st, m_temp);
|
||||
return FinishBlockHash(hash_st);
|
||||
}
|
||||
|
||||
|
@ -2828,7 +2821,7 @@ GSTextureCache::HashCacheKey::HashCacheKey()
|
|||
TEXA.U64 = 0;
|
||||
}
|
||||
|
||||
GSTextureCache::HashCacheKey GSTextureCache::HashCacheKey::Create(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, GSRenderer* renderer, const u32* clut, const GSVector2i* lod)
|
||||
GSTextureCache::HashCacheKey GSTextureCache::HashCacheKey::Create(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const u32* clut, const GSVector2i* lod)
|
||||
{
|
||||
const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[TEX0.PSM];
|
||||
|
||||
|
@ -2841,7 +2834,7 @@ GSTextureCache::HashCacheKey GSTextureCache::HashCacheKey::Create(const GIFRegTE
|
|||
BlockHashReset(hash_st);
|
||||
|
||||
// base level is always hashed
|
||||
HashTextureLevel(renderer, TEX0, TEXA, hash_st, m_temp);
|
||||
HashTextureLevel(TEX0, TEXA, hash_st, m_temp);
|
||||
|
||||
if (lod)
|
||||
{
|
||||
|
@ -2850,8 +2843,8 @@ GSTextureCache::HashCacheKey GSTextureCache::HashCacheKey::Create(const GIFRegTE
|
|||
const int nmips = lod->y - lod->x + 1;
|
||||
for (int i = 1; i < nmips; i++)
|
||||
{
|
||||
const GIFRegTEX0 MIP_TEX0{renderer->GetTex0Layer(basemip + i)};
|
||||
HashTextureLevel(renderer, MIP_TEX0, TEXA, hash_st, m_temp);
|
||||
const GIFRegTEX0 MIP_TEX0{g_gs_renderer->GetTex0Layer(basemip + i)};
|
||||
HashTextureLevel(MIP_TEX0, TEXA, hash_st, m_temp);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,8 +50,7 @@ public:
|
|||
|
||||
HashCacheKey();
|
||||
|
||||
static HashCacheKey Create(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, GSRenderer* renderer, const u32* clut,
|
||||
const GSVector2i* lod);
|
||||
static HashCacheKey Create(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const u32* clut, const GSVector2i* lod);
|
||||
|
||||
HashCacheKey WithRemovedCLUTHash() const;
|
||||
void RemoveCLUTHash();
|
||||
|
@ -76,9 +75,6 @@ public:
|
|||
|
||||
class Surface : public GSAlignedClass<32>
|
||||
{
|
||||
protected:
|
||||
GSRenderer* m_renderer;
|
||||
|
||||
public:
|
||||
GSTexture* m_texture;
|
||||
HashCacheEntry* m_from_hash_cache;
|
||||
|
@ -90,7 +86,7 @@ public:
|
|||
u32 m_end_block; // Hint of the surface area.
|
||||
|
||||
public:
|
||||
Surface(GSRenderer* r);
|
||||
Surface();
|
||||
virtual ~Surface();
|
||||
|
||||
void UpdateAge();
|
||||
|
@ -110,10 +106,9 @@ public:
|
|||
u32* m_clut;
|
||||
u16 m_pal;
|
||||
GSTexture* m_tex_palette;
|
||||
const GSRenderer* m_renderer;
|
||||
|
||||
public:
|
||||
Palette(const GSRenderer* renderer, u16 pal, bool need_gs_texture);
|
||||
Palette(u16 pal, bool need_gs_texture);
|
||||
~Palette();
|
||||
|
||||
// Disable copy constructor and copy operator
|
||||
|
@ -178,7 +173,7 @@ public:
|
|||
GSOffset::PageLooper m_pages;
|
||||
|
||||
public:
|
||||
Source(GSRenderer* r, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, bool dummy_container = false);
|
||||
Source(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, bool dummy_container = false);
|
||||
virtual ~Source();
|
||||
|
||||
__fi bool CanPreload() const { return CanPreloadTextureSize(m_TEX0.TW, m_TEX0.TH); }
|
||||
|
@ -200,7 +195,7 @@ public:
|
|||
bool m_dirty_alpha;
|
||||
|
||||
public:
|
||||
Target(GSRenderer* r, const GIFRegTEX0& TEX0, const bool depth_supported, const int type);
|
||||
Target(const GIFRegTEX0& TEX0, const bool depth_supported, const int type);
|
||||
|
||||
void UpdateValidity(const GSVector4i& rect);
|
||||
|
||||
|
@ -211,7 +206,6 @@ public:
|
|||
{
|
||||
private:
|
||||
static const u16 MAX_SIZE = 65535; // Max size of each map.
|
||||
const GSRenderer* m_renderer;
|
||||
|
||||
// Array of 2 maps, the first for 64B palettes and the second for 1024B palettes.
|
||||
// Each map stores the key PaletteKey (clut copy, pal value) pointing to the relevant shared pointer to Palette object.
|
||||
|
@ -219,7 +213,7 @@ public:
|
|||
std::array<std::unordered_map<PaletteKey, std::shared_ptr<Palette>, PaletteKeyHash, PaletteKeyEqual>, 2> m_maps;
|
||||
|
||||
public:
|
||||
PaletteMap(const GSRenderer* renderer);
|
||||
PaletteMap();
|
||||
|
||||
// Retrieves a shared pointer to a valid Palette from m_maps or creates a new one adding it to the data structure
|
||||
std::shared_ptr<Palette> LookupPalette(u16 pal, bool need_gs_texture);
|
||||
|
@ -276,7 +270,6 @@ public:
|
|||
};
|
||||
|
||||
protected:
|
||||
GSRenderer* m_renderer;
|
||||
PaletteMap m_palette_map;
|
||||
SourceMap m_src;
|
||||
std::unordered_map<HashCacheKey, HashCacheEntry, HashCacheKeyHash> m_hash_cache;
|
||||
|
@ -293,13 +286,13 @@ protected:
|
|||
HashCacheEntry* LookupHashCache(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, bool& paltex, const u32* clut, const GSVector2i* lod);
|
||||
|
||||
static void PreloadTexture(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, GSLocalMemory& mem, bool paltex, GSTexture* tex, u32 level);
|
||||
static HashType HashTexture(GSRenderer* renderer, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
static HashType HashTexture(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
|
||||
// TODO: virtual void Write(Source* s, const GSVector4i& r) = 0;
|
||||
// TODO: virtual void Write(Target* t, const GSVector4i& r) = 0;
|
||||
|
||||
public:
|
||||
GSTextureCache(GSRenderer* r);
|
||||
GSTextureCache();
|
||||
~GSTextureCache();
|
||||
|
||||
__fi u64 GetHashCacheMemoryUsage() const { return m_hash_cache_memory_usage; }
|
||||
|
|
|
@ -202,25 +202,25 @@ public:
|
|||
virtual ~GSRasterizerList();
|
||||
|
||||
template <class DS>
|
||||
static IRasterizer* Create(int threads)
|
||||
static std::unique_ptr<IRasterizer> Create(int threads)
|
||||
{
|
||||
threads = std::max<int>(threads, 0);
|
||||
|
||||
if (threads == 0)
|
||||
{
|
||||
return new GSRasterizer(new DS(), 0, 1);
|
||||
return std::make_unique<GSRasterizer>(new DS(), 0, 1);
|
||||
}
|
||||
|
||||
GSRasterizerList* rl = new GSRasterizerList(threads);
|
||||
std::unique_ptr<GSRasterizerList> rl(new GSRasterizerList(threads));
|
||||
|
||||
for (int i = 0; i < threads; i++)
|
||||
{
|
||||
rl->m_r.push_back(std::unique_ptr<GSRasterizer>(new GSRasterizer(new DS(), i, threads)));
|
||||
auto& r = *rl->m_r[i];
|
||||
rl->m_workers.push_back(std::unique_ptr<GSWorker>(new GSWorker(
|
||||
[rl, i]() { rl->OnWorkerStartup(i); },
|
||||
[i]() { GSRasterizerList::OnWorkerStartup(i); },
|
||||
[&r](GSRingHeap::SharedPtr<GSRasterizerData>& item) { r.Draw(item.get()); },
|
||||
[rl, i]() { rl->OnWorkerShutdown(i); })));
|
||||
[i]() { GSRasterizerList::OnWorkerShutdown(i); })));
|
||||
}
|
||||
|
||||
return rl;
|
||||
|
|
|
@ -31,10 +31,7 @@ GSRendererSW::GSRendererSW(int threads)
|
|||
{
|
||||
m_nativeres = true; // ignore ini, sw is always native
|
||||
|
||||
m_tc = new GSTextureCacheSW(this);
|
||||
|
||||
memset(m_texture, 0, sizeof(m_texture));
|
||||
|
||||
m_tc = std::make_unique<GSTextureCacheSW>();
|
||||
m_rl = GSRasterizerList::Create<GSDrawScanline>(threads);
|
||||
|
||||
m_output = (u8*)_aligned_malloc(1024 * 1024 * sizeof(u32), 32);
|
||||
|
@ -62,16 +59,10 @@ GSRendererSW::GSRendererSW(int threads)
|
|||
|
||||
GSRendererSW::~GSRendererSW()
|
||||
{
|
||||
// Need to destroy worker queue first to stop any pending thread work
|
||||
delete m_rl;
|
||||
delete m_tc;
|
||||
|
||||
for (GSTexture* tex : m_texture)
|
||||
{
|
||||
delete tex;
|
||||
}
|
||||
|
||||
_aligned_free(m_output);
|
||||
// strictly speaking we should always be destroyed when the destructor runs..
|
||||
// except if an exception gets thrown during construction. this will go once
|
||||
// we get rid of exceptions...
|
||||
GSRendererSW::Destroy();
|
||||
}
|
||||
|
||||
void GSRendererSW::Reset()
|
||||
|
@ -83,6 +74,22 @@ void GSRendererSW::Reset()
|
|||
GSRenderer::Reset();
|
||||
}
|
||||
|
||||
void GSRendererSW::Destroy()
|
||||
{
|
||||
// Need to destroy worker queue first to stop any pending thread work
|
||||
m_rl.reset();
|
||||
m_tc.reset();
|
||||
|
||||
for (GSTexture*& tex : m_texture)
|
||||
{
|
||||
delete tex;
|
||||
tex = nullptr;
|
||||
}
|
||||
|
||||
_aligned_free(m_output);
|
||||
m_output = nullptr;
|
||||
}
|
||||
|
||||
void GSRendererSW::VSync(u32 field, bool registers_written)
|
||||
{
|
||||
Sync(0); // IncAge might delete a cached texture in use
|
||||
|
@ -335,7 +342,7 @@ void GSRendererSW::Draw()
|
|||
}
|
||||
}
|
||||
|
||||
auto data = m_vertex_heap.make_shared<SharedData>(this).cast<GSRasterizerData>();
|
||||
auto data = m_vertex_heap.make_shared<SharedData>().cast<GSRasterizerData>();
|
||||
SharedData* sd = static_cast<SharedData*>(data.get());
|
||||
|
||||
sd->primclass = m_vt.m_primclass;
|
||||
|
@ -1419,9 +1426,8 @@ bool GSRendererSW::GetScanlineGlobalData(SharedData* data)
|
|||
return true;
|
||||
}
|
||||
|
||||
GSRendererSW::SharedData::SharedData(GSRendererSW* parent)
|
||||
: m_parent(parent)
|
||||
, m_fpsm(0)
|
||||
GSRendererSW::SharedData::SharedData()
|
||||
: m_fpsm(0)
|
||||
, m_zpsm(0)
|
||||
, m_using_pages(false)
|
||||
, m_syncpoint(SyncNone)
|
||||
|
@ -1466,17 +1472,17 @@ void GSRendererSW::SharedData::UsePages(const GSOffset::PageLooper* fb_pages, in
|
|||
|
||||
if (global.sel.fb)
|
||||
{
|
||||
m_parent->UsePages(*fb_pages, 0);
|
||||
GSRendererSW::GetInstance()->UsePages(*fb_pages, 0);
|
||||
}
|
||||
|
||||
if (global.sel.zb)
|
||||
{
|
||||
m_parent->UsePages(*zb_pages, 1);
|
||||
GSRendererSW::GetInstance()->UsePages(*zb_pages, 1);
|
||||
}
|
||||
|
||||
for (size_t i = 0; m_tex[i].t != NULL; i++)
|
||||
{
|
||||
m_parent->UsePages(m_tex[i].t->m_pages, 2);
|
||||
GSRendererSW::GetInstance()->UsePages(m_tex[i].t->m_pages, 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1500,17 +1506,17 @@ void GSRendererSW::SharedData::ReleasePages()
|
|||
|
||||
if (global.sel.fb)
|
||||
{
|
||||
m_parent->ReleasePages(m_fb_pages, 0);
|
||||
GSRendererSW::GetInstance()->ReleasePages(m_fb_pages, 0);
|
||||
}
|
||||
|
||||
if (global.sel.zb)
|
||||
{
|
||||
m_parent->ReleasePages(m_zb_pages, 1);
|
||||
GSRendererSW::GetInstance()->ReleasePages(m_zb_pages, 1);
|
||||
}
|
||||
|
||||
for (size_t i = 0; m_tex[i].t != NULL; i++)
|
||||
{
|
||||
m_parent->ReleasePages(m_tex[i].t->m_pages, 2);
|
||||
GSRendererSW::GetInstance()->ReleasePages(m_tex[i].t->m_pages, 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1545,19 +1551,19 @@ void GSRendererSW::SharedData::UpdateSource()
|
|||
|
||||
// TODO
|
||||
|
||||
if (m_parent->s_dump)
|
||||
if (g_gs_renderer->s_dump)
|
||||
{
|
||||
u64 frame = g_perfmon.GetFrame();
|
||||
|
||||
std::string s;
|
||||
|
||||
if (m_parent->s_savet && m_parent->s_n >= m_parent->s_saven)
|
||||
if (g_gs_renderer->s_savet && g_gs_renderer->s_n >= g_gs_renderer->s_saven)
|
||||
{
|
||||
for (size_t i = 0; m_tex[i].t != NULL; i++)
|
||||
{
|
||||
const GIFRegTEX0& TEX0 = m_parent->GetTex0Layer(i);
|
||||
const GIFRegTEX0& TEX0 = g_gs_renderer->GetTex0Layer(i);
|
||||
|
||||
s = format("%05d_f%lld_itex%d_%05x_%s.bmp", m_parent->s_n, frame, i, TEX0.TBP0, psm_str(TEX0.PSM));
|
||||
s = format("%05d_f%lld_itex%d_%05x_%s.bmp", g_gs_renderer->s_n, frame, i, TEX0.TBP0, psm_str(TEX0.PSM));
|
||||
|
||||
m_tex[i].t->Save(root_sw + s);
|
||||
}
|
||||
|
@ -1568,7 +1574,7 @@ void GSRendererSW::SharedData::UpdateSource()
|
|||
|
||||
t->Update(GSVector4i(0, 0, 256, 1), global.clut, sizeof(u32) * 256);
|
||||
|
||||
s = format("%05d_f%lld_itexp_%05x_%s.bmp", m_parent->s_n, frame, (int)m_parent->m_context->TEX0.CBP, psm_str(m_parent->m_context->TEX0.CPSM));
|
||||
s = format("%05d_f%lld_itexp_%05x_%s.bmp", g_gs_renderer->s_n, frame, (int)g_gs_renderer->m_context->TEX0.CBP, psm_str(g_gs_renderer->m_context->TEX0.CPSM));
|
||||
|
||||
t->Save(root_sw + s);
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include "GSDrawScanline.h"
|
||||
#include "GS/GSRingHeap.h"
|
||||
|
||||
class GSRendererSW : public GSRenderer
|
||||
class GSRendererSW final : public GSRenderer
|
||||
{
|
||||
static const GSVector4 m_pos_scale;
|
||||
#if _M_SSE >= 0x501
|
||||
|
@ -35,7 +35,6 @@ class GSRendererSW : public GSRenderer
|
|||
};
|
||||
|
||||
public:
|
||||
GSRendererSW* m_parent;
|
||||
GSOffset::PageLooper m_fb_pages;
|
||||
GSOffset::PageLooper m_zb_pages;
|
||||
int m_fpsm;
|
||||
|
@ -50,7 +49,7 @@ class GSRendererSW : public GSRenderer
|
|||
} m_syncpoint;
|
||||
|
||||
public:
|
||||
SharedData(GSRendererSW* parent);
|
||||
SharedData();
|
||||
virtual ~SharedData();
|
||||
|
||||
void UsePages(const GSOffset::PageLooper* fb_pages, int fpsm, const GSOffset::PageLooper* zb_pages, int zpsm);
|
||||
|
@ -68,10 +67,10 @@ class GSRendererSW : public GSRenderer
|
|||
void ConvertVertexBuffer(GSVertexSW* RESTRICT dst, const GSVertex* RESTRICT src, size_t count);
|
||||
|
||||
protected:
|
||||
IRasterizer* m_rl;
|
||||
std::unique_ptr<IRasterizer> m_rl;
|
||||
std::unique_ptr<GSTextureCacheSW> m_tc;
|
||||
GSRingHeap m_vertex_heap;
|
||||
GSTextureCacheSW* m_tc;
|
||||
GSTexture* m_texture[3];
|
||||
std::array<GSTexture*, 3> m_texture = {};
|
||||
u8* m_output;
|
||||
GSPixelOffset4* m_fzb;
|
||||
GSVector4i m_fzb_bbox;
|
||||
|
@ -101,4 +100,8 @@ protected:
|
|||
public:
|
||||
GSRendererSW(int threads);
|
||||
~GSRendererSW() override;
|
||||
|
||||
__fi static GSRendererSW* GetInstance() { return static_cast<GSRendererSW*>(g_gs_renderer.get()); }
|
||||
|
||||
void Destroy() override;
|
||||
};
|
||||
|
|
|
@ -16,10 +16,7 @@
|
|||
#include "PrecompiledHeader.h"
|
||||
#include "GSTextureCacheSW.h"
|
||||
|
||||
GSTextureCacheSW::GSTextureCacheSW(GSState* state)
|
||||
: m_state(state)
|
||||
{
|
||||
}
|
||||
GSTextureCacheSW::GSTextureCacheSW() = default;
|
||||
|
||||
GSTextureCacheSW::~GSTextureCacheSW()
|
||||
{
|
||||
|
@ -58,7 +55,7 @@ GSTextureCacheSW::Texture* GSTextureCacheSW::Lookup(const GIFRegTEX0& TEX0, cons
|
|||
}
|
||||
|
||||
// Lookup miss
|
||||
Texture* t = new Texture(m_state, tw0, TEX0, TEXA);
|
||||
Texture* t = new Texture(tw0, TEX0, TEXA);
|
||||
|
||||
m_textures.insert(t);
|
||||
|
||||
|
@ -137,9 +134,8 @@ void GSTextureCacheSW::IncAge()
|
|||
|
||||
//
|
||||
|
||||
GSTextureCacheSW::Texture::Texture(GSState* state, u32 tw0, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
: m_state(state)
|
||||
, m_buff(NULL)
|
||||
GSTextureCacheSW::Texture::Texture(u32 tw0, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
|
||||
: m_buff(NULL)
|
||||
, m_tw(tw0)
|
||||
, m_age(0)
|
||||
, m_complete(false)
|
||||
|
@ -157,14 +153,14 @@ GSTextureCacheSW::Texture::Texture(GSState* state, u32 tw0, const GIFRegTEX0& TE
|
|||
|
||||
m_sharedbits = GSUtil::HasSharedBitsPtr(m_TEX0.PSM);
|
||||
|
||||
m_offset = m_state->m_mem.GetOffset(TEX0.TBP0, TEX0.TBW, TEX0.PSM);
|
||||
m_offset = g_gs_renderer->m_mem.GetOffset(TEX0.TBP0, TEX0.TBW, TEX0.PSM);
|
||||
m_pages = m_offset.pageLooperForRect(GSVector4i(0, 0, 1 << TEX0.TW, 1 << TEX0.TH));
|
||||
|
||||
m_repeating = m_TEX0.IsRepeating(); // repeating mode always works, it is just slightly slower
|
||||
|
||||
if (m_repeating)
|
||||
{
|
||||
m_p2t = m_state->m_mem.GetPage2TileMap(m_TEX0);
|
||||
m_p2t = g_gs_renderer->m_mem.GetPage2TileMap(m_TEX0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,7 +209,7 @@ bool GSTextureCacheSW::Texture::Update(const GSVector4i& rect)
|
|||
}
|
||||
}
|
||||
|
||||
GSLocalMemory& mem = m_state->m_mem;
|
||||
GSLocalMemory& mem = g_gs_renderer->m_mem;
|
||||
|
||||
GSOffset off = m_offset;
|
||||
|
||||
|
@ -291,7 +287,7 @@ bool GSTextureCacheSW::Texture::Update(const GSVector4i& rect)
|
|||
|
||||
bool GSTextureCacheSW::Texture::Save(const std::string& fn, bool dds) const
|
||||
{
|
||||
const u32* RESTRICT clut = m_state->m_mem.m_clut;
|
||||
const u32* RESTRICT clut = g_gs_renderer->m_mem.m_clut;
|
||||
|
||||
int w = 1 << m_TEX0.TW;
|
||||
int h = 1 << m_TEX0.TH;
|
||||
|
|
|
@ -25,7 +25,6 @@ public:
|
|||
class Texture
|
||||
{
|
||||
public:
|
||||
GSState* m_state;
|
||||
GSOffset m_offset;
|
||||
GSOffset::PageLooper m_pages;
|
||||
GIFRegTEX0 m_TEX0;
|
||||
|
@ -44,7 +43,7 @@ public:
|
|||
// fast mode: each u32 bits map to the 32 blocks of that page
|
||||
// repeating mode: 1 bpp image of the texture tiles (8x8), also having 512 elements is just a coincidence (worst case: (1024*1024)/(8*8)/(sizeof(u32)*8))
|
||||
|
||||
Texture(GSState* state, u32 tw0, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
Texture(u32 tw0, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
|
||||
virtual ~Texture();
|
||||
|
||||
bool Update(const GSVector4i& r);
|
||||
|
@ -52,12 +51,11 @@ public:
|
|||
};
|
||||
|
||||
protected:
|
||||
GSState* m_state;
|
||||
std::unordered_set<Texture*> m_textures;
|
||||
std::array<FastList<Texture*>, MAX_PAGES> m_map;
|
||||
|
||||
public:
|
||||
GSTextureCacheSW(GSState* state);
|
||||
GSTextureCacheSW();
|
||||
virtual ~GSTextureCacheSW();
|
||||
|
||||
Texture* Lookup(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, u32 tw0 = 0);
|
||||
|
|
Loading…
Reference in New Issue