Compare commits

...

6 Commits

Author SHA1 Message Date
Jakly
8cf78d964a
Merge 3268f94f4b into 5e8beb3ab7 2024-11-13 18:13:13 +02:00
Nadia Holmquist Pedersen
5e8beb3ab7 fix a typo
Some checks failed
macOS / ${{ matrix.arch }} (arm64) (push) Has been cancelled
macOS / ${{ matrix.arch }} (x86_64) (push) Has been cancelled
Ubuntu / x86_64 (push) Has been cancelled
Ubuntu / aarch64 (push) Has been cancelled
Windows / build (push) Has been cancelled
macOS / Universal binary (push) Has been cancelled
2024-11-13 15:23:59 +01:00
Jaklyy
3268f94f4b remove an optimization for swapped polygons
why did i optimize swapped polygons?
they're not that common.
2023-12-10 16:37:35 -05:00
Jaklyy
3facbe90c9 remove templates
seems to just make things sliiightly slower on my machine
2023-12-10 16:37:35 -05:00
Jaklyy
0c8095c1bb rewrite of aa code
should behave identically
2023-12-10 16:36:18 -05:00
Jaklyy
ed79b1772c invert coverage to fix xmajor aa
if the calculated y coordinate differs from the expected y coordinate, invert its coverage.
2023-12-10 16:36:18 -05:00
3 changed files with 49 additions and 72 deletions

View File

@ -47,7 +47,7 @@
1. Install Qt: `pacman -S <prefix>-{qt6-base,qt6-svg,qt6-multimedia,qt6-svg,qt6-tools}` 1. Install Qt: `pacman -S <prefix>-{qt6-base,qt6-svg,qt6-multimedia,qt6-svg,qt6-tools}`
2. Set up the build directory with `cmake -B build` 2. Set up the build directory with `cmake -B build`
* Static builds (without DLLs, standalone executable) * Static builds (without DLLs, standalone executable)
1. Install Qt: `pacman -S <prefi>-qt5-static` 1. Install Qt: `pacman -S <prefix>-qt5-static`
(Note: As of writing, the `qt6-static` package does not work.) (Note: As of writing, the `qt6-static` package does not work.)
2. Set up the build directory with `cmake -B build -DBUILD_STATIC=ON -DUSE_QT6=OFF -DCMAKE_PREFIX_PATH=$MSYSTEM_PREFIX/qt5-static` 2. Set up the build directory with `cmake -B build -DBUILD_STATIC=ON -DUSE_QT6=OFF -DCMAKE_PREFIX_PATH=$MSYSTEM_PREFIX/qt5-static`
7. Compile: `cmake --build build` 7. Compile: `cmake --build build`

View File

