GS: Make renderer a global

This commit is contained in:
Connor McLaughlin 2022-04-23 14:08:26 +10:00 committed by refractionpcsx2
parent 568ebc6199
commit 6e84613a14
12 changed files with 190 additions and 197 deletions

View File

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

View File

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

View File

@ -60,3 +60,5 @@ public:
bool SaveSnapshotToMemory(u32 width, u32 height, std::vector<u32>* pixels);
};
extern std::unique_ptr<GSRenderer> g_gs_renderer;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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