summaryrefslogtreecommitdiff
path: root/Source/Core/VideoBackends/Software/Rasterizer.cpp
diff options
context:
space:
mode:
authorPokechu22 <Pokechu022@gmail.com>2021-11-09 18:38:24 -0800
committerPokechu22 <Pokechu022@gmail.com>2022-04-16 12:34:58 -0700
commit925ceab82f874dcd9eeab5ca9520b5d6f0157ed1 (patch)
treebf3996af9d6e6dc23c2fd91939c96f3ba53a73f6 /Source/Core/VideoBackends/Software/Rasterizer.cpp
parent076392a0f65fa11b8c3475b762b8b9794057ae11 (diff)
Software: Use new scissor logic
Unlike the hardware backends, the software renderer can use multiple scissor rectangles (though this will result in extra rasterization).
Diffstat (limited to 'Source/Core/VideoBackends/Software/Rasterizer.cpp')
-rw-r--r--Source/Core/VideoBackends/Software/Rasterizer.cpp89
1 files changed, 48 insertions, 41 deletions
diff --git a/Source/Core/VideoBackends/Software/Rasterizer.cpp b/Source/Core/VideoBackends/Software/Rasterizer.cpp
index 726692138c..d23b6fc558 100644
--- a/Source/Core/VideoBackends/Software/Rasterizer.cpp
+++ b/Source/Core/VideoBackends/Software/Rasterizer.cpp
@@ -5,11 +5,16 @@
#include <algorithm>
#include <cstring>
+#include <vector>
+#include "Common/Assert.h"
#include "Common/CommonTypes.h"
+
#include "VideoBackends/Software/EfbInterface.h"
#include "VideoBackends/Software/NativeVertexFormat.h"
#include "VideoBackends/Software/Tev.h"
+#include "VideoCommon/BPFunctions.h"
+#include "VideoCommon/BPMemory.h"
#include "VideoCommon/PerfQueryBase.h"
#include "VideoCommon/Statistics.h"
#include "VideoCommon/VideoCommon.h"
@@ -23,14 +28,14 @@ static constexpr int BLOCK_SIZE = 2;
struct SlopeContext
{
SlopeContext(const OutputVertexData* v0, const OutputVertexData* v1, const OutputVertexData* v2,
- s32 x0, s32 y0)
+ s32 x0, s32 y0, s32 x_off, s32 y_off)
: x0(x0), y0(y0)
{
// adjust a little less than 0.5
const float adjust = 0.495f;
- xOff = ((float)x0 - v0->screenPosition.x) + adjust;
- yOff = ((float)y0 - v0->screenPosition.y) + adjust;
+ xOff = ((float)x0 - (v0->screenPosition.x - x_off)) + adjust;
+ yOff = ((float)y0 - (v0->screenPosition.y - y_off)) + adjust;
dx10 = v1->screenPosition.x - v0->screenPosition.x;
dx20 = v2->screenPosition.x - v0->screenPosition.x;
@@ -99,6 +104,8 @@ static Slope TexSlopes[8][3];
static Tev tev;
static RasterBlock rasterBlock;
+static std::vector<BPFunctions::ScissorRect> scissors;
+
void Init()
{
tev.Init();
@@ -108,6 +115,11 @@ void Init()
ZSlope = Slope();
}
+void ScissorChanged()
+{
+ scissors = std::move(BPFunctions::ComputeScissorRects().m_result);
+}
+
// Returns approximation of log2(f) in s28.4
// results are close enough to use for LOD
static s32 FixedLog2(float f)
@@ -302,37 +314,36 @@ static void BuildBlock(s32 blockX, s32 blockY)
}
void UpdateZSlope(const OutputVertexData* v0, const OutputVertexData* v1,
- const OutputVertexData* v2)
+ const OutputVertexData* v2, s32 x_off, s32 y_off)
{
if (!bpmem.genMode.zfreeze)
{
- const s32 X1 = iround(16.0f * v0->screenPosition[0]) - 9;
- const s32 Y1 = iround(16.0f * v0->screenPosition[1]) - 9;
- const SlopeContext ctx(v0, v1, v2, (X1 + 0xF) >> 4, (Y1 + 0xF) >> 4);
+ const s32 X1 = iround(16.0f * (v0->screenPosition.x - x_off)) - 9;
+ const s32 Y1 = iround(16.0f * (v0->screenPosition.y - y_off)) - 9;
+ const SlopeContext ctx(v0, v1, v2, (X1 + 0xF) >> 4, (Y1 + 0xF) >> 4, x_off, y_off);
ZSlope = Slope(v0->screenPosition.z, v1->screenPosition.z, v2->screenPosition.z, ctx);
}
}
-void DrawTriangleFrontFace(const OutputVertexData* v0, const OutputVertexData* v1,
- const OutputVertexData* v2)
+static void DrawTriangleFrontFace(const OutputVertexData* v0, const OutputVertexData* v1,
+ const OutputVertexData* v2,
+ const BPFunctions::ScissorRect& scissor)
{
- INCSTAT(g_stats.this_frame.num_triangles_drawn);
-
// The zslope should be updated now, even if the triangle is rejected by the scissor test, as
// zfreeze depends on it
- UpdateZSlope(v0, v1, v2);
+ UpdateZSlope(v0, v1, v2, scissor.x_off, scissor.y_off);
// adapted from http://devmaster.net/posts/6145/advanced-rasterization
// 28.4 fixed-pou32 coordinates. rounded to nearest and adjusted to match hardware output
// could also take floor and adjust -8
- const s32 Y1 = iround(16.0f * v0->screenPosition[1]) - 9;
- const s32 Y2 = iround(16.0f * v1->screenPosition[1]) - 9;
- const s32 Y3 = iround(16.0f * v2->screenPosition[1]) - 9;
+ const s32 Y1 = iround(16.0f * (v0->screenPosition.y - scissor.y_off)) - 9;
+ const s32 Y2 = iround(16.0f * (v1->screenPosition.y - scissor.y_off)) - 9;
+ const s32 Y3 = iround(16.0f * (v2->screenPosition.y - scissor.y_off)) - 9;
- const s32 X1 = iround(16.0f * v0->screenPosition[0]) - 9;
- const s32 X2 = iround(16.0f * v1->screenPosition[0]) - 9;
- const s32 X3 = iround(16.0f * v2->screenPosition[0]) - 9;
+ const s32 X1 = iround(16.0f * (v0->screenPosition.x - scissor.x_off)) - 9;
+ const s32 X2 = iround(16.0f * (v1->screenPosition.x - scissor.x_off)) - 9;
+ const s32 X3 = iround(16.0f * (v2->screenPosition.x - scissor.x_off)) - 9;
// Deltas
const s32 DX12 = X1 - X2;
@@ -359,35 +370,22 @@ void DrawTriangleFrontFace(const OutputVertexData* v0, const OutputVertexData* v
s32 maxy = (std::max(std::max(Y1, Y2), Y3) + 0xF) >> 4;
// scissor
- s32 xoff = bpmem.scissorOffset.x * 2;
- s32 yoff = bpmem.scissorOffset.y * 2;
-
- s32 scissorLeft = bpmem.scissorTL.x - xoff;
- if (scissorLeft < 0)
- scissorLeft = 0;
+ ASSERT(scissor.rect.left >= 0);
+ ASSERT(scissor.rect.right <= EFB_WIDTH);
+ ASSERT(scissor.rect.top >= 0);
+ ASSERT(scissor.rect.bottom <= EFB_HEIGHT);
- s32 scissorTop = bpmem.scissorTL.y - yoff;
- if (scissorTop < 0)
- scissorTop = 0;
-
- s32 scissorRight = bpmem.scissorBR.x - xoff + 1;
- if (scissorRight > s32(EFB_WIDTH))
- scissorRight = EFB_WIDTH;
-
- s32 scissorBottom = bpmem.scissorBR.y - yoff + 1;
- if (scissorBottom > s32(EFB_HEIGHT))
- scissorBottom = EFB_HEIGHT;
-
- minx = std::max(minx, scissorLeft);
- maxx = std::min(maxx, scissorRight);
- miny = std::max(miny, scissorTop);
- maxy = std::min(maxy, scissorBottom);
+ minx = std::max(minx, scissor.rect.left);
+ maxx = std::min(maxx, scissor.rect.right);
+ miny = std::max(miny, scissor.rect.top);
+ maxy = std::min(maxy, scissor.rect.bottom);
if (minx >= maxx || miny >= maxy)
return;
// Set up the remaining slopes
- const SlopeContext ctx(v0, v1, v2, (X1 + 0xF) >> 4, (Y1 + 0xF) >> 4);
+ const SlopeContext ctx(v0, v1, v2, (X1 + 0xF) >> 4, (Y1 + 0xF) >> 4, scissor.x_off,
+ scissor.y_off);
float w[3] = {1.0f / v0->projectedPosition.w, 1.0f / v1->projectedPosition.w,
1.0f / v2->projectedPosition.w};
@@ -504,4 +502,13 @@ void DrawTriangleFrontFace(const OutputVertexData* v0, const OutputVertexData* v
}
}
}
+
+void DrawTriangleFrontFace(const OutputVertexData* v0, const OutputVertexData* v1,
+ const OutputVertexData* v2)
+{
+ INCSTAT(g_stats.this_frame.num_triangles_drawn);
+
+ for (const auto& scissor : scissors)
+ DrawTriangleFrontFace(v0, v1, v2, scissor);
+}
} // namespace Rasterizer