Add clipping tests; Fix tev combiner test for the "op=1" case; Use a more generic set of input variables for tev combiner test.

This commit is contained in:
Tony Wasserka 2014-03-21 13:38:17 +01:00
parent c1bce96661
commit 461476112f
2 changed files with 174 additions and 16 deletions

View File

@ -11,7 +11,7 @@
#include "cgx_defaults.h"
#include "gxtest_util.h"
#define ENABLE_DEBUG_DISPLAY
//#define ENABLE_DEBUG_DISPLAY
namespace GXTest
{
@ -138,6 +138,7 @@ void DebugDisplayEfbContents()
{
#ifdef ENABLE_DEBUG_DISPLAY
CGX_DoEfbCopyXfb(0, 0, rmode->fbWidth, rmode->efbHeight, xfbHeight, frameBuffer[fb]);
CGX_WaitForGpuToFinish();
VIDEO_SetNextFramebuffer(frameBuffer[fb]);
VIDEO_Flush();
@ -302,6 +303,17 @@ void Quad::Draw()
}
}
void CopyToTestBuffer(int left_most_pixel, int top_most_pixel, int right_most_pixel, int bottom_most_pixel)
{
// TODO: Do we need to impose additional constraints on the parameters?
memset(test_buffer, 0, TEST_BUFFER_SIZE);
CGX_DoEfbCopyTex(left_most_pixel, top_most_pixel,
right_most_pixel - left_most_pixel + 1,
bottom_most_pixel - top_most_pixel + 1, 0x6 /*RGBA8*/,
false, test_buffer);
}
// TODO: Make this behave flexible with regards to the current EFB format!
Vec4<int> GetTevOutput(const GenMode& genmode, const TevStageCombiner::ColorCombiner& last_cc)
{

View File

@ -4,6 +4,7 @@
#include "Test.h"
#include <stdlib.h>
#include <string.h>
#include <wiiuse/wpad.h>
#include "cgx.h"
#include "cgx_defaults.h"
@ -43,7 +44,7 @@ int TevCombinerExpectation(int a, int b, int c, int d, int shift, int bias, int
c = c+(c>>7);
u16 lshift = (shift == 1) ? 1 : (shift == 2) ? 2 : 0;
u16 rshift = (shift == 3) ? 1 : 0;
int round_bias = (shift==3) ? 0 /*: (cc.op==1) ? -128*/ : 128; // TODO: No idea if cc.op plays any role here.. results are still different anyway
int round_bias = (shift==3) ? 0 : ((op==1) ? 127 : 128);
int expected = (((a*(256-c) + b*c) << lshift)+round_bias)>>8; // lerp
expected = (d << lshift) + expected * ((op == 1) ? (-1) : 1);
expected += ((bias == 2) ? -128 : (bias == 1) ? 128 : 0) << lshift;
@ -76,7 +77,7 @@ void TevCombinerTest()
// Test if we can extract all bits of the tev combiner output...
auto tevreg = CGXDefault<TevReg>(1, false); // c0
#if 0
#if 1
for (tevreg.red = -1024; tevreg.red != 1023; tevreg.red = tevreg.red+1)
{
CGX_LOAD_BP_REG(tevreg.low);
@ -97,7 +98,7 @@ void TevCombinerTest()
#endif
// Now: Randomized testing of tev combiners.
for (int i = 0x000000; i < 0x010000; ++i)
for (int i = 0x000000; i < 0x000F000; ++i)
{
if ((i & 0xFF00) == i)
network_printf("progress: %x\n", i);
@ -114,13 +115,13 @@ void TevCombinerTest()
cc.d = TEVCOLORARG_ZERO;// TEVCOLORARG_CPREV; // NOTE: TEVCOLORARG_CPREV doesn't actually seem to fetch its data from PREV when used in the first stage?
cc.shift = rand() % 4;
cc.bias = rand() % 3;
cc.op = 0; //rand()%2;
cc.op = rand()%2;
cc.clamp = rand() % 2;
CGX_LOAD_BP_REG(cc.hex);
int a = rand() % 255;
int b = rand() % 255;
int c = rand() % 255;
int a = -1024 + (rand() % 2048);
int b = -1024 + (rand() % 2048);
int c = -1024 + (rand() % 2048);
int d = 0; //-1024 + (rand() % 2048);
tevreg = CGXDefault<TevReg>(1, false); // c0
tevreg.red = a;
@ -175,34 +176,179 @@ void ClipTest()
genmode.numtevstages = 0; // One stage
CGX_LOAD_BP_REG(genmode.hex);
for (int i = 0; i < 200; ++i)
for (int step = 0; step < 13; ++step)
{
network_printf("step %d\n", i);
GX_SetViewport(100, 100, 50.f, 50, 0, 1);
auto zmode = CGXDefault<ZMode>();
CGX_LOAD_BP_REG(zmode.hex);
// First off, clear previous screen contents
CGX_SetViewport(0.0f, 0.0f, 201.0f, 50.0f, 0.0f, 1.0f); // stuff which really should not be filled
auto cc = CGXDefault<TevStageCombiner::ColorCombiner>(0);
cc.d = TEVCOLORARG_RASC;
CGX_LOAD_BP_REG(cc.hex);
GXTest::Quad().ColorRGBA(0,0,0,0xff).Draw();
CGX_SetViewport(75.0f, 0.0f, 100.0f, 50.0f, 0.0f, 1.0f); // guardband
cc = CGXDefault<TevStageCombiner::ColorCombiner>(0);
cc.d = TEVCOLORARG_RASC;
CGX_LOAD_BP_REG(cc.hex);
GXTest::Quad().ColorRGBA(0,0x7f,0,0xff).Draw();
CGX_SetViewport(100.0f, 0.0f, 50.0f, 50.0f, 0.0f, 1.0f); // viewport
cc = CGXDefault<TevStageCombiner::ColorCombiner>(0);
cc.d = TEVCOLORARG_RASC;
CGX_LOAD_BP_REG(cc.hex);
GXTest::Quad().ColorRGBA(0,0xff,0,0xff).Draw();
// Now, enable testing viewport and draw the (red) testing quad
CGX_SetViewport(100.0f, 0.0f, 50.0f, 50.0f, 0.0f, 1.0f);
cc.d = TEVCOLORARG_C0;
CGX_LOAD_BP_REG(cc.hex);
auto tevreg = CGXDefault<TevReg>(1, false); // c0
tevreg.red = rand()%256;
tevreg.red = 0xff;
CGX_LOAD_BP_REG(tevreg.low);
CGX_LOAD_BP_REG(tevreg.high);
CGX_BEGIN_LOAD_XF_REGS(0x1005, 1);
wgPipe->U32 = 0; // 0 = enable clipping, 1 = disable clipping
GXTest::Quad().ColorRGBA(0xff,0xff,0xff,0xff).AtDepth(1.00000001).Draw();
bool expect_quad_to_be_drawn = true;
int test_x = 125, test_y = 25; // Somewhere within the viewport
GXTest::Quad test_quad;
test_quad.ColorRGBA(0xff,0xff,0xff,0xff);
switch (step)
{
// Rendering outside the viewport when scissor rect is bigger than viewport
// TODO: What about partially covered primitives?
case 0: // all vertices within viewport
// Nothing to do
break;
case 1: // two vertices outside viewport, but within guardband
test_quad.VertexTopLeft(-1.8f, 1.0f, 1.0f).VertexBottomLeft(-1.8f, -1.0f, 1.0f);
test_x = 75; // TODO: Move closer to actual viewport, but debug readback issues first
break;
case 2: // two vertices outside viewport and guardband
test_quad.VertexTopLeft(-2.5f, 1.0f, 1.0f).VertexBottomLeft(-2.5f, -1.0f, 1.0f);
test_x = 51; // TODO: This is actually outside the guardband
// TODO: Check x=50, should be green
break;
case 3: // all vertices outside viewport, but within guardband and NOT on the same side of the viewport
test_quad.VertexTopLeft(-1.5f, 1.0f, 1.0f).VertexBottomLeft(-1.5f, -1.0f, 1.0f);
test_quad.VertexTopRight(1.5f, 1.0f, 1.0f).VertexBottomRight(1.5f, 1.0f, 1.0f);
test_x = 80; // TODO: MOve closer to actual viewport
break;
case 4: // all vertices outside viewport and guardband, but NOT on the same side of the viewport
test_quad.VertexTopLeft(-2.5f, 1.0f, 1.0f).VertexBottomLeft(-2.5f, -1.0f, 1.0f);
test_quad.VertexTopRight(2.5f, 1.0f, 1.0f).VertexBottomRight(2.5f, 1.0f, 1.0f);
test_x = 51; // TODO: This is actually outside the guardband
// TODO: Check x=50,x=200?,x=201?, 50 and 201 should be green, 200 should be red
break;
case 5: // all vertices outside viewport, but within guardband and on the same side of the viewport
test_quad.VertexTopLeft(-1.8f, 1.0f, 1.0f).VertexBottomLeft(-1.8f, -1.0f, 1.0f);
test_quad.VertexTopRight(-1.2f, 1.0f, 1.0f).VertexBottomRight(-1.2f, 1.0f, 1.0f);
test_quad.VertexTopRight(1.5f, 1.0f, 1.0f);
expect_quad_to_be_drawn = false;
break;
case 6: // guardband-clipping test
// Exceeds the guard-band clipping plane by the viewport width,
// so the primitive will get clipped such that one edge touches
// the clipping plane.exactly at the vertical viewport center.
// ASCII picture of clipped primitive (within guard-band region):
// |----- pixel row 0
// | pixel row 1
// | pixel row 2
// | pixel row 3
// | pixel row 4
// \ pixel row 5 <-- vertical viewport center
// \ pixel row 6
// \ pixel row 7
// \ pixel row 8
// \ pixel row 9
// \ pixel row 10
test_quad.VertexTopLeft(-4.0f, 1.0f, 1.0f);
test_x = 51; // TODO: This is actually outside the guardband
test_y = 1;
// TODO: Test y roughly equals 60 (there's no good way to test this without relying on pixel-perfect clipping), here should NOT be a quad!
break;
// Depth clipping tests
case 7: // Everything behind z=w plane, depth clipping enabled
case 8: // Everything behind z=w plane, depth clipping disabled
CGX_BEGIN_LOAD_XF_REGS(0x1005, 1);
wgPipe->U32 = step - 7; // 0 = enable clipping, 1 = disable clipping
test_quad.AtDepth(1.1);
expect_quad_to_be_drawn = false;
break;
case 9: // Everything in front of z=0 plane, depth clipping enabled
case 10: // Everything in front of z=0 plane, depth clipping disabled
CGX_BEGIN_LOAD_XF_REGS(0x1005, 1);
wgPipe->U32 = step - 9; // 0 = enable clipping, 1 = disable clipping
test_quad.AtDepth(-0.00001);
expect_quad_to_be_drawn = false;
break;
case 11: // Very slightly behind z=w plane, depth clipping enabled
case 12: // Very slightly behind z=w plane, depth clipping disabled
// The GC/Wii GPU doesn't implement IEEE floats strictly, hence
// the sum of the projected position's z and w is a very small
// number, which by IEEE would be non-zero but which in fact is
// treated as zero.
// In particular, the value by IEEE is -0.00000011920928955078125.
CGX_BEGIN_LOAD_XF_REGS(0x1005, 1);
wgPipe->U32 = step - 11; // 0 = enable clipping, 1 = disable clipping
test_quad.AtDepth(1.0000001);
break;
case 13: // One vertex behind z=w plane, depth clipping enabled
case 14: // One vertex behind z=w plane, depth clipping disabled
CGX_BEGIN_LOAD_XF_REGS(0x1005, 1);
wgPipe->U32 = step - 13; // 0 = enable clipping, 1 = disable clipping
test_quad.VertexTopLeft(-1.0f, 1.0f, 1.5f);
// whole primitive gets clipped away
expect_quad_to_be_drawn = false;
break;
case 15: // Three vertices with a very large value for z, depth clipping disabled
CGX_BEGIN_LOAD_XF_REGS(0x1005, 1);
wgPipe->U32 = 1; // 0 = enable clipping, 1 = disable clipping
test_quad.VertexTopLeft(-1.0f, 1.0f, 65537.f);
test_quad.VertexTopRight(1.0f, 1.0f, 65537.f);
test_quad.VertexBottomLeft(-1.0f, -1.0f, 65537.f);
break;
// TODO: One vertex with z < 0, depth clipping enabled, primitive gets properly (!) clipped
// TODO: One vertex with z < 0, depth clipping disabled, whole primitive gets drawn
}
test_quad.Draw();
GXTest::CopyToTestBuffer(0, 0, 199, 49);
CGX_WaitForGpuToFinish();
GXTest::Vec4<u8> result = GXTest::ReadTestBuffer(test_x, test_y, 200);
if (expect_quad_to_be_drawn)
DO_TEST(result.r == 0xff, "Clipping test failed at step %d (expected quad to be shown at pixel (%d, %d), but it was not)", step, test_x, test_y);
else
DO_TEST(result.r == 0x00, "Clipping test failed at step %d (expected quad to be hidden at pixel (%d, %d), but it was not)", step, test_x, test_y);
GXTest::DebugDisplayEfbContents();
}
@ -217,7 +363,7 @@ int main()
GXTest::Init();
BitfieldTest();
// TevCombinerTest();
TevCombinerTest();
ClipTest();
network_printf("Shutting down...\n");