mirror of https://github.com/PCSX2/pcsx2.git
GS/HW: Only allocate as many mip levels as present
This prevents any possibility of sampling undefined or garbage/reused texture data from levels which aren't used by the current draw. And a tiny bit of VRAM. But nothing really measurable. Also fixes a bug in Vulkan where a copied texture can get mip-generated in the wrong command buffer when using basic mipmapping.
This commit is contained in:
parent
7f9932129d
commit
1910c8fc0f
|
@ -264,9 +264,9 @@ GSTexture* GSDevice::CreateDepthStencil(int w, int h, GSTexture::Format format,
|
|||
return FetchSurface(GSTexture::Type::DepthStencil, w, h, 1, format, clear, true);
|
||||
}
|
||||
|
||||
GSTexture* GSDevice::CreateTexture(int w, int h, bool mipmap, GSTexture::Format format, bool prefer_reuse /* = false */)
|
||||
GSTexture* GSDevice::CreateTexture(int w, int h, int mipmap_levels, GSTexture::Format format, bool prefer_reuse /* = false */)
|
||||
{
|
||||
const int levels = mipmap ? MipmapLevelsForSize(w, h) : 1;
|
||||
const int levels = mipmap_levels < 0 ? MipmapLevelsForSize(w, h) : mipmap_levels;
|
||||
return FetchSurface(GSTexture::Type::Texture, w, h, levels, format, false, prefer_reuse);
|
||||
}
|
||||
|
||||
|
|
|
@ -812,7 +812,7 @@ public:
|
|||
|
||||
GSTexture* CreateRenderTarget(int w, int h, GSTexture::Format format, bool clear = true);
|
||||
GSTexture* CreateDepthStencil(int w, int h, GSTexture::Format format, bool clear = true);
|
||||
GSTexture* CreateTexture(int w, int h, bool mipmap, GSTexture::Format format, bool prefer_reuse = false);
|
||||
GSTexture* CreateTexture(int w, int h, int mipmap_levels, GSTexture::Format format, bool prefer_reuse = false);
|
||||
GSTexture* CreateOffscreen(int w, int h, GSTexture::Format format);
|
||||
GSTexture::Format GetDefaultTextureFormat(GSTexture::Type type);
|
||||
|
||||
|
|
|
@ -440,9 +440,12 @@ void GSDevice12::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r,
|
|||
dTexVK->CommitClear();
|
||||
|
||||
EndRenderPass();
|
||||
|
||||
sTexVK->TransitionToState(D3D12_RESOURCE_STATE_COPY_SOURCE);
|
||||
dTexVK->SetState(GSTexture::State::Dirty);
|
||||
sTexVK->SetUsedThisCommandBuffer();
|
||||
|
||||
dTexVK->TransitionToState(D3D12_RESOURCE_STATE_COPY_DEST);
|
||||
dTexVK->SetUsedThisCommandBuffer();
|
||||
|
||||
D3D12_TEXTURE_COPY_LOCATION srcloc;
|
||||
srcloc.pResource = sTexVK->GetResource();
|
||||
|
@ -2514,7 +2517,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
|||
else if (config.require_one_barrier)
|
||||
{
|
||||
// requires a copy of the RT
|
||||
draw_rt_clone = static_cast<GSTexture12*>(CreateTexture(rtsize.x, rtsize.y, false, GSTexture::Format::Color, false));
|
||||
draw_rt_clone = static_cast<GSTexture12*>(CreateTexture(rtsize.x, rtsize.y, 1, GSTexture::Format::Color, false));
|
||||
if (draw_rt_clone)
|
||||
{
|
||||
EndRenderPass();
|
||||
|
|
|
@ -4661,7 +4661,7 @@ bool GSRendererHW::OI_FFXII(GSTexture* rt, GSTexture* ds, GSTextureCache::Source
|
|||
|
||||
g_gs_device->Recycle(t->m_texture);
|
||||
|
||||
t->m_texture = g_gs_device->CreateTexture(512, 512, false, GSTexture::Format::Color);
|
||||
t->m_texture = g_gs_device->CreateTexture(512, 512, 1, GSTexture::Format::Color);
|
||||
|
||||
t->m_texture->Update(GSVector4i(0, 0, 448, lines), video, 448 * 4);
|
||||
|
||||
|
|
|
@ -1562,12 +1562,18 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
|
|||
{
|
||||
const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[TEX0.PSM];
|
||||
Source* src = new Source(TEX0, TEXA, false);
|
||||
if (lod)
|
||||
src->m_lod = *lod;
|
||||
|
||||
int tw = 1 << TEX0.TW;
|
||||
int th = 1 << TEX0.TH;
|
||||
//int tp = TEX0.TBW << 6;
|
||||
int tlevels = 1;
|
||||
if (lod)
|
||||
{
|
||||
// lod won't contain the full range when using basic mipmapping, only that
|
||||
// which is hashed, so we just allocate the full thing.
|
||||
tlevels = (GSConfig.HWMipmap != HWMipmapLevel::Full) ? -1 : (lod->y - lod->x + 1);
|
||||
src->m_lod = *lod;
|
||||
}
|
||||
|
||||
bool hack = false;
|
||||
|
||||
|
@ -1584,7 +1590,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
|
|||
GSTexture* sTex = dst->m_texture;
|
||||
GSTexture* dTex = outside_target ?
|
||||
g_gs_device->CreateRenderTarget(w, h, GSTexture::Format::Color, true) :
|
||||
g_gs_device->CreateTexture(w, h, false, GSTexture::Format::Color, true);
|
||||
g_gs_device->CreateTexture(w, h, tlevels, GSTexture::Format::Color, true);
|
||||
|
||||
// copy the rt in
|
||||
const GSVector4i area(GSVector4i(x, y, x + w, y + h).rintersect(GSVector4i(sTex->GetSize()).zwxy()));
|
||||
|
@ -1816,7 +1822,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
|
|||
// 'src' is the new texture cache entry (hence the output)
|
||||
GSTexture* sTex = dst->m_texture;
|
||||
GSTexture* dTex = use_texture ?
|
||||
g_gs_device->CreateTexture(w, h, false, GSTexture::Format::Color, true) :
|
||||
g_gs_device->CreateTexture(w, h, 1, GSTexture::Format::Color, true) :
|
||||
g_gs_device->CreateRenderTarget(w, h, GSTexture::Format::Color, false);
|
||||
src->m_texture = dTex;
|
||||
|
||||
|
@ -1880,12 +1886,12 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
|
|||
}
|
||||
else if (paltex)
|
||||
{
|
||||
src->m_texture = g_gs_device->CreateTexture(tw, th, false, GSTexture::Format::UNorm8);
|
||||
src->m_texture = g_gs_device->CreateTexture(tw, th, tlevels, GSTexture::Format::UNorm8);
|
||||
AttachPaletteToSource(src, psm.pal, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
src->m_texture = g_gs_device->CreateTexture(tw, th, (lod != nullptr), GSTexture::Format::Color);
|
||||
src->m_texture = g_gs_device->CreateTexture(tw, th, tlevels, GSTexture::Format::Color);
|
||||
if (psm.pal > 0)
|
||||
{
|
||||
AttachPaletteToSource(src, psm.pal, false);
|
||||
|
@ -2009,7 +2015,8 @@ GSTextureCache::HashCacheEntry* GSTextureCache::LookupHashCache(const GIFRegTEX0
|
|||
// expand/upload texture
|
||||
const int tw = 1 << TEX0.TW;
|
||||
const int th = 1 << TEX0.TH;
|
||||
GSTexture* tex = g_gs_device->CreateTexture(tw, th, paltex ? false : (lod != nullptr), paltex ? GSTexture::Format::UNorm8 : GSTexture::Format::Color);
|
||||
const int tlevels = lod ? ((GSConfig.HWMipmap != HWMipmapLevel::Full) ? -1 : (lod->y - lod->x + 1)) : 1;
|
||||
GSTexture* tex = g_gs_device->CreateTexture(tw, th, tlevels, paltex ? GSTexture::Format::UNorm8 : GSTexture::Format::Color);
|
||||
if (!tex)
|
||||
{
|
||||
// out of video memory if we hit here
|
||||
|
@ -2627,7 +2634,7 @@ void GSTextureCache::Target::Update()
|
|||
TEXA.TA0 = 0;
|
||||
TEXA.TA1 = 0x80;
|
||||
|
||||
GSTexture* t = g_gs_device->CreateTexture(w, h, false, GSTexture::Format::Color);
|
||||
GSTexture* t = g_gs_device->CreateTexture(w, h, 1, GSTexture::Format::Color);
|
||||
|
||||
GSOffset off = g_gs_renderer->m_mem.GetOffset(m_TEX0.TBP0, m_TEX0.TBW, m_TEX0.PSM);
|
||||
|
||||
|
@ -3047,7 +3054,7 @@ void GSTextureCache::Palette::InitializeTexture()
|
|||
// sampling such texture are always normalized by 255.
|
||||
// This is because indexes are stored as normalized values of an RGBA texture (e.g. index 15 will be read as (15/255),
|
||||
// and therefore will read texel 15/255 * texture size).
|
||||
m_tex_palette = g_gs_device->CreateTexture(256, 1, false, GSTexture::Format::Color);
|
||||
m_tex_palette = g_gs_device->CreateTexture(256, 1, 1, GSTexture::Format::Color);
|
||||
m_tex_palette->Update(GSVector4i(0, 0, m_pal, 1), m_clut, m_pal * sizeof(m_clut[0]));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -536,7 +536,7 @@ GSTexture* GSTextureReplacements::CreateReplacementTexture(const ReplacementText
|
|||
mipmap = false;
|
||||
}
|
||||
|
||||
GSTexture* tex = g_gs_device->CreateTexture(rtex.width, rtex.height, mipmap, rtex.format);
|
||||
GSTexture* tex = g_gs_device->CreateTexture(rtex.width, rtex.height, static_cast<int>(rtex.mips.size()) + 1, rtex.format);
|
||||
if (!tex)
|
||||
return nullptr;
|
||||
|
||||
|
|
|
@ -1873,7 +1873,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
|||
else if (config.require_one_barrier && !m_features.texture_barrier)
|
||||
{
|
||||
// Requires a copy of the RT
|
||||
draw_rt_clone = CreateTexture(rtsize.x, rtsize.y, false, GSTexture::Format::Color, false);
|
||||
draw_rt_clone = CreateTexture(rtsize.x, rtsize.y, 1, GSTexture::Format::Color, false);
|
||||
GL_PUSH("Copy RT to temp texture for fbmask {%d,%d %dx%d}",
|
||||
config.drawarea.left, config.drawarea.top,
|
||||
config.drawarea.width(), config.drawarea.height());
|
||||
|
|
|
@ -552,6 +552,7 @@ void GSDeviceVK::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r,
|
|||
EndRenderPass();
|
||||
|
||||
dTexVK->TransitionToLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
dTexVK->SetUsedThisCommandBuffer();
|
||||
sTexVK->TransitionToLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
sTexVK->SetUsedThisCommandBuffer();
|
||||
|
||||
|
@ -2954,7 +2955,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
|||
else if (config.require_one_barrier && !m_features.texture_barrier)
|
||||
{
|
||||
// requires a copy of the RT
|
||||
draw_rt_clone = static_cast<GSTextureVK*>(CreateTexture(rtsize.x, rtsize.y, false, GSTexture::Format::Color, false));
|
||||
draw_rt_clone = static_cast<GSTextureVK*>(CreateTexture(rtsize.x, rtsize.y, 1, GSTexture::Format::Color, false));
|
||||
if (draw_rt_clone)
|
||||
{
|
||||
EndRenderPass();
|
||||
|
|
Loading…
Reference in New Issue