From 510229b68b1c00110beb747f0f10f431a35e2286 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 22 Oct 2019 23:46:26 +0200 Subject: [PATCH] SoftGPU: Detect through-mode rectangles from triangle strips --- GPU/Math3D.h | 4 ++++ GPU/Software/Clipper.cpp | 2 +- GPU/Software/TransformUnit.cpp | 38 ++++++++++++++++++++++++++++++++-- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/GPU/Math3D.h b/GPU/Math3D.h index 292c63be05..ada1a6931e 100644 --- a/GPU/Math3D.h +++ b/GPU/Math3D.h @@ -625,6 +625,10 @@ public: *this = *this / f; } + bool operator ==(const Vec4 &other) const { + return x == other.x && y == other.y && z == other.z && w == other.w; + } + T Length2() const { return x*x + y*y + z*z + w*w; diff --git a/GPU/Software/Clipper.cpp b/GPU/Software/Clipper.cpp index ca04f7f97b..746896c431 100644 --- a/GPU/Software/Clipper.cpp +++ b/GPU/Software/Clipper.cpp @@ -198,7 +198,7 @@ void ProcessRect(const VertexData& v0, const VertexData& v1) // Color and depth values of second vertex are used for the whole rectangle buf[0].color0 = buf[1].color0 = buf[2].color0 = buf[3].color0; - buf[0].color1 = buf[1].color1 = buf[2].color1 = buf[3].color1; + buf[0].color1 = buf[1].color1 = buf[2].color1 = buf[3].color1; // is color1 ever used in through mode? buf[0].clippos.w = buf[1].clippos.w = buf[2].clippos.w = buf[3].clippos.w = 1.0f; buf[0].fogdepth = buf[1].fogdepth = buf[2].fogdepth = buf[3].fogdepth = 1.0f; diff --git a/GPU/Software/TransformUnit.cpp b/GPU/Software/TransformUnit.cpp index 3b0603fd79..2848ce600f 100644 --- a/GPU/Software/TransformUnit.cpp +++ b/GPU/Software/TransformUnit.cpp @@ -319,8 +319,7 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, GEPrimitiveTy VertexReader vreader(buf, vtxfmt, vertex_type); - const int max_vtcs_per_prim = 3; - static VertexData data[max_vtcs_per_prim]; + static VertexData data[4]; // Normally max verts per prim is 3, but we temporarily need 4 to detect rectangles from strips. // This is the index of the next vert in data (or higher, may need modulus.) static int data_index = 0; @@ -439,6 +438,41 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, GEPrimitiveTy // Don't draw a triangle when loading the first two vertices. int skip_count = data_index >= 2 ? 0 : 2 - data_index; + // If index count == 4, check if we can convert to a rectangle. + // This is for Darkstalkers (and should speed up many 2D games). + if (vertex_count == 4 && gstate.isModeThrough()) { + for (int vtx = 0; vtx < 4; ++vtx) { + if (indices) { + vreader.Goto(ConvertIndex(vtx) - index_lower_bound); + } + else { + vreader.Goto(vtx); + } + data[vtx] = ReadVertex(vreader); + } + + // OK, now let's look at data to detect rectangles. There are a few possibilities + // but we focus on Darkstalkers for now. + if (data[0].screenpos.x == data[1].screenpos.x && + data[0].screenpos.y == data[2].screenpos.y && + data[2].screenpos.x == data[3].screenpos.x && + data[1].screenpos.y == data[3].screenpos.y && + data[1].screenpos.y > data[0].screenpos.y && // Avoid rotation handling + data[2].screenpos.x > data[0].screenpos.x && + data[0].texturecoords.x == data[1].texturecoords.x && + data[0].texturecoords.y == data[2].texturecoords.y && + data[2].texturecoords.x == data[3].texturecoords.x && + data[1].texturecoords.y == data[3].texturecoords.y && + data[1].texturecoords.y > data[0].texturecoords.y && + data[2].texturecoords.x > data[0].texturecoords.x && + data[0].color0 == data[1].color0 && + data[1].color0 == data[2].color0 && + data[2].color0 == data[3].color0) { + // It's a rectangle! + Clipper::ProcessRect(data[0], data[3]); + } + } + for (int vtx = 0; vtx < vertex_count; ++vtx) { if (indices) { vreader.Goto(ConvertIndex(vtx) - index_lower_bound);