Fix portals not working in softpoly (#1323)

This commit is contained in:
Magnus Norddahl 2021-03-01 02:24:15 +01:00 committed by GitHub
parent c7edb9d22f
commit d6f8e80177
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 105 additions and 103 deletions

View file

@ -186,13 +186,8 @@ void PolyTriangleThreadData::SetDepthFunc(int func)
void PolyTriangleThreadData::SetDepthRange(float min, float max)
{
// The only two variants used by hwrenderer layer
if (min == 0.0f && max == 1.0f)
{
}
else if (min == 1.0f && max == 1.0f)
{
}
DepthRangeStart = min;
DepthRangeScale = max - min;
}
void PolyTriangleThreadData::SetDepthBias(float depthBiasConstantFactor, float depthBiasSlopeFactor)
@ -210,19 +205,18 @@ void PolyTriangleThreadData::SetStencil(int stencilRef, int op)
StencilTestValue = stencilRef;
if (op == SOP_Increment)
{
WriteStencil = StencilTest;
StencilWriteValue = MIN(stencilRef + 1, (int)255);
}
else if (op == SOP_Decrement)
{
WriteStencil = StencilTest;
StencilWriteValue = MAX(stencilRef - 1, (int)0);
}
else // SOP_Keep
{
WriteStencil = false;
StencilWriteValue = stencilRef;
}
WriteStencil = StencilTest && (StencilTestValue != StencilWriteValue);
}
void PolyTriangleThreadData::SetCulling(int mode)

View file

@ -174,6 +174,8 @@ public:
bool WriteDepth = true;
uint8_t StencilTestValue = 0;
uint8_t StencilWriteValue = 0;
float DepthRangeStart = 0.0f;
float DepthRangeScale = 1.0f;
void (*FragmentShader)(int x0, int x1, PolyTriangleThreadData* thread) = nullptr;
void (*WriteColorFunc)(int y, int x0, int x1, PolyTriangleThreadData* thread) = nullptr;

View file

@ -70,11 +70,13 @@ void WriteW(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangle
mposW = _mm_add_ps(mposW, mstepW);
}
posW += ssecount * stepW;
mstepW = _mm_set_ss(stepW);
for (int x = sseend; x < x1; x++)
{
w[x] = 1.0f / posW;
posW += stepW;
__m128 res = _mm_rcp_ss(mposW);
__m128 muls = _mm_mul_ss(mposW, _mm_mul_ss(res, res));
_mm_store_ss(w + x, _mm_sub_ss(_mm_add_ss(res, res), muls));
mposW = _mm_add_ss(mposW, mstepW);
}
}
#endif

View file

