diff --git a/pcsx2/GS/GSVector.h b/pcsx2/GS/GSVector.h index 3a3e42e4bb..979f284207 100644 --- a/pcsx2/GS/GSVector.h +++ b/pcsx2/GS/GSVector.h @@ -72,6 +72,16 @@ public: { return x != v.x || y != v.y; } + + constexpr GSVector2T operator*(const GSVector2T& v) const + { + return { x * v.x, y * v.y }; + } + + constexpr GSVector2T operator/(const GSVector2T& v) const + { + return { x / v.x, y / v.y }; + } }; typedef GSVector2T GSVector2; diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index 327973ce31..ea556f9786 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -333,7 +333,7 @@ GSTexture* GSRendererHW::GetOutput(int i, int& y_offset) GSTexture* t = NULL; - if (GSTextureCache::Target* rt = m_tc->LookupTarget(TEX0, m_width, m_height, GetFramebufferHeight())) + if (GSTextureCache::Target* rt = m_tc->LookupTarget(TEX0, GetTargetSize(), GetFramebufferHeight())) { t = rt->m_texture; @@ -368,7 +368,7 @@ GSTexture* GSRendererHW::GetFeedbackOutput() TEX0.TBW = m_regs->EXTBUF.EXBW; TEX0.PSM = m_regs->DISP[m_regs->EXTBUF.FBIN & 1].DISPFB.PSM; - GSTextureCache::Target* rt = m_tc->LookupTarget(TEX0, m_width, m_height, /*GetFrameRect(i).bottom*/ 0); + GSTextureCache::Target* rt = m_tc->LookupTarget(TEX0, GetTargetSize(), /*GetFrameRect(i).bottom*/ 0); GSTexture* t = rt->m_texture; @@ -789,10 +789,10 @@ void GSRendererHW::MergeSprite(GSTextureCache::Source* tex) } } -GSVector2 GSRendererHW::GetTextureScaleFactor() +GSVector2 GSRendererHW::GetTextureScaleFactor(const bool force_upscaling) { GSVector2 scale_factor{ 1.0f, 1.0f }; - if (CanUpscale()) + if (force_upscaling || CanUpscale()) { const int multiplier = GetUpscaleMultiplier(); if (multiplier == 0) @@ -812,6 +812,24 @@ GSVector2 GSRendererHW::GetTextureScaleFactor() return scale_factor; } +GSVector2 GSRendererHW::GetTextureScaleFactor() +{ + return GetTextureScaleFactor(false); +} + +GSVector2i GSRendererHW::GetTargetSize() +{ + const GSVector2i t_size = { m_width, m_height }; + if (GetUpscaleMultiplier() == 1 || CanUpscale()) + return t_size; + // Undo the upscaling for native resolution draws. + const GSVector2 up_s = GetTextureScaleFactor(true); + return { + static_cast(std::ceil(static_cast(t_size.x) / up_s.x)), + static_cast(std::ceil(static_cast(t_size.y) / up_s.y)), + }; +} + void GSRendererHW::InvalidateVideoMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r) { // printf("[%d] InvalidateVideoMem %d,%d - %d,%d %05x (%d)\n", (int)m_perfmon.GetFrame(), r.left, r.top, r.right, r.bottom, (int)BITBLTBUF.DBP, (int)BITBLTBUF.DPSM); @@ -1518,6 +1536,8 @@ void GSRendererHW::Draw() } } + const GSVector2i t_size = GetTargetSize(); + TEX0.TBP0 = context->FRAME.Block(); TEX0.TBW = context->FRAME.FBW; TEX0.PSM = context->FRAME.PSM; @@ -1526,7 +1546,7 @@ void GSRendererHW::Draw() GSTexture* rt_tex = nullptr; if (!no_rt) { - rt = m_tc->LookupTarget(TEX0, m_width, m_height, GSTextureCache::RenderTarget, true, fm); + rt = m_tc->LookupTarget(TEX0, t_size, GSTextureCache::RenderTarget, true, fm); rt_tex = rt->m_texture; } @@ -1538,7 +1558,7 @@ void GSRendererHW::Draw() GSTexture* ds_tex = nullptr; if (!no_ds) { - ds = m_tc->LookupTarget(TEX0, m_width, m_height, GSTextureCache::DepthStencil, context->DepthWrite()); + ds = m_tc->LookupTarget(TEX0, t_size, GSTextureCache::DepthStencil, context->DepthWrite()); ds_tex = ds->m_texture; } @@ -2230,7 +2250,7 @@ bool GSRendererHW::OI_RozenMaidenGebetGarden(GSTexture* rt, GSTexture* ds, GSTex TEX0.TBW = m_context->FRAME.FBW; TEX0.PSM = m_context->FRAME.PSM; - if (GSTextureCache::Target* tmp_rt = m_tc->LookupTarget(TEX0, m_width, m_height, GSTextureCache::RenderTarget, true)) + if (GSTextureCache::Target* tmp_rt = m_tc->LookupTarget(TEX0, GetTargetSize(), GSTextureCache::RenderTarget, true)) { GL_INS("OI_RozenMaidenGebetGarden FB clear"); tmp_rt->m_texture->Commit(); // Don't bother to save few MB for a single game @@ -2249,7 +2269,7 @@ bool GSRendererHW::OI_RozenMaidenGebetGarden(GSTexture* rt, GSTexture* ds, GSTex TEX0.TBW = m_context->FRAME.FBW; TEX0.PSM = m_context->ZBUF.PSM; - if (GSTextureCache::Target* tmp_ds = m_tc->LookupTarget(TEX0, m_width, m_height, GSTextureCache::DepthStencil, true)) + if (GSTextureCache::Target* tmp_ds = m_tc->LookupTarget(TEX0, GetTargetSize(), GSTextureCache::DepthStencil, true)) { GL_INS("OI_RozenMaidenGebetGarden ZB clear"); tmp_ds->m_texture->Commit(); // Don't bother to save few MB for a single game @@ -2287,7 +2307,7 @@ bool GSRendererHW::OI_SonicUnleashed(GSTexture* rt, GSTexture* ds, GSTextureCach GL_INS("OI_SonicUnleashed replace draw by a copy"); - GSTextureCache::Target* src = m_tc->LookupTarget(Texture, m_width, m_height, GSTextureCache::RenderTarget, true); + GSTextureCache::Target* src = m_tc->LookupTarget(Texture, GetTargetSize(), GSTextureCache::RenderTarget, true); const GSVector2i size = rt->GetSize(); diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.h b/pcsx2/GS/Renderers/HW/GSRendererHW.h index 5b06019ba8..bbf9690ef4 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.h +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.h @@ -177,7 +177,9 @@ public: GSVector4 RealignTargetTextureCoordinate(const GSTextureCache::Source* tex); GSVector4i ComputeBoundingBox(const GSVector2& rtscale, const GSVector2i& rtsize); void MergeSprite(GSTextureCache::Source* tex); + GSVector2 GetTextureScaleFactor(const bool force_upscaling); GSVector2 GetTextureScaleFactor() override; + GSVector2i GetTargetSize(); void Reset() override; void VSync(u32 field, bool registers_written) override; diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index 789d0a5705..109f8845d0 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -443,51 +443,111 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con return src; } -void GSTextureCache::ScaleTexture(GSTexture* texture) -{ - if (texture) - texture->SetScale(m_renderer->GetTextureScaleFactor()); -} - bool GSTextureCache::ShallSearchTextureInsideRt() { return m_texture_inside_rt || (m_renderer->m_game.flags & CRC::Flags::TextureInsideRt); } -GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, int w, int h, int type, bool used, u32 fbmask) +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]; - u32 bp = TEX0.TBP0; - - Target* dst = NULL; - - auto& list = m_dst[type]; - for (auto i = list.begin(); i != list.end(); ++i) + const GSVector2& new_s = m_renderer->GetTextureScaleFactor(); + const u32 bp = TEX0.TBP0; + GSVector2 res_size{ 0, 0 }; + GSVector2i new_size{ 0, 0 }; + const GSVector4 sRect(0, 0, 1, 1); + GSVector4 dRect{}; + bool clear = true; + const auto& calcRescale = [size, new_s, &res_size, &new_size, &clear, &dRect](const GSTexture* tex) { - Target* t = *i; + // TODO Possible optimization: rescale only the validity rectangle of the old target texture into the new one. + const GSVector2& old_s = tex->GetScale(); + const GSVector2 ratio = new_s / old_s; + const int old_w = tex->GetWidth(); + const int old_h = tex->GetHeight(); + res_size = GSVector2(old_w, old_h) * ratio; + new_size.x = std::max(static_cast(std::ceil(res_size.x)), size.x); + new_size.y = std::max(static_cast(std::ceil(res_size.y)), size.y); + clear = new_size.x > res_size.x || new_size.y > res_size.y; + dRect = GSVector4(0.0f, 0.0f, res_size.x, res_size.y); + }; - if (bp == t->m_TEX0.TBP0) + Target* dst = nullptr; + auto& list = m_dst[type]; + if (!is_frame) + { + for (auto i = list.begin(); i != list.end(); ++i) { - list.MoveFront(i.Index()); + Target* t = *i; - dst = t; + if (bp == t->m_TEX0.TBP0) + { + list.MoveFront(i.Index()); - dst->m_32_bits_fmt |= (psm_s.bpp != 16); - dst->m_TEX0 = TEX0; + dst = t; - break; + dst->m_32_bits_fmt |= (psm_s.bpp != 16); + dst->m_TEX0 = TEX0; + + break; + } } + } + else + { + assert(type == RenderTarget); + // Let's try to find a perfect frame that contains valid data + for (auto t : list) + if (bp == t->m_TEX0.TBP0 && t->m_end_block >= bp) + { + dst = t; + GL_CACHE("TC: Lookup Frame %dx%d, perfect hit: %d (0x%x -> 0x%x %s)", size.x, size.y, dst->m_texture->GetID(), bp, t->m_end_block, psm_str(TEX0.PSM)); + break; + } + + // 2nd try ! Try to find a frame that include the bp + if (!dst) + for (auto t : list) + if (t->m_TEX0.TBP0 < bp && bp <= t->m_end_block) + { + dst = t; + GL_CACHE("TC: Lookup Frame %dx%d, inclusive hit: %d (0x%x, took 0x%x -> 0x%x %s)", size.x, size.y, t->m_texture->GetID(), bp, t->m_TEX0.TBP0, t->m_end_block, psm_str(TEX0.PSM)); + break; + } + + // 3rd try ! Try to find a frame that doesn't contain valid data (honestly I'm not sure we need to do it) + if (!dst) + for (auto t :list) + if (bp == t->m_TEX0.TBP0) + { + dst = t; + GL_CACHE("TC: Lookup Frame %dx%d, empty hit: %d (0x%x -> 0x%x %s)", size.x, size.y, dst->m_texture->GetID(), bp, t->m_end_block, psm_str(TEX0.PSM)); + break; + } } if (dst) { - GL_CACHE("TC: Lookup Target(%s) %dx%d, hit: %d (0x%x, %s)", to_string(type), w, h, dst->m_texture->GetID(), bp, psm_str(TEX0.PSM)); + GL_CACHE("TC: Lookup %s(%s) %dx%d, hit: %d (0x%x, %s)", is_frame ? "Frame" : "Target", to_string(type), size.x, size.y, dst->m_texture->GetID(), bp, psm_str(TEX0.PSM)); dst->Update(); - dst->m_dirty_alpha |= (psm_s.trbpp == 32 && (fbmask & 0xFF000000) != 0xFF000000) || (psm_s.trbpp == 16); + const GSVector2& old_s = dst->m_texture->GetScale(); + if (new_s != old_s) + { + calcRescale(dst->m_texture); + GSTexture* tex = type == RenderTarget ? g_gs_device->CreateSparseRenderTarget(new_size.x, new_size.y, GSTexture::Format::Color, clear) : + g_gs_device->CreateSparseDepthStencil(new_size.x, new_size.y, GSTexture::Format::DepthStencil, clear); + g_gs_device->StretchRect(dst->m_texture, sRect, tex, dRect, ShaderConvert::COPY, false); + g_gs_device->Recycle(dst->m_texture); + tex->SetScale(new_s); + dst->m_texture = tex; + } + + if (!is_frame) + dst->m_dirty_alpha |= (psm_s.trbpp == 32 && (fbmask & 0xFF000000) != 0xFF000000) || (psm_s.trbpp == 16); } - else if (m_can_convert_depth) + else if (!is_frame && m_can_convert_depth) { int rev_type = (type == DepthStencil) ? RenderTarget : DepthStencil; @@ -513,42 +573,31 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, int if (dst_match) { - const GSVector2& new_s = m_renderer->GetTextureScaleFactor(); - const GSVector2& old_s = dst_match->m_texture->GetScale(); - const GSVector2 ratio{ new_s.x / old_s.x, new_s.y / old_s.y }; - const int old_w = dst_match->m_texture->GetWidth(); - const int old_h = dst_match->m_texture->GetHeight(); - const float res_w = static_cast(old_w) * ratio.x; - const float res_h = static_cast(old_h) * ratio.y; - const int new_w = std::max(static_cast(std::ceil(res_w)), w); - const int new_h = std::max(static_cast(std::ceil(res_h)), h); - const GSVector4 sRect(0, 0, 1, 1); - const GSVector4 dRect(0.0f, 0.0f, res_w, res_h); - - dst = CreateTarget(TEX0, new_w, new_h, type); + dst_match->Update(); + calcRescale(dst_match->m_texture); + dst = CreateTarget(TEX0, new_size.x, new_size.y, type, clear); dst->m_32_bits_fmt = dst_match->m_32_bits_fmt; - ShaderConvert shader; bool fmt_16_bits = (psm_s.bpp == 16 && GSLocalMemory::m_psm[dst_match->m_TEX0.PSM].bpp == 16); if (type == DepthStencil) { - GL_CACHE("TC: Lookup Target(Depth) %dx%d, hit Color (0x%x, %s was %s)", new_w, new_h, bp, psm_str(TEX0.PSM), psm_str(dst_match->m_TEX0.PSM)); + GL_CACHE("TC: Lookup Target(Depth) %dx%d, hit Color (0x%x, %s was %s)", new_size.x, new_size.y, bp, psm_str(TEX0.PSM), psm_str(dst_match->m_TEX0.PSM)); shader = (fmt_16_bits) ? ShaderConvert::RGB5A1_TO_FLOAT16 : (ShaderConvert)((int)ShaderConvert::RGBA8_TO_FLOAT32 + psm_s.fmt); } else { - GL_CACHE("TC: Lookup Target(Color) %dx%d, hit Depth (0x%x, %s was %s)", new_w, new_h, bp, psm_str(TEX0.PSM), psm_str(dst_match->m_TEX0.PSM)); + GL_CACHE("TC: Lookup Target(Color) %dx%d, hit Depth (0x%x, %s was %s)", new_size.x, new_size.y, bp, psm_str(TEX0.PSM), psm_str(dst_match->m_TEX0.PSM)); shader = (fmt_16_bits) ? ShaderConvert::FLOAT16_TO_RGB5A1 : ShaderConvert::FLOAT32_TO_RGBA8; } g_gs_device->StretchRect(dst_match->m_texture, sRect, dst->m_texture, dRect, shader, false); } } - if (dst == NULL) + if (!dst) { - GL_CACHE("TC: Lookup Target(%s) %dx%d, miss (0x%x, %s)", to_string(type), w, h, bp, psm_str(TEX0.PSM)); + GL_CACHE("TC: Lookup %s(%s) %dx%d, miss (0x%x, %s)", is_frame ? "Frame" : "Target", to_string(type), size.x, size.y, bp, psm_str(TEX0.PSM)); - dst = CreateTarget(TEX0, w, h, type); + dst = CreateTarget(TEX0, size.x, size.y, type, true); // In theory new textures contain invalidated data. Still in theory a new target // must contains the content of the GS memory. @@ -572,131 +621,24 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, int // h is likely smaller than w (true most of the time). Reduce the upload size (speed) max_h = std::min(max_h, TEX0.TBW * 64); - dst->m_dirty.push_back(GSDirtyRect(GSVector4i(0, 0, TEX0.TBW * 64, max_h), TEX0.PSM, TEX0.TBW)); + dst->m_dirty.push_back(GSDirtyRect(GSVector4i(0, 0, TEX0.TBW * 64, is_frame ? real_h : max_h), TEX0.PSM, TEX0.TBW)); dst->Update(); } } - ScaleTexture(dst->m_texture); if (used) { dst->m_used = true; } - + if (is_frame) + dst->m_dirty_alpha = false; + assert(dst && dst->m_texture && dst->m_texture->GetScale() == new_s); + assert(dst && dst->m_dirty.empty()); return dst; } -GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, int w, int h, int real_h) +GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, const GSVector2i& size, const int real_h) { - u32 bp = TEX0.TBP0; - - Target* dst = NULL; - -#if 0 - // Dump the list of targets for debug - for(auto t : m_dst[RenderTarget]) { - GL_INS("TC: frame 0x%x -> 0x%x : %d (age %d)", t->m_TEX0.TBP0, t->m_end_block, t->m_texture->GetID(), t->m_age); - } -#endif - - // Let's try to find a perfect frame that contains valid data - for (auto t : m_dst[RenderTarget]) - { - if (bp == t->m_TEX0.TBP0 && t->m_end_block >= bp) - { - dst = t; - - GL_CACHE("TC: Lookup Frame %dx%d, perfect hit: %d (0x%x -> 0x%x %s)", w, h, dst->m_texture->GetID(), bp, t->m_end_block, psm_str(TEX0.PSM)); - - break; - } - } - - // 2nd try ! Try to find a frame that include the bp - if (dst == NULL) - { - for (auto t : m_dst[RenderTarget]) - { - if (t->m_TEX0.TBP0 < bp && bp <= t->m_end_block) - { - dst = t; - - GL_CACHE("TC: Lookup Frame %dx%d, inclusive hit: %d (0x%x, took 0x%x -> 0x%x %s)", w, h, t->m_texture->GetID(), bp, t->m_TEX0.TBP0, t->m_end_block, psm_str(TEX0.PSM)); - - break; - } - } - } - - // 3rd try ! Try to find a frame that doesn't contain valid data (honestly I'm not sure we need to do it) - if (dst == NULL) - { - for (auto t : m_dst[RenderTarget]) - { - if (bp == t->m_TEX0.TBP0) - { - dst = t; - - GL_CACHE("TC: Lookup Frame %dx%d, empty hit: %d (0x%x -> 0x%x %s)", w, h, dst->m_texture->GetID(), bp, t->m_end_block, psm_str(TEX0.PSM)); - - break; - } - } - } - - -#if 0 - for(auto t : m_dst[RenderTarget]) - { - if(bp == t->m_TEX0.TBP0) - { - dst = t; - - GL_CACHE("TC: Lookup Frame %dx%d, perfect hit: %d (0x%x -> 0x%x)", w, h, dst->m_texture->GetID(), bp, t->m_end_block); - - break; - } - else - { - // HACK: try to find something close to the base pointer - - if(t->m_TEX0.TBP0 <= bp && bp < t->m_TEX0.TBP0 + 0xe00UL && (!dst || t->m_TEX0.TBP0 >= dst->m_TEX0.TBP0)) - { - GL_CACHE("TC: Lookup Frame %dx%d, close hit: %d (0x%x, took 0x%x -> 0x%x)", w, h, t->m_texture->GetID(), bp, t->m_TEX0.TBP0, t->m_end_block); - dst = t; - } - } - } -#endif - - if (dst == NULL) - { - GL_CACHE("TC: Lookup Frame %dx%d, miss (0x%x %s)", w, h, bp, psm_str(TEX0.PSM)); - - dst = CreateTarget(TEX0, w, h, RenderTarget); - ScaleTexture(dst->m_texture); - - if (m_preload_frame) - { - // Load GS data into frame. Game can directly uploads a background or the full image in - // "CTRC" buffer. It will also avoid various black screen issue in gs dump. - // - // Code is more or less an equivalent of the SW renderer - // - // Option is hidden and not enabled by default to avoid any regression - dst->m_dirty.push_back(GSDirtyRect(GSVector4i(0, 0, TEX0.TBW * 64, real_h), TEX0.PSM, TEX0.TBW)); - dst->Update(); - } - } - else - { - dst->m_TEX0.TBW = TEX0.TBW; - dst->Update(); - } - - dst->m_used = true; - dst->m_dirty_alpha = false; - - return dst; + return LookupTarget(TEX0, size, RenderTarget, true, 0, true, real_h); } // Goal: Depth And Target at the same address is not possible. On GS it is @@ -1516,27 +1458,27 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con return src; } -GSTextureCache::Target* GSTextureCache::CreateTarget(const GIFRegTEX0& TEX0, int w, int h, int type) +GSTextureCache::Target* GSTextureCache::CreateTarget(const GIFRegTEX0& TEX0, int w, int h, int type, const bool clear) { ASSERT(type == RenderTarget || type == DepthStencil); - Target* t = new Target(m_renderer, TEX0, m_temp, m_can_convert_depth); + Target* t = new Target(m_renderer, TEX0, m_temp, m_can_convert_depth, type); // FIXME: initial data should be unswizzled from local mem in Update() if dirty - t->m_type = type; - if (type == RenderTarget) { - t->m_texture = g_gs_device->CreateSparseRenderTarget(w, h, GSTexture::Format::Color); + t->m_texture = g_gs_device->CreateSparseRenderTarget(w, h, GSTexture::Format::Color, clear); t->m_used = true; // FIXME } else if (type == DepthStencil) { - t->m_texture = g_gs_device->CreateSparseDepthStencil(w, h, GSTexture::Format::DepthStencil); + t->m_texture = g_gs_device->CreateSparseDepthStencil(w, h, GSTexture::Format::DepthStencil, clear); } + t->m_texture->SetScale(m_renderer->GetTextureScaleFactor()); + m_dst[type].push_front(t); return t; @@ -2144,9 +2086,9 @@ bool GSTextureCache::Source::ClutMatch(const PaletteKey& palette_key) // GSTextureCache::Target -GSTextureCache::Target::Target(GSRenderer* r, const GIFRegTEX0& TEX0, u8* temp, bool depth_supported) +GSTextureCache::Target::Target(GSRenderer* r, const GIFRegTEX0& TEX0, u8* temp, const bool depth_supported, const int type) : Surface(r, temp) - , m_type(-1) + , m_type(type) , m_used(false) , m_depth_supported(depth_supported) { @@ -2245,6 +2187,8 @@ void GSTextureCache::Target::Update() } g_gs_device->Recycle(t); + + UpdateValidity(r); } void GSTextureCache::Target::UpdateValidity(const GSVector4i& rect) diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.h b/pcsx2/GS/Renderers/HW/GSTextureCache.h index ebf7c27ab2..09f691babb 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.h +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.h @@ -163,15 +163,15 @@ public: class Target : public Surface { public: - int m_type; + const int m_type; bool m_used; GSDirtyRectList m_dirty; GSVector4i m_valid; - bool m_depth_supported; + const bool m_depth_supported; bool m_dirty_alpha; public: - Target(GSRenderer* r, const GIFRegTEX0& TEX0, u8* temp, bool depth_supported); + Target(GSRenderer* r, const GIFRegTEX0& TEX0, u8* temp, const bool depth_supported, const int type); void UpdateValidity(const GSVector4i& rect); @@ -263,7 +263,7 @@ protected: std::unordered_map m_surface_offset_cache; Source* CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* t = NULL, bool half_right = false, int x_offset = 0, int y_offset = 0, bool mipmap = false); - Target* CreateTarget(const GIFRegTEX0& TEX0, int w, int h, int type); + Target* CreateTarget(const GIFRegTEX0& TEX0, int w, int h, int type, const bool clear); // TODO: virtual void Write(Source* s, const GSVector4i& r) = 0; // TODO: virtual void Write(Target* t, const GSVector4i& r) = 0; @@ -279,8 +279,8 @@ public: Source* LookupSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GSVector4i& r, bool mipmap); Source* LookupDepthSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GSVector4i& r, bool palette = false); - Target* LookupTarget(const GIFRegTEX0& TEX0, int w, int h, int type, bool used, u32 fbmask = 0); - Target* LookupTarget(const GIFRegTEX0& TEX0, int w, int h, int real_h); + Target* LookupTarget(const GIFRegTEX0& TEX0, const GSVector2i& size, int type, bool used, u32 fbmask = 0, const bool is_frame = false, const int real_h = 0); + Target* LookupTarget(const GIFRegTEX0& TEX0, const GSVector2i& size, const int real_h); void InvalidateVideoMemType(int type, u32 bp); void InvalidateVideoMemSubTarget(GSTextureCache::Target* rt); @@ -289,7 +289,6 @@ public: void IncAge(); bool UserHacks_HalfPixelOffset; - void ScaleTexture(GSTexture* texture); bool ShallSearchTextureInsideRt();