mirror of
https://github.com/dolphin-emu/hwtests.git
synced 2024-10-07 15:43:28 +00:00
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:
parent
c1bce96661
commit
461476112f
@ -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)
|
||||
{
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user