@ -774,8 +774,8 @@ void SoftRenderer::RenderShadowMaskScanline(const GPU3D& gpu3d, RendererPolygon*
interp_start = &rp->SlopeR.Interp; interp_start = &rp->SlopeR.Interp;
interp_end = &rp->SlopeL.Interp; interp_end = &rp->SlopeL.Interp;
rp->SlopeR.EdgeParams<true>(&l_edgelen, &l_edgecov); rp->SlopeR.EdgeParams(&l_edgelen, &l_edgecov, true);
rp->SlopeL.EdgeParams<true>(&r_edgelen, &r_edgecov); rp->SlopeL.EdgeParams(&r_edgelen, &r_edgecov, true);
std::swap(xstart, xend); std::swap(xstart, xend);
std::swap(wl, wr); std::swap(wl, wr);
@ -806,8 +806,8 @@ void SoftRenderer::RenderShadowMaskScanline(const GPU3D& gpu3d, RendererPolygon*
interp_start = &rp->SlopeL.Interp; interp_start = &rp->SlopeL.Interp;
interp_end = &rp->SlopeR.Interp; interp_end = &rp->SlopeR.Interp;
rp->SlopeL.EdgeParams<false>(&l_edgelen, &l_edgecov); rp->SlopeL.EdgeParams(&l_edgelen, &l_edgecov, false);
rp->SlopeR.EdgeParams<false>(&r_edgelen, &r_edgecov); rp->SlopeR.EdgeParams(&r_edgelen, &r_edgecov, false);
// CHECKME: edge fill rules for unswapped opaque shadow mask polygons // CHECKME: edge fill rules for unswapped opaque shadow mask polygons
if ((gpu3d.RenderDispCnt & ((1<<4)|(1<<5))) || ((polyalpha < 31) && (gpu3d.RenderDispCnt & (1<<3))) || wireframe) if ((gpu3d.RenderDispCnt & ((1<<4)|(1<<5))) || ((polyalpha < 31) && (gpu3d.RenderDispCnt & (1<<3))) || wireframe)
@ -1003,8 +1003,8 @@ void SoftRenderer::RenderPolygonScanline(const GPU& gpu, RendererPolygon* rp, s3
interp_start = &rp->SlopeR.Interp; interp_start = &rp->SlopeR.Interp;
interp_end = &rp->SlopeL.Interp; interp_end = &rp->SlopeL.Interp;
rp->SlopeR.EdgeParams<true>(&l_edgelen, &l_edgecov); rp->SlopeR.EdgeParams(&l_edgelen, &l_edgecov, true);
rp->SlopeL.EdgeParams<true>(&r_edgelen, &r_edgecov); rp->SlopeL.EdgeParams(&r_edgelen, &r_edgecov, true);
std::swap(xstart, xend); std::swap(xstart, xend);
std::swap(wl, wr); std::swap(wl, wr);
@ -1041,8 +1041,8 @@ void SoftRenderer::RenderPolygonScanline(const GPU& gpu, RendererPolygon* rp, s3
interp_start = &rp->SlopeL.Interp; interp_start = &rp->SlopeL.Interp;
interp_end = &rp->SlopeR.Interp; interp_end = &rp->SlopeR.Interp;
rp->SlopeL.EdgeParams<false>(&l_edgelen, &l_edgecov); rp->SlopeL.EdgeParams(&l_edgelen, &l_edgecov, false);
rp->SlopeR.EdgeParams<false>(&r_edgelen, &r_edgecov); rp->SlopeR.EdgeParams(&r_edgelen, &r_edgecov, false);
// edge fill rules for unswapped opaque edges: // edge fill rules for unswapped opaque edges:
// * right edge is filled if slope > 1 // * right edge is filled if slope > 1
@ -1096,18 +1096,11 @@ void SoftRenderer::RenderPolygonScanline(const GPU& gpu, RendererPolygon* rp, s3
if (x < 0) x = 0; if (x < 0) x = 0;
s32 xlimit; s32 xlimit;
s32 xcov = 0;
// part 1: left edge // part 1: left edge
edge = yedge | 0x1; edge = yedge | 0x1;
xlimit = xstart+l_edgelen; xlimit = xstart+l_edgelen;
if (xlimit > xend+1) xlimit = xend+1; if (xlimit > xend+1) xlimit = xend+1;
if (xlimit > 256) xlimit = 256; if (xlimit > 256) xlimit = 256;
if (l_edgecov & (1<<31))
{
xcov = (l_edgecov >> 12) & 0x3FF;
if (xcov == 0x3FF) xcov = 0;
}
if (!l_filledge) x = xlimit; if (!l_filledge) x = xlimit;
else else
@ -1166,14 +1159,12 @@ void SoftRenderer::RenderPolygonScanline(const GPU& gpu, RendererPolygon* rp, s3
// anti-aliasing: all edges are rendered // anti-aliasing: all edges are rendered
// calculate coverage // calculate coverage
s32 cov = l_edgecov; attr |= (l_edgecov >> 5) << 8;
if (cov & (1<<31)) if (x < xlimit-1)
{ {
cov = xcov >> 5; l_edgecov += rp->SlopeL.XCov_Incr;
if (cov > 31) cov = 31; if (l_edgecov > 0x3FF) l_edgecov = 0x3FF;
xcov += (l_edgecov & 0x3FF);
} }
attr |= (cov << 8);
// push old pixel down if needed // push old pixel down if needed
if (pixeladdr < BufferSize) if (pixeladdr < BufferSize)
@ -1292,11 +1283,6 @@ void SoftRenderer::RenderPolygonScanline(const GPU& gpu, RendererPolygon* rp, s3
edge = yedge | 0x2; edge = yedge | 0x2;
xlimit = xend+1; xlimit = xend+1;
if (xlimit > 256) xlimit = 256; if (xlimit > 256) xlimit = 256;
if (r_edgecov & (1<<31))
{
xcov = (r_edgecov >> 12) & 0x3FF;
if (xcov == 0x3FF) xcov = 0;
}
if (r_filledge) if (r_filledge)
for (; x < xlimit; x++) for (; x < xlimit; x++)
@ -1354,14 +1340,12 @@ void SoftRenderer::RenderPolygonScanline(const GPU& gpu, RendererPolygon* rp, s3
// anti-aliasing: all edges are rendered // anti-aliasing: all edges are rendered
// calculate coverage // calculate coverage
s32 cov = r_edgecov; attr |= (r_edgecov >> 5) << 8;
if (cov & (1<<31)) if (x < xlimit-1)
{ {
cov = 0x1F - (xcov >> 5); r_edgecov -= rp->SlopeR.XCov_Incr;
if (cov < 0) cov = 0; if (r_edgecov < 0) r_edgecov = 0;
xcov += (r_edgecov & 0x3FF);
} }
attr |= (cov << 8);
// push old pixel down if needed // push old pixel down if needed
if (pixeladdr < BufferSize) if (pixeladdr < BufferSize)

View File

@ -238,6 +238,7 @@ private:
dx = 0; dx = 0;
this->x0 = x0; this->x0 = x0;
this->y0 = y0;
this->xmin = x0; this->xmin = x0;
this->xmax = x0; this->xmax = x0;
@ -247,7 +248,7 @@ private:
Interp.Setup(0, 0, 0, 0); Interp.Setup(0, 0, 0, 0);
Interp.SetX(0); Interp.SetX(0);
xcov_incr = 0; XCov_Incr = 0;
return x0; return x0;
} }
@ -255,6 +256,7 @@ private:
constexpr s32 Setup(s32 x0, s32 x1, s32 y0, s32 y1, s32 w0, s32 w1, s32 y) constexpr s32 Setup(s32 x0, s32 x1, s32 y0, s32 y1, s32 w0, s32 w1, s32 y)
{ {
this->x0 = x0; this->x0 = x0;
this->y0 = y0;
this->y = y; this->y = y;
if (x1 > x0) if (x1 > x0)
@ -322,7 +324,7 @@ private:
Interp.SetX(y); Interp.SetX(y);
// used for calculating AA coverage // used for calculating AA coverage
if (XMajor) xcov_incr = (ylen << 10) / xlen; if (XMajor) XCov_Incr = ((ylen << 10) / xlen) & 0x3FF;
return x; return x;
} }
@ -348,18 +350,14 @@ private:
return ret; return ret;
} }
template<bool swapped> constexpr void EdgeParams_XMajor(s32* length, s32* coverage, bool swapped) const
constexpr void EdgeParams_XMajor(s32* length, s32* coverage) const
{ {
// only do length calc for right side when swapped as it's // only do length calc for right side when swapped as it's
// only needed for aa calcs, as actual line spans are broken // only needed for aa calcs, as actual line spans are broken
if constexpr (!swapped || side) if (side ^ Negative)
{ *length = (dx >> 18) - ((dx-Increment) >> 18);
if (side ^ Negative) else
*length = (dx >> 18) - ((dx-Increment) >> 18); *length = ((dx+Increment) >> 18) - (dx >> 18);
else
*length = ((dx+Increment) >> 18) - (dx >> 18);
}
// for X-major edges, we return the coverage // for X-major edges, we return the coverage
// for the first pixel, and the increment for // for the first pixel, and the increment for
@ -369,13 +367,20 @@ private:
if (side) startx = startx - *length + 1; if (side) startx = startx - *length + 1;
s32 startcov = (((startx << 10) + 0x1FF) * ylen) / xlen; s32 startcov = (((startx << 10) + 0x1FF) * ylen) / xlen;
*coverage = (1<<31) | ((startcov & 0x3FF) << 12) | (xcov_incr & 0x3FF);
if constexpr (swapped) *length = 1; // fix the y value for negative slopes
s32 ycoord = Negative ? (ylen << 10) - startcov >> 10 : startcov >> 10;
// if yvalue is not equal to actual y value, invert coverage value
startcov &= 0x3FF;
if (ycoord != y - y0) startcov = 0x3FF - startcov;
if (side ^ swapped) startcov = 0x3FF - startcov;
*coverage = startcov;
if (swapped) *length = 1;
} }
template<bool swapped> constexpr void EdgeParams_YMajor(s32* length, s32* coverage, bool swapped) const
constexpr void EdgeParams_YMajor(s32* length, s32* coverage) const
{ {
*length = 1; *length = 1;
@ -383,51 +388,39 @@ private:
{ {
// for some reason vertical edges' aa values // for some reason vertical edges' aa values
// are inverted too when the edges are swapped // are inverted too when the edges are swapped
if constexpr (swapped) *coverage = swapped ? 0 : 31 << 5;
*coverage = 0;
else
*coverage = 31;
} }
else else
{ {
s32 cov = ((dx >> 9) + (Increment >> 10)) >> 4; s32 cov = ((dx >> 9) + (Increment >> 10)) >> 4;
if ((cov >> 5) != (dx >> 18)) cov = 31; if ((cov >> 5) != (dx >> 18)) cov = 31;
cov &= 0x1F; cov &= 0x1F;
if constexpr (swapped) if (side ^ !Negative ^ swapped) cov = 0x1F - cov;
{
if (side ^ Negative) cov = 0x1F - cov;
}
else
{
if (!(side ^ Negative)) cov = 0x1F - cov;
}
*coverage = cov; // shift left 5 just to make it align with xmajor coverage values
*coverage = cov << 5;
} }
} }
template<bool swapped> constexpr void EdgeParams(s32* length, s32* coverage, bool swapped) const
constexpr void EdgeParams(s32* length, s32* coverage) const
{ {
if (XMajor) if (XMajor)
return EdgeParams_XMajor<swapped>(length, coverage); return EdgeParams_XMajor(length, coverage, swapped);
else else
return EdgeParams_YMajor<swapped>(length, coverage); return EdgeParams_YMajor(length, coverage, swapped);
} }
s32 Increment; s32 Increment;
bool Negative; bool Negative;
bool XMajor; bool XMajor;
Interpolator<1> Interp; Interpolator<1> Interp;
s32 XCov_Incr;
private: private:
s32 x0, xmin, xmax; s32 x0, y0, xmin, xmax;
s32 xlen, ylen; s32 xlen, ylen;
s32 dx; s32 dx;
s32 y; s32 y;
s32 xcov_incr;
s32 ycoverage, ycov_incr;
}; };
u32 AlphaBlend(const GPU3D& gpu3d, u32 srccolor, u32 dstcolor, u32 alpha) const noexcept; u32 AlphaBlend(const GPU3D& gpu3d, u32 srccolor, u32 dstcolor, u32 alpha) const noexcept;