diff --git a/pcsx2/GS/GSState.cpp b/pcsx2/GS/GSState.cpp index b1c3c5867f..ae2211102e 100644 --- a/pcsx2/GS/GSState.cpp +++ b/pcsx2/GS/GSState.cpp @@ -154,8 +154,6 @@ void GSState::Reset(bool hardware_reset) UpdateVertexKick(); - UpdateDIMX(); - for (u32 i = 0; i < 2; i++) { m_env.CTXT[i].UpdateScissor(); @@ -1207,9 +1205,6 @@ void GSState::GIFRegHandlerDIMX(const GIFReg* RESTRICT r) m_env.DIMX = r->DIMX; - if (update) - UpdateDIMX(); - if (m_prev_env.DIMX != m_env.DIMX) m_dirty_gs_regs |= (1 << DIRTY_REG_DIMX); else @@ -1454,18 +1449,12 @@ void GSState::Flush(GSFlushReason reason) PRIM = &m_prev_env.PRIM; UpdateContext(); - if (m_dirty_gs_regs & (1 << DIRTY_REG_DIMX)) - UpdateDIMX(); - FlushPrim(); m_draw_env = &m_env; PRIM = &m_env.PRIM; UpdateContext(); - if (m_dirty_gs_regs & (1 << DIRTY_REG_DIMX)) - UpdateDIMX(); - m_backed_up_ctx = -1; } else @@ -2526,8 +2515,6 @@ int GSState::Defrost(const freezeData* fd) UpdateVertexKick(); - UpdateDIMX(); - for (u32 i = 0; i < 2; i++) { m_env.CTXT[i].UpdateScissor(); @@ -2566,7 +2553,6 @@ void GSState::UpdateContext() if (ctx_switch) GL_REG("Context Switch %d", PRIM->CTXT); - // TODO: Don't mutate context (looking at you, HW) m_context = const_cast(&m_draw_env->CTXT[PRIM->CTXT]); UpdateScissor(); @@ -3814,19 +3800,6 @@ bool GSState::IsCoverageAlpha() return !PRIM->ABE && PRIM->AA1 && (m_vt.m_primclass == GS_LINE_CLASS || m_vt.m_primclass == GS_TRIANGLE_CLASS); } -void GSState::UpdateDIMX() -{ - const GIFRegDIMX& DIMX = m_draw_env->DIMX; - dimx[1] = GSVector4i(DIMX.DM00, 0, DIMX.DM01, 0, DIMX.DM02, 0, DIMX.DM03, 0); - dimx[0] = dimx[1].xxzzlh(); - dimx[3] = GSVector4i(DIMX.DM10, 0, DIMX.DM11, 0, DIMX.DM12, 0, DIMX.DM13, 0); - dimx[2] = dimx[3].xxzzlh(); - dimx[5] = GSVector4i(DIMX.DM20, 0, DIMX.DM21, 0, DIMX.DM22, 0, DIMX.DM23, 0); - dimx[4] = dimx[5].xxzzlh(); - dimx[7] = GSVector4i(DIMX.DM30, 0, DIMX.DM31, 0, DIMX.DM32, 0, DIMX.DM33, 0); - dimx[6] = dimx[7].xxzzlh(); -} - GIFRegTEX0 GSState::GetTex0Layer(u32 lod) { // Shortcut diff --git a/pcsx2/GS/GSState.h b/pcsx2/GS/GSState.h index a7fdb359aa..acd95b7f16 100644 --- a/pcsx2/GS/GSState.h +++ b/pcsx2/GS/GSState.h @@ -205,7 +205,6 @@ protected: bool IsMipMapDraw(); bool IsMipMapActive(); bool IsCoverageAlpha(); - void UpdateDIMX(); public: struct GSUploadQueue @@ -224,7 +223,6 @@ public: const GSDrawingEnvironment* m_draw_env = &m_env; GSDrawingContext* m_context = nullptr; GSVector4i temp_draw_rect = {}; - GSVector4i dimx[8] = {}; u32 m_crc = 0; CRC::Game m_game = {}; std::unique_ptr m_dump; @@ -870,6 +868,9 @@ public: /// Returns the appropriate directory for draw dumping. static std::string GetDrawDumpPath(const char* format, ...); + /// Expands dither matrix, suitable for software renderer. + static void ExpandDIMX(GSVector4i* dimx, const GIFRegDIMX DIMX); + void ResetHandlers(); void ResetPCRTC(); @@ -920,3 +921,16 @@ public: PRIM_OVERLAP PrimitiveOverlap(); GIFRegTEX0 GetTex0Layer(u32 lod); }; + +// We put this in the header because of Multi-ISA. +inline void GSState::ExpandDIMX(GSVector4i* dimx, const GIFRegDIMX DIMX) +{ + dimx[1] = GSVector4i(DIMX.DM00, 0, DIMX.DM01, 0, DIMX.DM02, 0, DIMX.DM03, 0); + dimx[0] = dimx[1].xxzzlh(); + dimx[3] = GSVector4i(DIMX.DM10, 0, DIMX.DM11, 0, DIMX.DM12, 0, DIMX.DM13, 0); + dimx[2] = dimx[3].xxzzlh(); + dimx[5] = GSVector4i(DIMX.DM20, 0, DIMX.DM21, 0, DIMX.DM22, 0, DIMX.DM23, 0); + dimx[4] = dimx[5].xxzzlh(); + dimx[7] = GSVector4i(DIMX.DM30, 0, DIMX.DM31, 0, DIMX.DM32, 0, DIMX.DM33, 0); + dimx[6] = dimx[7].xxzzlh(); +} diff --git a/pcsx2/GS/Renderers/HW/GSRendererHWMultiISA.cpp b/pcsx2/GS/Renderers/HW/GSRendererHWMultiISA.cpp index 2b4c88fe89..a36578a392 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHWMultiISA.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHWMultiISA.cpp @@ -36,6 +36,10 @@ void CURRENT_ISA::GSRendererHWPopulateFunctions(GSRendererHW& renderer) GSRendererHWFunctions::Populate(renderer); } +// since there's no overlapping draws, we can just keep this intact +static GSVector4i s_dimx_storage[8]; +static GIFRegDIMX s_last_dimx; + bool GSRendererHWFunctions::SwPrimRender(GSRendererHW& hw, bool invalidate_tc) { GSVertexTrace& vt = hw.m_vt; @@ -47,9 +51,6 @@ bool GSRendererHWFunctions::SwPrimRender(GSRendererHW& hw, bool invalidate_tc) GSRasterizerData data; GSScanlineGlobalData& gd = data.global; - u32 clut_storage[256]; - GSVector4i dimx_storage[8]; - hw.m_sw_vertex_buffer.resize(((hw.m_vertex.next + 1) & ~1)); data.primclass = vt.m_primclass; @@ -180,9 +181,7 @@ bool GSRendererHWFunctions::SwPrimRender(GSRendererHW& hw, bool invalidate_tc) { gd.sel.tlu = 1; - gd.clut = clut_storage; // FIXME: might address uninitialized data of the texture (0xCD) that is not in 0-15 range for 4-bpp formats - - memcpy(gd.clut, (const u32*)hw.m_mem.m_clut, sizeof(u32) * GSLocalMemory::m_psm[context->TEX0.PSM].pal); + gd.clut = const_cast(static_cast(hw.m_mem.m_clut)); } gd.sel.wms = context->CLAMP.WMS; @@ -452,10 +451,12 @@ bool GSRendererHWFunctions::SwPrimRender(GSRendererHW& hw, bool invalidate_tc) if (env.DTHE.DTHE) { gd.sel.dthe = 1; - - gd.dimx = dimx_storage; - - memcpy(gd.dimx, hw.dimx, sizeof(hw.dimx)); + gd.dimx = s_dimx_storage; + if (s_last_dimx != env.DIMX) + { + s_last_dimx = env.DIMX; + GSState::ExpandDIMX(s_dimx_storage, env.DIMX); + } } } diff --git a/pcsx2/GS/Renderers/SW/GSRendererSW.cpp b/pcsx2/GS/Renderers/SW/GSRendererSW.cpp index 45a32d6f51..c56d1b8e21 100644 --- a/pcsx2/GS/Renderers/SW/GSRendererSW.cpp +++ b/pcsx2/GS/Renderers/SW/GSRendererSW.cpp @@ -1327,9 +1327,15 @@ bool GSRendererSW::GetScanlineGlobalData(SharedData* data) { gd.sel.dthe = 1; - gd.dimx = (GSVector4i*)m_vertex_heap.alloc(sizeof(dimx), 32); + if (m_last_dimx != env.DIMX) + { + m_last_dimx = env.DIMX; + ExpandDIMX(m_dimx, env.DIMX); + } - memcpy(gd.dimx, dimx, sizeof(dimx)); + gd.dimx = (GSVector4i*)m_vertex_heap.alloc(sizeof(m_dimx), 32); + + std::memcpy(gd.dimx, m_dimx, sizeof(m_dimx)); } } diff --git a/pcsx2/GS/Renderers/SW/GSRendererSW.h b/pcsx2/GS/Renderers/SW/GSRendererSW.h index 9295a0f044..b9d12341d8 100644 --- a/pcsx2/GS/Renderers/SW/GSRendererSW.h +++ b/pcsx2/GS/Renderers/SW/GSRendererSW.h @@ -69,6 +69,8 @@ protected: u32 m_fzb_cur_pages[16]; std::atomic m_fzb_pages[512]; // u16 frame/zbuf pages interleaved std::atomic m_tex_pages[512]; + GIFRegDIMX m_last_dimx = {}; + GSVector4i m_dimx[8] = {}; void Reset(bool hardware_reset) override; void VSync(u32 field, bool registers_written) override;