mirror of https://github.com/PCSX2/pcsx2.git
GSdx: it's hard to keep track of the leftover vertices properly, a bit of sps was still possible, psx sprites were fixed too
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5065 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
5b5a9787d9
commit
481f1fdda2
|
@ -83,7 +83,7 @@ void GPUDrawScanline::EndDraw(uint64 frame, uint64 ticks, int pixels)
|
|||
|
||||
#ifndef ENABLE_JIT_RASTERIZER
|
||||
|
||||
void GPUDrawScanline::SetupPrim(const GSVertexSW& vertex, const GSVertexSW& dscan)
|
||||
void GPUDrawScanline::SetupPrim(const GSVertexSW* vertex, const uint32* index, const GSVertexSW& dscan)
|
||||
{
|
||||
GPUScanlineSelector sel = m_global.sel;
|
||||
|
||||
|
@ -93,7 +93,7 @@ void GPUDrawScanline::SetupPrim(const GSVertexSW& vertex, const GSVertexSW& dsca
|
|||
{
|
||||
if(sel.sprite)
|
||||
{
|
||||
GSVector4i t = (GSVector4i(vertex.t) >> 8) - GSVector4i::x00000001();
|
||||
GSVector4i t = (GSVector4i(vertex[index[1]].t) >> 8) - GSVector4i::x00000001();
|
||||
|
||||
t = t.ps32(t);
|
||||
t = t.upl16(t);
|
||||
|
|
|
@ -65,7 +65,7 @@ public:
|
|||
|
||||
#ifndef ENABLE_JIT_RASTERIZER
|
||||
|
||||
void SetupPrim(const GSVertexSW& vertex, const GSVertexSW& dscan);
|
||||
void SetupPrim(const GSVertexSW* vertex, const uint32* index, const GSVertexSW& dscan);
|
||||
void DrawScanline(int pixels, int left, int top, const GSVertexSW& scan);
|
||||
void DrawEdge(int pixels, int left, int top, const GSVertexSW& scan);
|
||||
void DrawRect(const GSVector4i& r, const GSVertexSW& v);
|
||||
|
|
|
@ -27,6 +27,11 @@
|
|||
|
||||
using namespace Xbyak;
|
||||
|
||||
static const int _args = 0;
|
||||
static const int _vertex = _args + 4;
|
||||
static const int _index = _args + 8;
|
||||
static const int _dscan = _args + 12;
|
||||
|
||||
GPUSetupPrimCodeGenerator::GPUSetupPrimCodeGenerator(void* param, uint32 key, void* code, size_t maxsize)
|
||||
: GSCodeGenerator(code, maxsize)
|
||||
, m_local(*(GPUScanlineLocalData*)param)
|
||||
|
@ -50,7 +55,12 @@ void GPUSetupPrimCodeGenerator::Generate()
|
|||
{
|
||||
// t = (GSVector4i(vertices[1].t) >> 8) - GSVector4i::x00000001();
|
||||
|
||||
cvttps2dq(xmm1, ptr[ecx + sizeof(GSVertexSW) * 1 + offsetof(GSVertexSW, t)]);
|
||||
mov(ecx, ptr[esp + _index]);
|
||||
mov(ecx, ptr[ecx + sizeof(uint32) * 1]);
|
||||
shl(ecx, 6); // * sizeof(GSVertexSW)
|
||||
add(ecx, ptr[esp + _vertex]);
|
||||
|
||||
cvttps2dq(xmm1, ptr[ecx + offsetof(GSVertexSW, t)]);
|
||||
psrld(xmm1, 8);
|
||||
psrld(xmm0, 31);
|
||||
psubd(xmm1, xmm0);
|
||||
|
@ -86,6 +96,8 @@ void GPUSetupPrimCodeGenerator::Generate()
|
|||
|
||||
if(m_sel.tme || m_sel.iip && m_sel.tfx != 3)
|
||||
{
|
||||
mov(edx, dword[esp + _dscan]);
|
||||
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
movaps(Xmm(5 + i), ptr[&m_shift[i]]);
|
||||
|
|
|
@ -104,7 +104,7 @@ void GSDrawScanline::EndDraw(uint64 frame, uint64 ticks, int pixels)
|
|||
|
||||
// FIXME: something's not right with the sky in burnout 3
|
||||
|
||||
void GSDrawScanline::SetupPrim(const GSVertexSW& vertex, const GSVertexSW& dscan)
|
||||
void GSDrawScanline::SetupPrim(const GSVertexSW* vertex, const uint32* index, const GSVertexSW& dscan)
|
||||
{
|
||||
GSScanlineSelector sel = m_global.sel;
|
||||
|
||||
|
@ -147,12 +147,12 @@ void GSDrawScanline::SetupPrim(const GSVertexSW& vertex, const GSVertexSW& dscan
|
|||
{
|
||||
if(has_f)
|
||||
{
|
||||
m_local.p.f = GSVector4i(vertex.p).zzzzh().zzzz();
|
||||
m_local.p.f = GSVector4i(vertex[index[1]].p).zzzzh().zzzz();
|
||||
}
|
||||
|
||||
if(has_z)
|
||||
{
|
||||
m_local.p.z = vertex.t.u32[3]; // uint32 z is bypassed in t.w
|
||||
m_local.p.z = vertex[index[1]].t.u32[3]; // uint32 z is bypassed in t.w
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -236,7 +236,17 @@ void GSDrawScanline::SetupPrim(const GSVertexSW& vertex, const GSVertexSW& dscan
|
|||
}
|
||||
else
|
||||
{
|
||||
GSVector4i c = GSVector4i(vertex.c);
|
||||
int last = 0;
|
||||
|
||||
switch(sel.prim)
|
||||
{
|
||||
case GS_POINT_CLASS: last = 0; break;
|
||||
case GS_LINE_CLASS: last = 1; break;
|
||||
case GS_TRIANGLE_CLASS: last = 2; break;
|
||||
case GS_SPRITE_CLASS: last = 1; break;
|
||||
}
|
||||
|
||||
GSVector4i c = GSVector4i(vertex[index[last]].c);
|
||||
|
||||
c = c.upl16(c.zwxy());
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ public:
|
|||
|
||||
#ifndef ENABLE_JIT_RASTERIZER
|
||||
|
||||
void SetupPrim(const GSVertexSW& vertex, const GSVertexSW& dscan);
|
||||
void SetupPrim(const GSVertexSW* vertex, const uint32* index, const GSVertexSW& dscan);
|
||||
void DrawScanline(int pixels, int left, int top, const GSVertexSW& scan);
|
||||
void DrawEdge(int pixels, int left, int top, const GSVertexSW& scan);
|
||||
|
||||
|
|
|
@ -41,12 +41,11 @@ public:
|
|||
GIFRegFRAME FRAME;
|
||||
GIFRegZBUF ZBUF;
|
||||
|
||||
__aligned(struct, 32)
|
||||
struct
|
||||
{
|
||||
GSVector4i dx10;
|
||||
GSVector4 dx9;
|
||||
GSVector4 in;
|
||||
GSVector4 ex;
|
||||
GSVector4 ofex;
|
||||
uint32 ofxy;
|
||||
} scissor;
|
||||
|
||||
struct
|
||||
|
@ -83,25 +82,22 @@ public:
|
|||
|
||||
void UpdateScissor()
|
||||
{
|
||||
scissor.dx10 = GSVector4i(
|
||||
scissor.ofex = GSVector4(
|
||||
(int)((SCISSOR.SCAX0 << 4) + XYOFFSET.OFX),
|
||||
(int)((SCISSOR.SCAY0 << 4) + XYOFFSET.OFY),
|
||||
(int)((SCISSOR.SCAX1 << 4) + XYOFFSET.OFX),
|
||||
(int)((SCISSOR.SCAY1 << 4) + XYOFFSET.OFY));
|
||||
|
||||
scissor.dx9 = GSVector4(scissor.dx10);
|
||||
|
||||
scissor.in = GSVector4(
|
||||
(int)SCISSOR.SCAX0,
|
||||
(int)SCISSOR.SCAY0,
|
||||
(int)SCISSOR.SCAX1 + 1,
|
||||
(int)SCISSOR.SCAY1 + 1);
|
||||
|
||||
scissor.ex = GSVector4(
|
||||
(int)SCISSOR.SCAX0,
|
||||
(int)SCISSOR.SCAY0,
|
||||
(int)SCISSOR.SCAX1,
|
||||
(int)SCISSOR.SCAY1);
|
||||
uint16 ofx = (uint16)XYOFFSET.OFX - 15;
|
||||
uint16 ofy = (uint16)XYOFFSET.OFY - 15;
|
||||
|
||||
scissor.ofxy = ((ofy << 16) | ofx); // ceil(xy) => (xy - offset + 15) >> 4 => (xy - [offset - 15]) >> 4
|
||||
}
|
||||
|
||||
bool DepthRead() const
|
||||
|
|
|
@ -210,21 +210,47 @@ void GSRasterizer::Draw(GSRasterizerData* data)
|
|||
template<bool scissor_test>
|
||||
void GSRasterizer::DrawPoint(const GSVertexSW* vertex, int vertex_count, const uint32* index, int index_count)
|
||||
{
|
||||
for(int i = 0, count = index != NULL ? index_count : vertex_count; i < count; i++)
|
||||
if(index != NULL)
|
||||
{
|
||||
const GSVertexSW& v = vertex[index != NULL ? index[i] : i];
|
||||
|
||||
GSVector4i p(v.p);
|
||||
|
||||
if(!scissor_test || m_scissor.left <= p.x && p.x < m_scissor.right && m_scissor.top <= p.y && p.y < m_scissor.bottom)
|
||||
for(int i = 0; i < index_count; i++, index++)
|
||||
{
|
||||
if(IsOneOfMyScanlines(p.y))
|
||||
const GSVertexSW& v = vertex[*index];
|
||||
|
||||
GSVector4i p(v.p);
|
||||
|
||||
if(!scissor_test || m_scissor.left <= p.x && p.x < m_scissor.right && m_scissor.top <= p.y && p.y < m_scissor.bottom)
|
||||
{
|
||||
m_pixels++;
|
||||
if(IsOneOfMyScanlines(p.y))
|
||||
{
|
||||
m_pixels++;
|
||||
|
||||
m_ds->SetupPrim(v, v);
|
||||
m_ds->SetupPrim(vertex, index, GSVertexSW::zero());
|
||||
|
||||
m_ds->DrawScanline(1, p.x, p.y, v);
|
||||
m_ds->DrawScanline(1, p.x, p.y, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 tmp_index[1] = {0};
|
||||
|
||||
for(int i = 0; i < vertex_count; i++, vertex++)
|
||||
{
|
||||
const GSVertexSW& v = vertex[0];
|
||||
|
||||
GSVector4i p(v.p);
|
||||
|
||||
if(!scissor_test || m_scissor.left <= p.x && p.x < m_scissor.right && m_scissor.top <= p.y && p.y < m_scissor.bottom)
|
||||
{
|
||||
if(IsOneOfMyScanlines(p.y))
|
||||
{
|
||||
m_pixels++;
|
||||
|
||||
m_ds->SetupPrim(vertex, tmp_index, GSVertexSW::zero());
|
||||
|
||||
m_ds->DrawScanline(1, p.x, p.y, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -246,7 +272,7 @@ void GSRasterizer::DrawLine(const GSVertexSW* vertex, const uint32* index)
|
|||
DrawEdge(v0, v1, dv, i, 0);
|
||||
DrawEdge(v0, v1, dv, i, 1);
|
||||
|
||||
Flush(v1, GSVertexSW::zero(), true);
|
||||
Flush(vertex, index, GSVertexSW::zero(), true);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -289,7 +315,7 @@ void GSRasterizer::DrawLine(const GSVertexSW* vertex, const uint32* index)
|
|||
|
||||
scan += dscan * (l - scan.p).xxxx();
|
||||
|
||||
m_ds->SetupPrim(v1, dscan);
|
||||
m_ds->SetupPrim(vertex, index, dscan);
|
||||
|
||||
m_ds->DrawScanline(pixels, left, p.y, scan);
|
||||
}
|
||||
|
@ -329,7 +355,7 @@ void GSRasterizer::DrawLine(const GSVertexSW* vertex, const uint32* index)
|
|||
|
||||
m_edge.count = e - m_edge.buff;
|
||||
|
||||
Flush(v1, GSVertexSW::zero());
|
||||
Flush(vertex, index, GSVertexSW::zero());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -472,7 +498,7 @@ void GSRasterizer::DrawTriangle(const GSVertexSW* vertex, const uint32* index)
|
|||
}
|
||||
}
|
||||
|
||||
Flush(vertex[index[2]], dscan);
|
||||
Flush(vertex, index, dscan);
|
||||
|
||||
if(m_ds->HasEdge())
|
||||
{
|
||||
|
@ -487,7 +513,7 @@ void GSRasterizer::DrawTriangle(const GSVertexSW* vertex, const uint32* index)
|
|||
DrawEdge(v0, v2, dv[1], orientation & 2, side & 2);
|
||||
DrawEdge(v1, v2, dv[2], orientation & 4, side & 4);
|
||||
|
||||
Flush(vertex[index[2]], GSVertexSW::zero(), true);
|
||||
Flush(vertex, index, GSVertexSW::zero(), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -609,7 +635,7 @@ void GSRasterizer::DrawSprite(const GSVertexSW* vertex, const uint32* index, boo
|
|||
if((m & 2) == 0) scan.t += dedge.t * prestep.yyyy();
|
||||
if((m & 1) == 0) scan.t += dscan.t * prestep.xxxx();
|
||||
|
||||
m_ds->SetupPrim(v1, dscan);
|
||||
m_ds->SetupPrim(vertex, index, dscan);
|
||||
|
||||
while(1)
|
||||
{
|
||||
|
@ -826,7 +852,7 @@ void GSRasterizer::AddScanline(GSVertexSW* e, int pixels, int left, int top, con
|
|||
e->p.i16[2] = (int16)top;
|
||||
}
|
||||
|
||||
void GSRasterizer::Flush(const GSVertexSW& vertex, const GSVertexSW& dscan, bool edge)
|
||||
void GSRasterizer::Flush(const GSVertexSW* vertex, const uint32* index, const GSVertexSW& dscan, bool edge)
|
||||
{
|
||||
// TODO: on win64 this could be the place where xmm6-15 are preserved (not by each DrawScanline)
|
||||
|
||||
|
@ -834,7 +860,7 @@ void GSRasterizer::Flush(const GSVertexSW& vertex, const GSVertexSW& dscan, bool
|
|||
|
||||
if(count > 0)
|
||||
{
|
||||
m_ds->SetupPrim(vertex, dscan);
|
||||
m_ds->SetupPrim(vertex, index, dscan);
|
||||
|
||||
const GSVertexSW* RESTRICT e = m_edge.buff;
|
||||
const GSVertexSW* RESTRICT ee = e + count;
|
||||
|
|
|
@ -67,7 +67,7 @@ public:
|
|||
class IDrawScanline : public GSAlignedClass<32>
|
||||
{
|
||||
public:
|
||||
typedef void (__fastcall *SetupPrimPtr)(const GSVertexSW& vertex, const GSVertexSW& dscan);
|
||||
typedef void (*SetupPrimPtr)(const GSVertexSW* vertex, const uint32* index, const GSVertexSW& dscan);
|
||||
typedef void (__fastcall *DrawScanlinePtr)(int pixels, int left, int top, const GSVertexSW& scan);
|
||||
typedef void (IDrawScanline::*DrawRectPtr)(const GSVector4i& r, const GSVertexSW& v); // TODO: jit
|
||||
|
||||
|
@ -86,14 +86,14 @@ public:
|
|||
|
||||
#ifdef ENABLE_JIT_RASTERIZER
|
||||
|
||||
__forceinline void SetupPrim(const GSVertexSW& vertex, const GSVertexSW& dscan) {m_sp(vertex, dscan);}
|
||||
__forceinline void SetupPrim(const GSVertexSW* vertex, const uint32* index, const GSVertexSW& dscan) {m_sp(vertex, index, dscan);}
|
||||
__forceinline void DrawScanline(int pixels, int left, int top, const GSVertexSW& scan) {m_ds(pixels, left, top, scan);}
|
||||
__forceinline void DrawEdge(int pixels, int left, int top, const GSVertexSW& scan) {m_de(pixels, left, top, scan);}
|
||||
__forceinline void DrawRect(const GSVector4i& r, const GSVertexSW& v) {(this->*m_dr)(r, v);}
|
||||
|
||||
#else
|
||||
|
||||
virtual void SetupPrim(const GSVertexSW& vertex, const GSVertexSW& dscan) = 0;
|
||||
virtual void SetupPrim(const GSVertexSW* vertex, const uint32* index, const GSVertexSW& dscan) = 0;
|
||||
virtual void DrawScanline(int pixels, int left, int top, const GSVertexSW& scan) = 0;
|
||||
virtual void DrawEdge(int pixels, int left, int top, const GSVertexSW& scan) = 0;
|
||||
virtual void DrawRect(const GSVector4i& r, const GSVertexSW& v) = 0;
|
||||
|
@ -140,7 +140,7 @@ protected:
|
|||
void DrawEdge(const GSVertexSW& v0, const GSVertexSW& v1, const GSVertexSW& dv, int orientation, int side);
|
||||
|
||||
__forceinline void AddScanline(GSVertexSW* e, int pixels, int left, int top, const GSVertexSW& scan);
|
||||
__forceinline void Flush(const GSVertexSW& vertex, const GSVertexSW& dscan, bool edge = false);
|
||||
__forceinline void Flush(const GSVertexSW* vertex, const uint32* index, const GSVertexSW& dscan, bool edge = false);
|
||||
|
||||
public:
|
||||
GSRasterizer(IDrawScanline* ds, int id, int threads, GSPerfMon* perfmon);
|
||||
|
|
|
@ -206,8 +206,6 @@ void GSRendererSW::Draw()
|
|||
|
||||
if(!GetScanlineGlobalData(sd)) return;
|
||||
|
||||
//
|
||||
|
||||
data->primclass = m_vt->m_primclass;
|
||||
data->buff = (uint8*)_aligned_malloc(sizeof(GSVertexSW) * m_vertex.next + sizeof(uint32) * m_index.tail, 32);
|
||||
data->vertex = (GSVertexSW*)data->buff;
|
||||
|
@ -218,6 +216,11 @@ void GSRendererSW::Draw()
|
|||
memcpy(data->vertex, m_vertex.buff, sizeof(GSVertexSW) * m_vertex.next);
|
||||
memcpy(data->index, m_index.buff, sizeof(uint32) * m_index.tail);
|
||||
|
||||
for(size_t i = 0; i < m_index.tail; i++)
|
||||
{
|
||||
ASSERT(((GSVertexSW*)m_vertex.buff + m_index.buff[i])->_pad.u32[0] == 0x12345678);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
const GSDrawingContext* context = m_context;
|
||||
|
|
|
@ -27,10 +27,17 @@
|
|||
|
||||
using namespace Xbyak;
|
||||
|
||||
static const int _args = 0;
|
||||
static const int _vertex = _args + 4;
|
||||
static const int _index = _args + 8;
|
||||
static const int _dscan = _args + 12;
|
||||
|
||||
void GSSetupPrimCodeGenerator::Generate()
|
||||
{
|
||||
if((m_en.z || m_en.f) && m_sel.prim != GS_SPRITE_CLASS || m_en.t || m_en.c && m_sel.iip)
|
||||
{
|
||||
mov(edx, dword[esp + _dscan]);
|
||||
|
||||
for(int i = 0; i < 5; i++)
|
||||
{
|
||||
vmovaps(Xmm(3 + i), ptr[&m_shift[i]]);
|
||||
|
@ -107,7 +114,12 @@ void GSSetupPrimCodeGenerator::Depth()
|
|||
}
|
||||
else
|
||||
{
|
||||
// GSVector4 p = vertex.p;
|
||||
// GSVector4 p = vertex[index[1]].p;
|
||||
|
||||
mov(ecx, ptr[esp + _index]);
|
||||
mov(ecx, ptr[ecx + sizeof(uint32) * 1]);
|
||||
shl(ecx, 6); // * sizeof(GSVertexSW)
|
||||
add(ecx, ptr[esp + _vertex]);
|
||||
|
||||
vmovaps(xmm0, ptr[ecx + offsetof(GSVertexSW, p)]);
|
||||
|
||||
|
@ -312,7 +324,25 @@ void GSSetupPrimCodeGenerator::Color()
|
|||
}
|
||||
else
|
||||
{
|
||||
// GSVector4i c = GSVector4i(vertex.c);
|
||||
// GSVector4i c = GSVector4i(vertex[index[last].c);
|
||||
|
||||
int last = 0;
|
||||
|
||||
switch(m_sel.prim)
|
||||
{
|
||||
case GS_POINT_CLASS: last = 0; break;
|
||||
case GS_LINE_CLASS: last = 1; break;
|
||||
case GS_TRIANGLE_CLASS: last = 2; break;
|
||||
case GS_SPRITE_CLASS: last = 1; break;
|
||||
}
|
||||
|
||||
if(!(m_sel.prim == GS_SPRITE_CLASS && (m_en.z || m_en.f))) // if this is a sprite, the last vertex was already loaded in Depth()
|
||||
{
|
||||
mov(ecx, ptr[esp + _index]);
|
||||
mov(ecx, ptr[ecx + sizeof(uint32) * last]);
|
||||
shl(ecx, 6); // * sizeof(GSVertexSW)
|
||||
add(ecx, ptr[esp + _vertex]);
|
||||
}
|
||||
|
||||
vcvttps2dq(xmm0, ptr[ecx + offsetof(GSVertexSW, c)]);
|
||||
|
||||
|
|
|
@ -27,10 +27,17 @@
|
|||
|
||||
using namespace Xbyak;
|
||||
|
||||
static const int _args = 0;
|
||||
static const int _vertex = _args + 4;
|
||||
static const int _index = _args + 8;
|
||||
static const int _dscan = _args + 12;
|
||||
|
||||
void GSSetupPrimCodeGenerator::Generate()
|
||||
{
|
||||
if((m_en.z || m_en.f) && m_sel.prim != GS_SPRITE_CLASS || m_en.t || m_en.c && m_sel.iip)
|
||||
{
|
||||
mov(edx, dword[esp + _dscan]);
|
||||
|
||||
for(int i = 0; i < 5; i++)
|
||||
{
|
||||
movaps(Xmm(3 + i), ptr[&m_shift[i]]);
|
||||
|
@ -112,7 +119,12 @@ void GSSetupPrimCodeGenerator::Depth()
|
|||
}
|
||||
else
|
||||
{
|
||||
// GSVector4 p = vertex.p;
|
||||
// GSVector4 p = vertex[index[1]].p;
|
||||
|
||||
mov(ecx, ptr[esp + _index]);
|
||||
mov(ecx, ptr[ecx + sizeof(uint32) * 1]);
|
||||
shl(ecx, 6); // * sizeof(GSVertexSW)
|
||||
add(ecx, ptr[esp + _vertex]);
|
||||
|
||||
movaps(xmm0, ptr[ecx + offsetof(GSVertexSW, p)]);
|
||||
|
||||
|
@ -327,7 +339,25 @@ void GSSetupPrimCodeGenerator::Color()
|
|||
}
|
||||
else
|
||||
{
|
||||
// GSVector4i c = GSVector4i(vertex.c);
|
||||
// GSVector4i c = GSVector4i(vertex[index[last].c);
|
||||
|
||||
int last = 0;
|
||||
|
||||
switch(m_sel.prim)
|
||||
{
|
||||
case GS_POINT_CLASS: last = 0; break;
|
||||
case GS_LINE_CLASS: last = 1; break;
|
||||
case GS_TRIANGLE_CLASS: last = 2; break;
|
||||
case GS_SPRITE_CLASS: last = 1; break;
|
||||
}
|
||||
|
||||
if(!(m_sel.prim == GS_SPRITE_CLASS && (m_en.z || m_en.f))) // if this is a sprite, the last vertex was already loaded in Depth()
|
||||
{
|
||||
mov(ecx, ptr[esp + _index]);
|
||||
mov(ecx, ptr[ecx + sizeof(uint32) * last]);
|
||||
shl(ecx, 6); // * sizeof(GSVertexSW)
|
||||
add(ecx, ptr[esp + _vertex]);
|
||||
}
|
||||
|
||||
cvttps2dq(xmm0, ptr[ecx + offsetof(GSVertexSW, c)]);
|
||||
|
||||
|
|
|
@ -499,13 +499,6 @@ void GSState::GIFPackedRegHandlerUV(const GIFPackedReg* RESTRICT r)
|
|||
template<uint32 prim, uint32 adc>
|
||||
void GSState::GIFPackedRegHandlerXYZF2(const GIFPackedReg* RESTRICT r)
|
||||
{
|
||||
if(adc)
|
||||
{
|
||||
// not sure what the difference is between this and XYZF2 with ADC bit set
|
||||
|
||||
//printf("XYZF3 X %d Y %d Z %d F %d ADC %d\n", r->XYZF2.X, r->XYZF2.Y, r->XYZF2.Z, r->XYZF2.F, r->XYZF2.ADC);
|
||||
}
|
||||
|
||||
/*
|
||||
m_v.XYZ.X = r->XYZF2.X;
|
||||
m_v.XYZ.Y = r->XYZF2.Y;
|
||||
|
@ -525,12 +518,6 @@ void GSState::GIFPackedRegHandlerXYZF2(const GIFPackedReg* RESTRICT r)
|
|||
template<uint32 prim, uint32 adc>
|
||||
void GSState::GIFPackedRegHandlerXYZ2(const GIFPackedReg* RESTRICT r)
|
||||
{
|
||||
if(adc)
|
||||
{
|
||||
// not sure what the difference is between this and XYZ2 with ADC bit set
|
||||
|
||||
//printf("XYZ3 X %d Y %d Z %d ADC %d\n", r->XYZ2.X, r->XYZ2.Y, r->XYZ2.Z, r->XYZ2.ADC);
|
||||
}
|
||||
/*
|
||||
m_v.XYZ.X = r->XYZ2.X;
|
||||
m_v.XYZ.Y = r->XYZ2.Y;
|
||||
|
@ -585,12 +572,17 @@ __forceinline void GSState::ApplyPRIM(const GIFRegPRIM& prim)
|
|||
m_env.PRIM = (GSVector4i)prim;
|
||||
m_env.PRMODE._PRIM = prim.PRIM;
|
||||
|
||||
m_context = &m_env.CTXT[PRIM->CTXT];
|
||||
UpdateContext();
|
||||
|
||||
UpdateVertexKick();
|
||||
|
||||
ASSERT(m_index.tail == 0 || m_index.buff[m_index.tail - 1] + 1 == m_vertex.next);
|
||||
|
||||
if(m_index.tail == 0)
|
||||
{
|
||||
m_vertex.next = 0;
|
||||
}
|
||||
|
||||
m_vertex.head = m_vertex.tail = m_vertex.next; // remove unused vertices from the end of the vertex buffer
|
||||
}
|
||||
|
||||
|
@ -821,6 +813,8 @@ template<int i> void GSState::GIFRegHandlerXYOFFSET(const GIFReg* RESTRICT r)
|
|||
m_env.CTXT[i].XYOFFSET = o;
|
||||
|
||||
m_env.CTXT[i].UpdateScissor();
|
||||
|
||||
UpdateScissor();
|
||||
}
|
||||
|
||||
void GSState::GIFRegHandlerPRMODECONT(const GIFReg* RESTRICT r)
|
||||
|
@ -836,7 +830,7 @@ void GSState::GIFRegHandlerPRMODECONT(const GIFReg* RESTRICT r)
|
|||
|
||||
// if(PRIM->PRIM == 7) printf("Invalid PRMODECONT/PRIM\n");
|
||||
|
||||
m_context = &m_env.CTXT[PRIM->CTXT];
|
||||
UpdateContext();
|
||||
|
||||
UpdateVertexKick();
|
||||
}
|
||||
|
@ -852,7 +846,7 @@ void GSState::GIFRegHandlerPRMODE(const GIFReg* RESTRICT r)
|
|||
m_env.PRMODE = (GSVector4i)r->PRMODE;
|
||||
m_env.PRMODE._PRIM = _PRIM;
|
||||
|
||||
m_context = &m_env.CTXT[PRIM->CTXT];
|
||||
UpdateContext();
|
||||
|
||||
UpdateVertexKick();
|
||||
}
|
||||
|
@ -932,6 +926,8 @@ template<int i> void GSState::GIFRegHandlerSCISSOR(const GIFReg* RESTRICT r)
|
|||
m_env.CTXT[i].SCISSOR = (GSVector4i)r->SCISSOR;
|
||||
|
||||
m_env.CTXT[i].UpdateScissor();
|
||||
|
||||
UpdateScissor();
|
||||
}
|
||||
|
||||
template<int i> void GSState::GIFRegHandlerALPHA(const GIFReg* RESTRICT r)
|
||||
|
@ -1268,14 +1264,20 @@ void GSState::FlushPrim()
|
|||
size_t stride = m_vertex.stride;
|
||||
size_t head = m_vertex.head;
|
||||
size_t tail = m_vertex.tail;
|
||||
|
||||
size_t next = m_vertex.next;
|
||||
|
||||
if(tail > head)
|
||||
{
|
||||
switch(PRIM->PRIM)
|
||||
{
|
||||
case GS_POINTLIST:
|
||||
break;
|
||||
case GS_LINELIST:
|
||||
case GS_LINESTRIP:
|
||||
case GS_SPRITE:
|
||||
if(tail > head + 0) memcpy(&buff[stride * 0], &m_vertex.buff[stride * (head + 0)], stride);
|
||||
break;
|
||||
case GS_TRIANGLELIST:
|
||||
case GS_TRIANGLESTRIP:
|
||||
if(tail > head + 0) memcpy(&buff[stride * 0], &m_vertex.buff[stride * (head + 0)], stride);
|
||||
if(tail > head + 1) memcpy(&buff[stride * 1], &m_vertex.buff[stride * (head + 1)], stride);
|
||||
|
@ -1284,10 +1286,6 @@ void GSState::FlushPrim()
|
|||
if(tail > head + 0) memcpy(&buff[stride * 0], &m_vertex.buff[stride * (head + 0)], stride);
|
||||
if(tail > head + 1) memcpy(&buff[stride * 1], &m_vertex.buff[stride * (tail - 1)], stride);
|
||||
break;
|
||||
case GS_POINTLIST:
|
||||
case GS_LINELIST:
|
||||
case GS_TRIANGLELIST:
|
||||
case GS_SPRITE:
|
||||
case GS_INVALID:
|
||||
break;
|
||||
default:
|
||||
|
@ -1307,40 +1305,37 @@ void GSState::FlushPrim()
|
|||
m_perfmon.Put(GSPerfMon::Prim, m_index.tail / GSUtil::GetVertexCount(PRIM->PRIM));
|
||||
}
|
||||
|
||||
m_index.tail = 0;
|
||||
|
||||
m_vertex.head = 0;
|
||||
m_vertex.tail = 0;
|
||||
m_vertex.next = 0;
|
||||
|
||||
if(tail > head)
|
||||
{
|
||||
switch(PRIM->PRIM)
|
||||
{
|
||||
case GS_POINTLIST:
|
||||
break;
|
||||
case GS_LINELIST:
|
||||
case GS_LINESTRIP:
|
||||
case GS_SPRITE:
|
||||
if(tail > head + 0) {memcpy(&m_vertex.buff[stride * 0], &buff[stride * 0], stride); m_vertex.tail++;}
|
||||
break;
|
||||
case GS_TRIANGLELIST:
|
||||
case GS_TRIANGLESTRIP:
|
||||
case GS_TRIANGLEFAN:
|
||||
if(tail > head + 0) {memcpy(&m_vertex.buff[stride * 0], &buff[stride * 0], stride); m_vertex.tail++;}
|
||||
if(tail > head + 1) {memcpy(&m_vertex.buff[stride * 1], &buff[stride * 1], stride); m_vertex.tail++;}
|
||||
break;
|
||||
case GS_POINTLIST:
|
||||
case GS_LINELIST:
|
||||
case GS_TRIANGLELIST:
|
||||
case GS_SPRITE:
|
||||
case GS_INVALID:
|
||||
break;
|
||||
default:
|
||||
__assume(0);
|
||||
}
|
||||
}
|
||||
|
||||
m_vertex.next = m_vertex.tail;
|
||||
m_index.tail = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vertex.head = 0;
|
||||
m_vertex.tail = 0;
|
||||
m_vertex.next = 0;
|
||||
m_vertex.next = next > head ? next - head : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2064,7 +2059,7 @@ int GSState::Defrost(const GSFreezeData* fd)
|
|||
|
||||
PRIM = !m_env.PRMODECONT.AC ? (GIFRegPRIM*)&m_env.PRMODE : &m_env.PRIM;
|
||||
|
||||
m_context = &m_env.CTXT[PRIM->CTXT];
|
||||
UpdateContext();
|
||||
|
||||
UpdateVertexKick();
|
||||
|
||||
|
@ -2080,6 +2075,8 @@ int GSState::Defrost(const GSFreezeData* fd)
|
|||
m_env.CTXT[i].offset.fzb = m_mem.GetPixelOffset4(m_env.CTXT[i].FRAME, m_env.CTXT[i].ZBUF);
|
||||
}
|
||||
|
||||
UpdateScissor();
|
||||
|
||||
m_perfmon.SetFrame(5000);
|
||||
|
||||
return 0;
|
||||
|
@ -2094,6 +2091,19 @@ void GSState::SetGameCRC(uint32 crc, int options)
|
|||
|
||||
//
|
||||
|
||||
void GSState::UpdateContext()
|
||||
{
|
||||
m_context = &m_env.CTXT[PRIM->CTXT];
|
||||
|
||||
UpdateScissor();
|
||||
}
|
||||
|
||||
void GSState::UpdateScissor()
|
||||
{
|
||||
m_scissor = m_context->scissor.ofex;
|
||||
m_ofxy = m_context->scissor.ofxy;
|
||||
}
|
||||
|
||||
void GSState::UpdateVertexKick()
|
||||
{
|
||||
uint32 prim = PRIM->PRIM;
|
||||
|
@ -2157,7 +2167,7 @@ __forceinline void GSState::VertexKick(uint32 skip)
|
|||
tailptr[0] = v0;
|
||||
tailptr[1] = v1;
|
||||
|
||||
m_vertex.xy[xy_tail & 3] = GSVector4(v1.upl32(v1.add16(GSVector4i::x000f()).srl16(4)).upl16());
|
||||
m_vertex.xy[xy_tail & 3] = GSVector4(v1.upl32(v1.sub16(GSVector4i::load(m_ofxy)).sra16(4)).upl16()); // zw not sign extended, only useful for eq tests
|
||||
|
||||
#ifdef _DEBUG
|
||||
memset(&tailptr[2], 0, m_vertex.stride - sizeof(GSVertex));
|
||||
|
@ -2221,9 +2231,7 @@ __forceinline void GSState::VertexKick(uint32 skip)
|
|||
break;
|
||||
}
|
||||
|
||||
GSVector4 scissor = m_context->scissor.dx9;
|
||||
|
||||
GSVector4 test = pmax < scissor | pmin > scissor.zwxy();
|
||||
GSVector4 test = pmax < m_scissor | pmin > m_scissor.zwxy();
|
||||
|
||||
switch(prim)
|
||||
{
|
||||
|
|
|
@ -131,6 +131,8 @@ protected:
|
|||
|
||||
GSVertex m_v;
|
||||
float m_q;
|
||||
GSVector4 m_scissor;
|
||||
uint32 m_ofxy;
|
||||
|
||||
struct
|
||||
{
|
||||
|
@ -168,6 +170,9 @@ protected:
|
|||
InitConvertVertex2(T, GS_SPRITE) \
|
||||
InitConvertVertex2(T, GS_INVALID) \
|
||||
|
||||
void UpdateContext();
|
||||
void UpdateScissor();
|
||||
|
||||
virtual void UpdateVertexKick();
|
||||
|
||||
void GrowVertexBuffer();
|
||||
|
|
|
@ -26,12 +26,12 @@
|
|||
|
||||
using namespace Xbyak;
|
||||
|
||||
static const int _args = 0;
|
||||
static const int _count = _args + 8; // rcx
|
||||
static const int _vertex = _args + 12; // rdx
|
||||
static const int _index = _args + 16; // r8
|
||||
static const int _min = _args + 20; // r9
|
||||
static const int _max = _args + 24; // _args + 4
|
||||
static const int _args = 4;
|
||||
static const int _count = _args + 4; // rcx
|
||||
static const int _vertex = _args + 8; // rdx
|
||||
static const int _index = _args + 12; // r8
|
||||
static const int _min = _args + 16; // r9
|
||||
static const int _max = _args + 20; // _args + 4
|
||||
|
||||
GSVertexTraceSW::CG::CG(const void* param, uint32 key, void* code, size_t maxsize)
|
||||
: GSCodeGenerator(code, maxsize)
|
||||
|
|
|
@ -26,12 +26,12 @@
|
|||
|
||||
using namespace Xbyak;
|
||||
|
||||
static const int _args = 0;
|
||||
static const int _count = _args + 8; // rcx
|
||||
static const int _vertex = _args + 12; // rdx
|
||||
static const int _index = _args + 16; // r8
|
||||
static const int _min = _args + 20; // r9
|
||||
static const int _max = _args + 24; // _args + 4
|
||||
static const int _args = 4;
|
||||
static const int _count = _args + 4; // rcx
|
||||
static const int _vertex = _args + 8; // rdx
|
||||
static const int _index = _args + 12; // r8
|
||||
static const int _min = _args + 16; // r9
|
||||
static const int _max = _args + 20; // _args + 4
|
||||
|
||||
GSVertexTraceSW::CG::CG(const void* param, uint32 key, void* code, size_t maxsize)
|
||||
: GSCodeGenerator(code, maxsize)
|
||||
|
|
Loading…
Reference in New Issue