@ -34,19 +34,28 @@
static void WriteDepth(int y, int x0, int x1, PolyTriangleThreadData* thread)
{
size_t pitch = thread->depthstencil->Width();
float* line = thread->depthstencil->DepthValues() + pitch * y;
float* w = thread->scanline.W;
for (int x = x0; x < x1; x++)
float* line = thread->depthstencil->DepthValues() + (size_t)thread->depthstencil->Width() * y;
if (thread->DepthRangeScale != 0.0f)
{
line[x] = w[x];
float* w = thread->scanline.W;
for (int x = x0; x < x1; x++)
{
line[x] = w[x];
}
}
else // portal fills always uses DepthRangeStart = 1 and DepthRangeScale = 0
{
for (int x = x0; x < x1; x++)
{
line[x] = 65536.0f;
}
}
}
static void WriteStencil(int y, int x0, int x1, PolyTriangleThreadData* thread)
{
size_t pitch = thread->depthstencil->Width();
uint8_t* line = thread->depthstencil->StencilValues() + pitch * y;
uint8_t* line = thread->depthstencil->StencilValues() + (size_t)thread->depthstencil->Width() * y;
uint8_t value = thread->StencilWriteValue;
for (int x = x0; x < x1; x++)
{
@ -54,11 +63,16 @@ static void WriteStencil(int y, int x0, int x1, PolyTriangleThreadData* thread)
}
}
static void DrawSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread)
static void RunFragmentShader(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread)
{
WriteVaryings(y, x0, x1, args, thread);
thread->FragmentShader(x0, x1, thread);
}
static void DrawSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread)
{
if (thread->WriteColor || thread->AlphaTest)
RunFragmentShader(y, x0, x1, args, thread);
if (!thread->AlphaTest)
{
@ -92,88 +106,83 @@ static void DrawSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, Pol
}
}
template<typename OptT>
static void TestSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread)
static void NoTestSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread)
{
WriteW(y, x0, x1, args, thread);
DrawSpan(y, x0, x1, args, thread);
}
static void DepthTestSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread)
{
WriteW(y, x0, x1, args, thread);
if ((OptT::Flags & SWTRI_DepthTest) || (OptT::Flags & SWTRI_StencilTest))
float* zbufferLine = thread->depthstencil->DepthValues() + (size_t)thread->depthstencil->Width() * y;
float* w = thread->scanline.W;
float depthbias = thread->depthbias;
int x = x0;
int xend = x1;
while (x < xend)
{
size_t pitch = thread->depthstencil->Width();
int xstart = x;
uint8_t* stencilbuffer;
uint8_t* stencilLine;
uint8_t stencilTestValue;
if (OptT::Flags & SWTRI_StencilTest)
while (zbufferLine[x] >= w[x] + depthbias && x < xend)
x++;
if (x > xstart)
{
stencilbuffer = thread->depthstencil->StencilValues();
stencilLine = stencilbuffer + pitch * y;
stencilTestValue = thread->StencilTestValue;
DrawSpan(y, xstart, x, args, thread);
}
float* zbuffer;
float* zbufferLine;
float* w;
float depthbias;
if (OptT::Flags & SWTRI_DepthTest)
{
zbuffer = thread->depthstencil->DepthValues();
zbufferLine = zbuffer + pitch * y;
w = thread->scanline.W;
depthbias = thread->depthbias;
}
int x = x0;
int xend = x1;
while (x < xend)
{
int xstart = x;
if ((OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_StencilTest))
{
while (zbufferLine[x] >= w[x] + depthbias && stencilLine[x] == stencilTestValue && x < xend)
x++;
}
else if (OptT::Flags & SWTRI_DepthTest)
{
while (zbufferLine[x] >= w[x] + depthbias && x < xend)
x++;
}
else if (OptT::Flags & SWTRI_StencilTest)
{
while (stencilLine[x] == stencilTestValue && x < xend)
x++;
}
else
{
x = xend;
}
if (x > xstart)
{
DrawSpan(y, xstart, x, args, thread);
}
if ((OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_StencilTest))
{
while ((zbufferLine[x] < w[x] + depthbias || stencilLine[x] != stencilTestValue) && x < xend)
x++;
}
else if (OptT::Flags & SWTRI_DepthTest)
{
while (zbufferLine[x] < w[x] + depthbias && x < xend)
x++;
}
else if (OptT::Flags & SWTRI_StencilTest)
{
while (stencilLine[x] != stencilTestValue && x < xend)
x++;
}
}
while (zbufferLine[x] < w[x] + depthbias && x < xend)
x++;
}
else
}
static void DepthStencilTestSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread)
{
uint8_t* stencilLine = thread->depthstencil->StencilValues() + (size_t)thread->depthstencil->Width() * y;
uint8_t stencilTestValue = thread->StencilTestValue;
int x = x0;
int xend = x1;
while (x < xend)
{
DrawSpan(y, x0, x1, args, thread);
int xstart = x;
while (stencilLine[x] == stencilTestValue && x < xend)
x++;
if (x > xstart)
{
DepthTestSpan(y, xstart, x, args, thread);
}
while (stencilLine[x] != stencilTestValue && x < xend)
x++;
}
}
static void StencilTestSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread)
{
uint8_t* stencilLine = thread->depthstencil->StencilValues() + (size_t)thread->depthstencil->Width() * y;
uint8_t stencilTestValue = thread->StencilTestValue;
int x = x0;
int xend = x1;
while (x < xend)
{
int xstart = x;
while (stencilLine[x] == stencilTestValue && x < xend)
x++;
if (x > xstart)
{
WriteW(y, x0, x1, args, thread);
DrawSpan(y, xstart, x, args, thread);
}
while (stencilLine[x] != stencilTestValue && x < xend)
x++;
}
}
@ -287,8 +296,8 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs* args, PolyTriangleThreadDat
void(*ScreenTriangle::TestSpanOpts[])(int y, int x0, int x1, const TriDrawTriangleArgs* args, PolyTriangleThreadData* thread) =
{
&TestSpan<TestSpanOpt0>,
&TestSpan<TestSpanOpt1>,
&TestSpan<TestSpanOpt2>,
&TestSpan<TestSpanOpt3>
&NoTestSpan,
&DepthTestSpan,
&StencilTestSpan,
&DepthStencilTestSpan
};

View file

@ -122,8 +122,3 @@ enum SWTestSpan
SWTRI_DepthTest = 1,
SWTRI_StencilTest = 2
};
struct TestSpanOpt0 { static const int Flags = 0; };
struct TestSpanOpt1 { static const int Flags = 1; };
struct TestSpanOpt2 { static const int Flags = 2; };
struct TestSpanOpt3 { static const int Flags = 3; };