GS: Make sure everything in GSState is initialized

This commit is contained in:
Stenzek 2023-02-12 13:04:18 +10:00 committed by refractionpcsx2
parent d0a933cda8
commit 8a08e2fd97
7 changed files with 146 additions and 161 deletions

View File

@ -481,7 +481,7 @@ public:
static psm_t m_psm[64];
static readImage m_readImageX;
static const int m_vmsize = 1024 * 1024 * 4;
static constexpr int m_vmsize = 1024 * 1024 * 4;
u8* m_vm8;

View File

@ -37,14 +37,61 @@ static __fi bool IsFirstProvokingVertex()
return (GSConfig.Renderer != GSRendererType::SW && !g_gs_device->Features().provoking_vertex_last);
}
constexpr int GSState::GetSaveStateSize()
{
int size = 0;
size += sizeof(STATE_VERSION);
size += sizeof(m_env.PRIM);
size += sizeof(m_env.PRMODECONT);
size += sizeof(m_env.TEXCLUT);
size += sizeof(m_env.SCANMSK);
size += sizeof(m_env.TEXA);
size += sizeof(m_env.FOGCOL);
size += sizeof(m_env.DIMX);
size += sizeof(m_env.DTHE);
size += sizeof(m_env.COLCLAMP);
size += sizeof(m_env.PABE);
size += sizeof(m_env.BITBLTBUF);
size += sizeof(m_env.TRXDIR);
size += sizeof(m_env.TRXPOS);
size += sizeof(m_env.TRXREG);
size += sizeof(m_env.TRXREG); // obsolete
for (int i = 0; i < 2; i++)
{
size += sizeof(m_env.CTXT[i].XYOFFSET);
size += sizeof(m_env.CTXT[i].TEX0);
size += sizeof(m_env.CTXT[i].TEX1);
size += sizeof(m_env.CTXT[i].CLAMP);
size += sizeof(m_env.CTXT[i].MIPTBP1);
size += sizeof(m_env.CTXT[i].MIPTBP2);
size += sizeof(m_env.CTXT[i].SCISSOR);
size += sizeof(m_env.CTXT[i].ALPHA);
size += sizeof(m_env.CTXT[i].TEST);
size += sizeof(m_env.CTXT[i].FBA);
size += sizeof(m_env.CTXT[i].FRAME);
size += sizeof(m_env.CTXT[i].ZBUF);
}
size += sizeof(m_v.RGBAQ);
size += sizeof(m_v.ST);
size += sizeof(m_v.UV);
size += sizeof(m_v.FOG);
size += sizeof(m_v.XYZ);
size += sizeof(GIFReg); // obsolete
size += sizeof(m_tr.x);
size += sizeof(m_tr.y);
size += GSLocalMemory::m_vmsize;
size += (sizeof(GIFPath::tag) + sizeof(GIFPath::reg)) * 4 /* std::size(GSState::m_path) */; // std::size won't work without an instance.
size += sizeof(m_q);
return size;
}
GSState::GSState()
: m_version(STATE_VERSION)
, m_q(1.0f)
, m_scanmask_used(0)
, tex_flushed(true)
, m_vt(this, IsFirstProvokingVertex())
, m_regs(NULL)
, m_crc(0)
: m_vt(this, IsFirstProvokingVertex())
{
// m_nativeres seems to be a hack. Unfortunately it impacts draw call number which make debug painful in the replayer.
// Let's keep it disabled to ease debug.
@ -63,54 +110,6 @@ GSState::GSState()
m_draw_transfers.clear();
m_sssize = 0;
m_sssize += sizeof(m_version);
m_sssize += sizeof(m_env.PRIM);
m_sssize += sizeof(m_env.PRMODECONT);
m_sssize += sizeof(m_env.TEXCLUT);
m_sssize += sizeof(m_env.SCANMSK);
m_sssize += sizeof(m_env.TEXA);
m_sssize += sizeof(m_env.FOGCOL);
m_sssize += sizeof(m_env.DIMX);
m_sssize += sizeof(m_env.DTHE);
m_sssize += sizeof(m_env.COLCLAMP);
m_sssize += sizeof(m_env.PABE);
m_sssize += sizeof(m_env.BITBLTBUF);
m_sssize += sizeof(m_env.TRXDIR);
m_sssize += sizeof(m_env.TRXPOS);
m_sssize += sizeof(m_env.TRXREG);
m_sssize += sizeof(m_env.TRXREG); // obsolete
for (int i = 0; i < 2; i++)
{
m_sssize += sizeof(m_env.CTXT[i].XYOFFSET);
m_sssize += sizeof(m_env.CTXT[i].TEX0);
m_sssize += sizeof(m_env.CTXT[i].TEX1);
m_sssize += sizeof(m_env.CTXT[i].CLAMP);
m_sssize += sizeof(m_env.CTXT[i].MIPTBP1);
m_sssize += sizeof(m_env.CTXT[i].MIPTBP2);
m_sssize += sizeof(m_env.CTXT[i].SCISSOR);
m_sssize += sizeof(m_env.CTXT[i].ALPHA);
m_sssize += sizeof(m_env.CTXT[i].TEST);
m_sssize += sizeof(m_env.CTXT[i].FBA);
m_sssize += sizeof(m_env.CTXT[i].FRAME);
m_sssize += sizeof(m_env.CTXT[i].ZBUF);
}
m_sssize += sizeof(m_v.RGBAQ);
m_sssize += sizeof(m_v.ST);
m_sssize += sizeof(m_v.UV);
m_sssize += sizeof(m_v.FOG);
m_sssize += sizeof(m_v.XYZ);
m_sssize += sizeof(GIFReg); // obsolete
m_sssize += sizeof(m_tr.x);
m_sssize += sizeof(m_tr.y);
m_sssize += m_mem.m_vmsize;
m_sssize += (sizeof(m_path[0].tag) + sizeof(m_path[0].reg)) * std::size(m_path);
m_sssize += sizeof(m_q);
PRIM = &m_env.PRIM;
//CSR->rREV = 0x20;
m_env.PRMODECONT.AC = 1;
@ -2330,18 +2329,19 @@ int GSState::Freeze(freezeData* fd, bool sizeonly)
{
if (sizeonly)
{
fd->size = m_sssize;
fd->size = GetSaveStateSize();
return 0;
}
if (!fd->data || fd->size < m_sssize)
if (!fd->data || fd->size < GetSaveStateSize())
return -1;
Flush(GSFlushReason::SAVESTATE);
u8* data = fd->data;
const u32 version = STATE_VERSION;
WriteState(data, &m_version);
WriteState(data, &version);
WriteState(data, &m_env.PRIM);
WriteState(data, &m_env.PRMODECONT);
WriteState(data, &m_env.TEXCLUT);
@ -2409,7 +2409,7 @@ int GSState::Defrost(const freezeData* fd)
if (!fd || !fd->data || fd->size == 0)
return -1;
if (fd->size < m_sssize)
if (fd->size < GetSaveStateSize())
return -1;
u8* data = fd->data;
@ -2418,7 +2418,7 @@ int GSState::Defrost(const freezeData* fd)
ReadState(&version, data);
if (version > m_version)
if (version > STATE_VERSION)
{
Console.Error("GS: Savestate version is incompatible. Load aborted.");
return -1;
@ -3850,9 +3850,6 @@ GIFRegTEX0 GSState::GetTex0Layer(u32 lod)
GSState::GSTransferBuffer::GSTransferBuffer()
{
x = y = 0;
start = end = total = 0;
constexpr size_t alloc_size = 1024 * 1024 * 4;
buff = reinterpret_cast<u8*>(_aligned_malloc(alloc_size, 32));
}

View File

@ -35,13 +35,15 @@ public:
GSState();
virtual ~GSState();
static constexpr int GetSaveStateSize();
private:
// RESTRICT prevents multiple loads of the same part of the register when accessing its bitfields (the compiler is happy to know that memory writes in-between will not go there)
typedef void (GSState::*GIFPackedRegHandler)(const GIFPackedReg* RESTRICT r);
GIFPackedRegHandler m_fpGIFPackedRegHandlers[16];
GIFPackedRegHandler m_fpGIFPackedRegHandlerXYZ[8][4];
GIFPackedRegHandler m_fpGIFPackedRegHandlers[16] = {};
GIFPackedRegHandler m_fpGIFPackedRegHandlerXYZ[8][4] = {};
void CheckFlushes();
@ -58,14 +60,14 @@ private:
typedef void (GSState::*GIFRegHandler)(const GIFReg* RESTRICT r);
GIFRegHandler m_fpGIFRegHandlers[256];
GIFRegHandler m_fpGIFRegHandlerXYZ[8][4];
GIFRegHandler m_fpGIFRegHandlers[256] = {};
GIFRegHandler m_fpGIFRegHandlerXYZ[8][4] = {};
typedef void (GSState::*GIFPackedRegHandlerC)(const GIFPackedReg* RESTRICT r, u32 size);
GIFPackedRegHandlerC m_fpGIFPackedRegHandlersC[2];
GIFPackedRegHandlerC m_fpGIFPackedRegHandlerSTQRGBAXYZF2[8];
GIFPackedRegHandlerC m_fpGIFPackedRegHandlerSTQRGBAXYZ2[8];
GIFPackedRegHandlerC m_fpGIFPackedRegHandlersC[2] = {};
GIFPackedRegHandlerC m_fpGIFPackedRegHandlerSTQRGBAXYZF2[8] = {};
GIFPackedRegHandlerC m_fpGIFPackedRegHandlerSTQRGBAXYZ2[8] = {};
template<u32 prim, bool auto_flush, bool index_swap> void GIFPackedRegHandlerSTQRGBAXYZF2(const GIFPackedReg* RESTRICT r, u32 size);
template<u32 prim, bool auto_flush, bool index_swap> void GIFPackedRegHandlerSTQRGBAXYZ2(const GIFPackedReg* RESTRICT r, u32 size);
@ -117,15 +119,12 @@ private:
template<bool auto_flush, bool index_swap>
void SetPrimHandlers();
u32 m_version;
int m_sssize;
struct GSTransferBuffer
{
int x, y;
int start, end, total;
u8* buff;
GIFRegBITBLTBUF m_blit;
int x = 0, y = 0;
int start = 0, end = 0, total = 0;
u8* buff = nullptr;
GIFRegBITBLTBUF m_blit = {};
GSTransferBuffer();
virtual ~GSTransferBuffer();
@ -139,14 +138,14 @@ private:
void CalcAlphaMinMax();
protected:
GSVertex m_v;
float m_q;
GSVector4i m_scissor;
GSVector4i m_ofxy;
GSVertex m_v = {};
float m_q = 1.0f;
GSVector4i m_scissor = {};
GSVector4i m_ofxy = {};
u8 m_scanmask_used;
bool tex_flushed;
bool m_isPackedUV_HackFlag;
u8 m_scanmask_used = 0;
bool tex_flushed = true;
bool m_isPackedUV_HackFlag = false;
struct
{
@ -154,13 +153,13 @@ protected:
u32 head, tail, next, maxcount; // head: first vertex, tail: last vertex + 1, next: last indexed + 1
u32 xy_tail;
u64 xy[4];
} m_vertex;
} m_vertex = {};
struct
{
u32* buff;
u32 tail;
} m_index;
} m_index = {};
void UpdateContext();
void UpdateScissor();
@ -213,24 +212,24 @@ public:
int draw;
};
GIFPath m_path[4];
GIFRegPRIM* PRIM;
GSPrivRegSet* m_regs;
GIFPath m_path[4] = {};
GIFRegPRIM* PRIM = nullptr;
GSPrivRegSet* m_regs = nullptr;
GSLocalMemory m_mem;
GSDrawingEnvironment m_env;
GSDrawingEnvironment m_backup_env;
GSDrawingEnvironment m_prev_env;
GSVector4i temp_draw_rect;
GSDrawingContext* m_context;
u32 m_crc;
CRC::Game m_game;
GSDrawingEnvironment m_env = {};
GSDrawingEnvironment m_backup_env = {};
GSDrawingEnvironment m_prev_env = {};
GSVector4i temp_draw_rect = {};
GSDrawingContext* m_context = nullptr;
u32 m_crc = 0;
CRC::Game m_game = {};
std::unique_ptr<GSDumpBase> m_dump;
bool m_nativeres;
bool m_mipmap;
u32 m_dirty_gs_regs;
int m_backed_up_ctx;
bool m_nativeres = false;
bool m_mipmap = false;
bool m_force_preload = false;
u32 m_dirty_gs_regs = 0;
int m_backed_up_ctx = 0;
std::vector<GSUploadQueue> m_draw_transfers;
bool m_force_preload;
static int s_n;
@ -278,7 +277,7 @@ public:
GSREOPEN = 1 << 13,
};
GSFlushReason m_state_flush_reason;
GSFlushReason m_state_flush_reason = UNKNOWN;
enum PRIM_OVERLAP
{
@ -287,7 +286,7 @@ public:
PRIM_OVERLAP_NO
};
PRIM_OVERLAP m_prim_overlap;
PRIM_OVERLAP m_prim_overlap = PRIM_OVERLAP_UNKNOW;
std::vector<size_t> m_drawlist;
struct GSPCRTCRegs
@ -297,31 +296,31 @@ public:
// these values leave a small black line on the right in a bunch of games, but it's not so bad.
// The only conclusion I can come to is there is horizontal overscan expected so there would normally
// be black borders either side anyway, or both sides slightly covered.
const GSVector4i VideoModeOffsets[6] = {
GSVector4i(640, 224, 642, 25),
GSVector4i(640, 256, 676, 36),
GSVector4i(640, 480, 276, 34),
GSVector4i(720, 480, 232, 35),
GSVector4i(1280, 720, 302, 24),
GSVector4i(1920, 540, 238, 40)
static inline constexpr GSVector4i VideoModeOffsets[6] = {
GSVector4i::cxpr(640, 224, 642, 25),
GSVector4i::cxpr(640, 256, 676, 36),
GSVector4i::cxpr(640, 480, 276, 34),
GSVector4i::cxpr(720, 480, 232, 35),
GSVector4i::cxpr(1280, 720, 302, 24),
GSVector4i::cxpr(1920, 540, 238, 40)
};
const GSVector4i VideoModeOffsetsOverscan[6] = {
GSVector4i(711, 243, 498, 12),
GSVector4i(702, 288, 532, 18),
GSVector4i(640, 480, 276, 34),
GSVector4i(720, 480, 232, 35),
GSVector4i(1280, 720, 302, 24),
GSVector4i(1920, 540, 238, 40)
static inline constexpr GSVector4i VideoModeOffsetsOverscan[6] = {
GSVector4i::cxpr(711, 243, 498, 12),
GSVector4i::cxpr(702, 288, 532, 18),
GSVector4i::cxpr(640, 480, 276, 34),
GSVector4i::cxpr(720, 480, 232, 35),
GSVector4i::cxpr(1280, 720, 302, 24),
GSVector4i::cxpr(1920, 540, 238, 40)
};
const GSVector4i VideoModeDividers[6] = {
GSVector4i(3, 0, 2559, 239),
GSVector4i(3, 0, 2559, 287),
GSVector4i(1, 0, 1279, 479),
GSVector4i(1, 0, 1439, 479),
GSVector4i(0, 0, 1279, 719),
GSVector4i(0, 0, 1919, 1079)
static inline constexpr GSVector4i VideoModeDividers[6] = {
GSVector4i::cxpr(3, 0, 2559, 239),
GSVector4i::cxpr(3, 0, 2559, 287),
GSVector4i::cxpr(1, 0, 1279, 479),
GSVector4i::cxpr(1, 0, 1439, 479),
GSVector4i::cxpr(0, 0, 1279, 719),
GSVector4i::cxpr(0, 0, 1919, 1079)
};
struct PCRTCDisplay
@ -345,12 +344,12 @@ public:
}
};
int videomode;
int interlaced;
int FFMD;
bool PCRTCSameSrc;
bool toggling_field;
PCRTCDisplay PCRTCDisplays[2];
int videomode = 0;
int interlaced = 0;
int FFMD = 0;
bool PCRTCSameSrc = false;
bool toggling_field = false;
PCRTCDisplay PCRTCDisplays[2] = {};
bool IsAnalogue()
{

View File

@ -19,10 +19,8 @@
#include "GS/GSState.h"
GSVertexTrace::GSVertexTrace(const GSState* state, bool provoking_vertex_first)
: m_accurate_stq(false), m_state(state), m_primclass(GS_INVALID_CLASS)
: m_state(state)
{
memset(&m_alpha, 0, sizeof(m_alpha));
MULTI_ISA_SELECT(GSVertexTracePopulateFunctions)(*this, provoking_vertex_first);
}

View File

@ -44,7 +44,7 @@ public:
int min, max;
bool valid;
};
bool m_accurate_stq;
bool m_accurate_stq = false;
protected:
const GSState* m_state;
@ -54,25 +54,25 @@ protected:
FindMinMaxPtr m_fmm[2][2][2][2][4];
public:
GS_PRIM_CLASS m_primclass;
GS_PRIM_CLASS m_primclass = GS_INVALID_CLASS;
Vertex m_min;
Vertex m_max;
VertexAlpha m_alpha; // source alpha range after tfx, GSRenderer::GetAlphaMinMax() updates it
Vertex m_min = {};
Vertex m_max = {};
VertexAlpha m_alpha = {}; // source alpha range after tfx, GSRenderer::GetAlphaMinMax() updates it
union
{
u32 value;
struct { u32 r:4, g:4, b:4, a:4, x:1, y:1, z:1, f:1, s:1, t:1, q:1, _pad:1; };
struct { u32 rgba:16, xyzf:4, stq:4; };
} m_eq;
} m_eq = {};
union
{
struct { u32 mmag:1, mmin:1, linear:1, opt_linear:1; };
} m_filter;
} m_filter = {};
GSVector2 m_lod; // x = min, y = max
GSVector2 m_lod = {}; // x = min, y = max
public:
GSVertexTrace(const GSState* state, bool provoking_vertex_first);

View File

@ -24,14 +24,6 @@
GSRendererHW::GSRendererHW()
: GSRenderer()
, m_tc(new GSTextureCache())
, m_src(nullptr)
, m_reset(false)
, m_tex_is_fb(false)
, m_channel_shuffle(false)
, m_userhacks_tcoffset(false)
, m_userhacks_tcoffset_x(0)
, m_userhacks_tcoffset_y(0)
, m_lod(GSVector2i(0, 0))
{
MULTI_ISA_SELECT(GSRendererHWPopulateFunctions)(*this);
m_mipmap = (GSConfig.HWMipmap >= HWMipmapLevel::Basic);
@ -44,7 +36,6 @@ GSRendererHW::GSRendererHW()
memset(&m_conf, 0, sizeof(m_conf));
m_prim_overlap = PRIM_OVERLAP_UNKNOW;
ResetStates();
}

View File

@ -97,8 +97,8 @@ private:
void SetTCOffset();
GSTextureCache* m_tc;
GSVector4i m_r;
GSTextureCache::Source* m_src;
GSVector4i m_r = {};
GSTextureCache::Source* m_src = nullptr;
// CRC Hacks
bool IsBadFrame();
@ -107,16 +107,16 @@ private:
int m_skip = 0;
int m_skip_offset = 0;
bool m_reset;
bool m_tex_is_fb;
bool m_channel_shuffle;
bool m_userhacks_tcoffset;
float m_userhacks_tcoffset_x;
float m_userhacks_tcoffset_y;
bool m_reset = false;
bool m_tex_is_fb = false;
bool m_channel_shuffle = false;
bool m_userhacks_tcoffset = false;
float m_userhacks_tcoffset_x = 0.0f;
float m_userhacks_tcoffset_y = 0.0f;
GSVector2i m_lod; // Min & Max level of detail
GSVector2i m_lod = {}; // Min & Max level of detail
GSHWDrawConfig m_conf;
GSHWDrawConfig m_conf = {};
// software sprite renderer state
std::vector<GSVertexSW> m_sw_vertex_buffer;