mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
Reimplement Bounding Box calculation using the software renderer.
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "VideoCommon/PixelEngine.h"
|
||||
#include "VideoCommon/TextureDecoder.h"
|
||||
#include "VideoCommon/BoundingBox.h"
|
||||
#include "VideoCommon/VideoCommon.h"
|
||||
|
||||
|
||||
@@ -73,12 +74,12 @@ void SWBPWritten(int address, int newvalue)
|
||||
EfbCopy::CopyEfb();
|
||||
break;
|
||||
case BPMEM_CLEARBBOX1:
|
||||
PixelEngine::bbox[0] = newvalue >> 10;
|
||||
PixelEngine::bbox[1] = newvalue & 0x3ff;
|
||||
BoundingBox::coords[BoundingBox::LEFT] = newvalue >> 10;
|
||||
BoundingBox::coords[BoundingBox::RIGHT] = newvalue & 0x3ff;
|
||||
break;
|
||||
case BPMEM_CLEARBBOX2:
|
||||
PixelEngine::bbox[2] = newvalue >> 10;
|
||||
PixelEngine::bbox[3] = newvalue & 0x3ff;
|
||||
BoundingBox::coords[BoundingBox::TOP] = newvalue >> 10;
|
||||
BoundingBox::coords[BoundingBox::BOTTOM] = newvalue & 0x3ff;
|
||||
break;
|
||||
case BPMEM_CLEAR_PIXEL_PERF:
|
||||
// TODO: I didn't test if the value written to this register affects the amount of cleared registers
|
||||
|
||||
@@ -437,12 +437,6 @@ namespace EfbInterface
|
||||
{
|
||||
SetPixelAlphaOnly(offset, dstClrPtr[ALP_C]);
|
||||
}
|
||||
|
||||
// branchless bounding box update
|
||||
PixelEngine::bbox[0] = std::min(x, PixelEngine::bbox[0]);
|
||||
PixelEngine::bbox[1] = std::max(x, PixelEngine::bbox[1]);
|
||||
PixelEngine::bbox[2] = std::min(y, PixelEngine::bbox[2]);
|
||||
PixelEngine::bbox[3] = std::max(y, PixelEngine::bbox[3]);
|
||||
}
|
||||
|
||||
void SetColor(u16 x, u16 y, u8 *color)
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "VideoBackends/Software/SWVideoConfig.h"
|
||||
#include "VideoBackends/Software/Tev.h"
|
||||
#include "VideoBackends/Software/XFMemLoader.h"
|
||||
#include "VideoCommon/BoundingBox.h"
|
||||
|
||||
|
||||
#define BLOCK_SIZE 2
|
||||
@@ -130,7 +131,7 @@ inline void Draw(s32 x, s32 y, s32 xi, s32 yi)
|
||||
if (z < 0 || z > 0x00ffffff)
|
||||
return;
|
||||
|
||||
if (bpmem.UseEarlyDepthTest() && g_SWVideoConfig.bZComploc)
|
||||
if (!BoundingBox::active && bpmem.UseEarlyDepthTest() && g_SWVideoConfig.bZComploc)
|
||||
{
|
||||
// TODO: Test if perf regs are incremented even if test is disabled
|
||||
EfbInterface::IncPerfCounterQuadCount(PQ_ZCOMP_INPUT_ZCOMPLOC);
|
||||
@@ -317,7 +318,7 @@ void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVer
|
||||
{
|
||||
INCSTAT(swstats.thisFrame.numTrianglesDrawn);
|
||||
|
||||
if (g_SWVideoConfig.bHwRasterizer)
|
||||
if (g_SWVideoConfig.bHwRasterizer && !BoundingBox::active)
|
||||
{
|
||||
HwRasterizer::DrawTriangleFrontFace(v0, v1, v2);
|
||||
return;
|
||||
@@ -414,84 +415,254 @@ void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVer
|
||||
if (DY23 < 0 || (DY23 == 0 && DX23 > 0)) C2++;
|
||||
if (DY31 < 0 || (DY31 == 0 && DX31 > 0)) C3++;
|
||||
|
||||
// Loop through blocks
|
||||
for (s32 y = miny; y < maxy; y += BLOCK_SIZE)
|
||||
// If drawing, rasterize every block
|
||||
if (!BoundingBox::active)
|
||||
{
|
||||
for (s32 x = minx; x < maxx; x += BLOCK_SIZE)
|
||||
// Loop through blocks
|
||||
for (s32 y = miny; y < maxy; y += BLOCK_SIZE)
|
||||
{
|
||||
// Corners of block
|
||||
s32 x0 = x << 4;
|
||||
s32 x1 = (x + BLOCK_SIZE - 1) << 4;
|
||||
s32 y0 = y << 4;
|
||||
s32 y1 = (y + BLOCK_SIZE - 1) << 4;
|
||||
|
||||
// Evaluate half-space functions
|
||||
bool a00 = C1 + DX12 * y0 - DY12 * x0 > 0;
|
||||
bool a10 = C1 + DX12 * y0 - DY12 * x1 > 0;
|
||||
bool a01 = C1 + DX12 * y1 - DY12 * x0 > 0;
|
||||
bool a11 = C1 + DX12 * y1 - DY12 * x1 > 0;
|
||||
int a = (a00 << 0) | (a10 << 1) | (a01 << 2) | (a11 << 3);
|
||||
|
||||
bool b00 = C2 + DX23 * y0 - DY23 * x0 > 0;
|
||||
bool b10 = C2 + DX23 * y0 - DY23 * x1 > 0;
|
||||
bool b01 = C2 + DX23 * y1 - DY23 * x0 > 0;
|
||||
bool b11 = C2 + DX23 * y1 - DY23 * x1 > 0;
|
||||
int b = (b00 << 0) | (b10 << 1) | (b01 << 2) | (b11 << 3);
|
||||
|
||||
bool c00 = C3 + DX31 * y0 - DY31 * x0 > 0;
|
||||
bool c10 = C3 + DX31 * y0 - DY31 * x1 > 0;
|
||||
bool c01 = C3 + DX31 * y1 - DY31 * x0 > 0;
|
||||
bool c11 = C3 + DX31 * y1 - DY31 * x1 > 0;
|
||||
int c = (c00 << 0) | (c10 << 1) | (c01 << 2) | (c11 << 3);
|
||||
|
||||
// Skip block when outside an edge
|
||||
if (a == 0x0 || b == 0x0 || c == 0x0)
|
||||
continue;
|
||||
|
||||
BuildBlock(x, y);
|
||||
|
||||
// Accept whole block when totally covered
|
||||
if (a == 0xF && b == 0xF && c == 0xF)
|
||||
for (s32 x = minx; x < maxx; x += BLOCK_SIZE)
|
||||
{
|
||||
for (s32 iy = 0; iy < BLOCK_SIZE; iy++)
|
||||
{
|
||||
for (s32 ix = 0; ix < BLOCK_SIZE; ix++)
|
||||
{
|
||||
Draw(x + ix, y + iy, ix, iy);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Partially covered block
|
||||
{
|
||||
s32 CY1 = C1 + DX12 * y0 - DY12 * x0;
|
||||
s32 CY2 = C2 + DX23 * y0 - DY23 * x0;
|
||||
s32 CY3 = C3 + DX31 * y0 - DY31 * x0;
|
||||
// Corners of block
|
||||
s32 x0 = x << 4;
|
||||
s32 x1 = (x + BLOCK_SIZE - 1) << 4;
|
||||
s32 y0 = y << 4;
|
||||
s32 y1 = (y + BLOCK_SIZE - 1) << 4;
|
||||
|
||||
for (s32 iy = 0; iy < BLOCK_SIZE; iy++)
|
||||
{
|
||||
s32 CX1 = CY1;
|
||||
s32 CX2 = CY2;
|
||||
s32 CX3 = CY3;
|
||||
// Evaluate half-space functions
|
||||
bool a00 = C1 + DX12 * y0 - DY12 * x0 > 0;
|
||||
bool a10 = C1 + DX12 * y0 - DY12 * x1 > 0;
|
||||
bool a01 = C1 + DX12 * y1 - DY12 * x0 > 0;
|
||||
bool a11 = C1 + DX12 * y1 - DY12 * x1 > 0;
|
||||
int a = (a00 << 0) | (a10 << 1) | (a01 << 2) | (a11 << 3);
|
||||
|
||||
for (s32 ix = 0; ix < BLOCK_SIZE; ix++)
|
||||
bool b00 = C2 + DX23 * y0 - DY23 * x0 > 0;
|
||||
bool b10 = C2 + DX23 * y0 - DY23 * x1 > 0;
|
||||
bool b01 = C2 + DX23 * y1 - DY23 * x0 > 0;
|
||||
bool b11 = C2 + DX23 * y1 - DY23 * x1 > 0;
|
||||
int b = (b00 << 0) | (b10 << 1) | (b01 << 2) | (b11 << 3);
|
||||
|
||||
bool c00 = C3 + DX31 * y0 - DY31 * x0 > 0;
|
||||
bool c10 = C3 + DX31 * y0 - DY31 * x1 > 0;
|
||||
bool c01 = C3 + DX31 * y1 - DY31 * x0 > 0;
|
||||
bool c11 = C3 + DX31 * y1 - DY31 * x1 > 0;
|
||||
int c = (c00 << 0) | (c10 << 1) | (c01 << 2) | (c11 << 3);
|
||||
|
||||
// Skip block when outside an edge
|
||||
if (a == 0x0 || b == 0x0 || c == 0x0)
|
||||
continue;
|
||||
|
||||
BuildBlock(x, y);
|
||||
|
||||
// Accept whole block when totally covered
|
||||
if (a == 0xF && b == 0xF && c == 0xF)
|
||||
{
|
||||
for (s32 iy = 0; iy < BLOCK_SIZE; iy++)
|
||||
{
|
||||
if (CX1 > 0 && CX2 > 0 && CX3 > 0)
|
||||
for (s32 ix = 0; ix < BLOCK_SIZE; ix++)
|
||||
{
|
||||
Draw(x + ix, y + iy, ix, iy);
|
||||
}
|
||||
|
||||
CX1 -= FDY12;
|
||||
CX2 -= FDY23;
|
||||
CX3 -= FDY31;
|
||||
}
|
||||
}
|
||||
else // Partially covered block
|
||||
{
|
||||
s32 CY1 = C1 + DX12 * y0 - DY12 * x0;
|
||||
s32 CY2 = C2 + DX23 * y0 - DY23 * x0;
|
||||
s32 CY3 = C3 + DX31 * y0 - DY31 * x0;
|
||||
|
||||
CY1 += FDX12;
|
||||
CY2 += FDX23;
|
||||
CY3 += FDX31;
|
||||
for (s32 iy = 0; iy < BLOCK_SIZE; iy++)
|
||||
{
|
||||
s32 CX1 = CY1;
|
||||
s32 CX2 = CY2;
|
||||
s32 CX3 = CY3;
|
||||
|
||||
for (s32 ix = 0; ix < BLOCK_SIZE; ix++)
|
||||
{
|
||||
if (CX1 > 0 && CX2 > 0 && CX3 > 0)
|
||||
{
|
||||
Draw(x + ix, y + iy, ix, iy);
|
||||
}
|
||||
|
||||
CX1 -= FDY12;
|
||||
CX2 -= FDY23;
|
||||
CX3 -= FDY31;
|
||||
}
|
||||
|
||||
CY1 += FDX12;
|
||||
CY2 += FDX23;
|
||||
CY3 += FDX31;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we are only calculating bbox, we only need to find the topmost,
|
||||
// leftmost, bottom most and rightmost pixels to be drawn.
|
||||
// So instead of drawing every single one of the triangle's pixels,
|
||||
// four loops are run: one for the top pixel, one for the left, one for
|
||||
// the bottom and one for the right. As soon as a pixel that is to be
|
||||
// drawn is found, the loop breaks. This enables a ~150% speedbost in
|
||||
// bbox calculation, albeit at the cost of some ugly repetitive code.
|
||||
const s32 FTOP = miny << 4;
|
||||
const s32 FLEFT = minx << 4;
|
||||
const s32 FBOTTOM = maxy << 4;
|
||||
const s32 FRIGHT = maxx << 4;
|
||||
|
||||
// Start checking for bbox top
|
||||
s32 CY1 = C1 + DX12 * FTOP - DY12 * FLEFT;
|
||||
s32 CY2 = C2 + DX23 * FTOP - DY23 * FLEFT;
|
||||
s32 CY3 = C3 + DX31 * FTOP - DY31 * FLEFT;
|
||||
|
||||
// Loop
|
||||
for (s32 y = miny; y <= maxy; ++y)
|
||||
{
|
||||
if (y >= BoundingBox::coords[BoundingBox::TOP])
|
||||
break;
|
||||
|
||||
s32 CX1 = CY1;
|
||||
s32 CX2 = CY2;
|
||||
s32 CX3 = CY3;
|
||||
|
||||
for (s32 x = minx; x <= maxx; ++x)
|
||||
{
|
||||
if (CX1 > 0 && CX2 > 0 && CX3 > 0)
|
||||
{
|
||||
// Build the new raster block every other pixel
|
||||
BuildBlock((x & ~(BLOCK_SIZE - 1)), y & ~(BLOCK_SIZE - 1));
|
||||
|
||||
Draw(x, y, x & 1, y & 1);
|
||||
|
||||
if (y >= BoundingBox::coords[BoundingBox::TOP])
|
||||
break;
|
||||
}
|
||||
|
||||
CX1 -= FDY12;
|
||||
CX2 -= FDY23;
|
||||
CX3 -= FDY31;
|
||||
}
|
||||
|
||||
CY1 += FDX12;
|
||||
CY2 += FDX23;
|
||||
CY3 += FDX31;
|
||||
}
|
||||
|
||||
// Checking for bbox left
|
||||
s32 CX1 = C1 + DX12 * FTOP - DY12 * FLEFT;
|
||||
s32 CX2 = C2 + DX23 * FTOP - DY23 * FLEFT;
|
||||
s32 CX3 = C3 + DX31 * FTOP - DY31 * FLEFT;
|
||||
|
||||
// Loop
|
||||
for (s32 x = minx; x <= maxx; ++x)
|
||||
{
|
||||
if (x >= BoundingBox::coords[BoundingBox::LEFT])
|
||||
break;
|
||||
|
||||
s32 CY1 = CX1;
|
||||
s32 CY2 = CX2;
|
||||
s32 CY3 = CX3;
|
||||
|
||||
for (s32 y = miny; y <= maxy; ++y)
|
||||
{
|
||||
if (CY1 > 0 && CY2 > 0 && CY3 > 0)
|
||||
{
|
||||
// Build the new raster block every other pixel
|
||||
BuildBlock((x & ~(BLOCK_SIZE - 1)), y & ~(BLOCK_SIZE - 1));
|
||||
|
||||
Draw(x, y, x & 1, y & 1);
|
||||
|
||||
if (x >= BoundingBox::coords[BoundingBox::LEFT])
|
||||
break;
|
||||
}
|
||||
|
||||
CY1 += FDX12;
|
||||
CY2 += FDX23;
|
||||
CY3 += FDX31;
|
||||
}
|
||||
|
||||
CX1 -= FDY12;
|
||||
CX2 -= FDY23;
|
||||
CX3 -= FDY31;
|
||||
}
|
||||
|
||||
// Checking for bbox bottom
|
||||
CY1 = C1 + DX12 * FBOTTOM - DY12 * FRIGHT;
|
||||
CY2 = C2 + DX23 * FBOTTOM - DY23 * FRIGHT;
|
||||
CY3 = C3 + DX31 * FBOTTOM - DY31 * FRIGHT;
|
||||
|
||||
// Loop
|
||||
for (s32 y = maxy; y >= miny; --y)
|
||||
{
|
||||
s32 CX1 = CY1;
|
||||
s32 CX2 = CY2;
|
||||
s32 CX3 = CY3;
|
||||
|
||||
if (y <= BoundingBox::coords[BoundingBox::BOTTOM])
|
||||
break;
|
||||
|
||||
for (s32 x = maxx; x >= minx; --x)
|
||||
{
|
||||
if (CX1 > 0 && CX2 > 0 && CX3 > 0)
|
||||
{
|
||||
// Build the new raster block every other pixel
|
||||
BuildBlock((x & ~(BLOCK_SIZE - 1)), y & ~(BLOCK_SIZE - 1));
|
||||
|
||||
Draw(x, y, x & 1, y & 1);
|
||||
|
||||
if (y <= BoundingBox::coords[BoundingBox::BOTTOM])
|
||||
break;
|
||||
}
|
||||
|
||||
CX1 += FDY12;
|
||||
CX2 += FDY23;
|
||||
CX3 += FDY31;
|
||||
}
|
||||
|
||||
CY1 -= FDX12;
|
||||
CY2 -= FDX23;
|
||||
CY3 -= FDX31;
|
||||
}
|
||||
|
||||
// Checking for bbox right
|
||||
CX1 = C1 + DX12 * FBOTTOM - DY12 * FRIGHT;
|
||||
CX2 = C2 + DX23 * FBOTTOM - DY23 * FRIGHT;
|
||||
CX3 = C3 + DX31 * FBOTTOM - DY31 * FRIGHT;
|
||||
|
||||
// Loop
|
||||
for (s32 x = maxx; x >= minx; --x)
|
||||
{
|
||||
if (x <= BoundingBox::coords[BoundingBox::RIGHT])
|
||||
break;
|
||||
|
||||
s32 CY1 = CX1;
|
||||
s32 CY2 = CX2;
|
||||
s32 CY3 = CX3;
|
||||
|
||||
for (s32 y = maxy; y >= miny; --y)
|
||||
{
|
||||
if (CY1 > 0 && CY2 > 0 && CY3 > 0)
|
||||
{
|
||||
// Build the new raster block every other pixel
|
||||
BuildBlock((x & ~(BLOCK_SIZE - 1)), y & ~(BLOCK_SIZE - 1));
|
||||
|
||||
Draw(x, y, x & 1, y & 1);
|
||||
|
||||
if (x <= BoundingBox::coords[BoundingBox::RIGHT])
|
||||
break;
|
||||
}
|
||||
|
||||
CY1 -= FDX12;
|
||||
CY2 -= FDX23;
|
||||
CY3 -= FDX31;
|
||||
}
|
||||
|
||||
CX1 += FDY12;
|
||||
CX2 += FDY23;
|
||||
CX3 += FDY31;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "VideoBackends/Software/Tev.h"
|
||||
#include "VideoBackends/Software/TextureSampler.h"
|
||||
#include "VideoBackends/Software/XFMemLoader.h"
|
||||
#include "VideoCommon/BoundingBox.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define ALLOW_TEV_DUMPS 1
|
||||
@@ -157,7 +158,7 @@ void Tev::SetRasColor(int colorChan, int swaptable)
|
||||
RasColor[ALP_C] = color[bpmem.tevksel[swaptable].swap2];
|
||||
}
|
||||
break;
|
||||
case 5: // alpha bump
|
||||
case 5: // alpha bump
|
||||
{
|
||||
for (s16& comp : RasColor)
|
||||
{
|
||||
@@ -649,121 +650,138 @@ void Tev::Draw()
|
||||
if (!TevAlphaTest(output[ALP_C]))
|
||||
return;
|
||||
|
||||
// z texture
|
||||
if (bpmem.ztex2.op)
|
||||
// This part is only needed if we are not simply computing bbox
|
||||
// (i. e., only needed when using the SW renderer)
|
||||
if (!BoundingBox::active)
|
||||
{
|
||||
u32 ztex = bpmem.ztex1.bias;
|
||||
switch (bpmem.ztex2.type)
|
||||
// z texture
|
||||
if (bpmem.ztex2.op)
|
||||
{
|
||||
case 0: // 8 bit
|
||||
ztex += TexColor[ALP_C];
|
||||
break;
|
||||
case 1: // 16 bit
|
||||
ztex += TexColor[ALP_C] << 8 | TexColor[RED_C];
|
||||
break;
|
||||
case 2: // 24 bit
|
||||
ztex += TexColor[RED_C] << 16 | TexColor[GRN_C] << 8 | TexColor[BLU_C];
|
||||
break;
|
||||
u32 ztex = bpmem.ztex1.bias;
|
||||
switch (bpmem.ztex2.type)
|
||||
{
|
||||
case 0: // 8 bit
|
||||
ztex += TexColor[ALP_C];
|
||||
break;
|
||||
case 1: // 16 bit
|
||||
ztex += TexColor[ALP_C] << 8 | TexColor[RED_C];
|
||||
break;
|
||||
case 2: // 24 bit
|
||||
ztex += TexColor[RED_C] << 16 | TexColor[GRN_C] << 8 | TexColor[BLU_C];
|
||||
break;
|
||||
}
|
||||
|
||||
if (bpmem.ztex2.op == ZTEXTURE_ADD)
|
||||
ztex += Position[2];
|
||||
|
||||
Position[2] = ztex & 0x00ffffff;
|
||||
}
|
||||
|
||||
if (bpmem.ztex2.op == ZTEXTURE_ADD)
|
||||
ztex += Position[2];
|
||||
// fog
|
||||
if (bpmem.fog.c_proj_fsel.fsel)
|
||||
{
|
||||
float ze;
|
||||
|
||||
Position[2] = ztex & 0x00ffffff;
|
||||
if (bpmem.fog.c_proj_fsel.proj == 0)
|
||||
{
|
||||
// perspective
|
||||
// ze = A/(B - (Zs >> B_SHF))
|
||||
s32 denom = bpmem.fog.b_magnitude - (Position[2] >> bpmem.fog.b_shift);
|
||||
//in addition downscale magnitude and zs to 0.24 bits
|
||||
ze = (bpmem.fog.a.GetA() * 16777215.0f) / (float)denom;
|
||||
}
|
||||
else
|
||||
{
|
||||
// orthographic
|
||||
// ze = a*Zs
|
||||
//in addition downscale zs to 0.24 bits
|
||||
ze = bpmem.fog.a.GetA() * ((float)Position[2] / 16777215.0f);
|
||||
|
||||
}
|
||||
|
||||
if (bpmem.fogRange.Base.Enabled)
|
||||
{
|
||||
// TODO: This is untested and should definitely be checked against real hw.
|
||||
// - No idea if offset is really normalized against the viewport width or against the projection matrix or yet something else
|
||||
// - scaling of the "k" coefficient isn't clear either.
|
||||
|
||||
// First, calculate the offset from the viewport center (normalized to 0..1)
|
||||
float offset = (Position[0] - (bpmem.fogRange.Base.Center - 342)) / (float)xfmem.viewport.wd;
|
||||
|
||||
// Based on that, choose the index such that points which are far away from the z-axis use the 10th "k" value and such that central points use the first value.
|
||||
float floatindex = 9.f - std::abs(offset) * 9.f;
|
||||
floatindex = (floatindex < 0.f) ? 0.f : (floatindex > 9.f) ? 9.f : floatindex; // TODO: This shouldn't be necessary!
|
||||
|
||||
// Get the two closest integer indices, look up the corresponding samples
|
||||
int indexlower = (int)floor(floatindex);
|
||||
int indexupper = indexlower + 1;
|
||||
// Look up coefficient... Seems like multiplying by 4 makes Fortune Street work properly (fog is too strong without the factor)
|
||||
float klower = bpmem.fogRange.K[indexlower/2].GetValue(indexlower%2) * 4.f;
|
||||
float kupper = bpmem.fogRange.K[indexupper/2].GetValue(indexupper%2) * 4.f;
|
||||
|
||||
// linearly interpolate the samples and multiple ze by the resulting adjustment factor
|
||||
float factor = indexupper - floatindex;
|
||||
float k = klower * factor + kupper * (1.f - factor);
|
||||
float x_adjust = sqrt(offset*offset + k*k)/k;
|
||||
ze *= x_adjust; // NOTE: This is basically dividing by a cosine (hidden behind GXInitFogAdjTable): 1/cos = c/b = sqrt(a^2+b^2)/b
|
||||
}
|
||||
|
||||
ze -= bpmem.fog.c_proj_fsel.GetC();
|
||||
|
||||
// clamp 0 to 1
|
||||
float fog = (ze<0.0f) ? 0.0f : ((ze>1.0f) ? 1.0f : ze);
|
||||
|
||||
switch (bpmem.fog.c_proj_fsel.fsel)
|
||||
{
|
||||
case 4: // exp
|
||||
fog = 1.0f - pow(2.0f, -8.0f * fog);
|
||||
break;
|
||||
case 5: // exp2
|
||||
fog = 1.0f - pow(2.0f, -8.0f * fog * fog);
|
||||
break;
|
||||
case 6: // backward exp
|
||||
fog = 1.0f - fog;
|
||||
fog = pow(2.0f, -8.0f * fog);
|
||||
break;
|
||||
case 7: // backward exp2
|
||||
fog = 1.0f - fog;
|
||||
fog = pow(2.0f, -8.0f * fog * fog);
|
||||
break;
|
||||
}
|
||||
|
||||
// lerp from output to fog color
|
||||
u32 fogInt = (u32)(fog * 256);
|
||||
u32 invFog = 256 - fogInt;
|
||||
|
||||
output[RED_C] = (output[RED_C] * invFog + fogInt * bpmem.fog.color.r) >> 8;
|
||||
output[GRN_C] = (output[GRN_C] * invFog + fogInt * bpmem.fog.color.g) >> 8;
|
||||
output[BLU_C] = (output[BLU_C] * invFog + fogInt * bpmem.fog.color.b) >> 8;
|
||||
}
|
||||
|
||||
bool late_ztest = !bpmem.zcontrol.early_ztest || !g_SWVideoConfig.bZComploc;
|
||||
if (late_ztest && bpmem.zmode.testenable)
|
||||
{
|
||||
// TODO: Check against hw if these values get incremented even if depth testing is disabled
|
||||
EfbInterface::IncPerfCounterQuadCount(PQ_ZCOMP_INPUT);
|
||||
|
||||
if (!EfbInterface::ZCompare(Position[0], Position[1], Position[2]))
|
||||
return;
|
||||
|
||||
EfbInterface::IncPerfCounterQuadCount(PQ_ZCOMP_OUTPUT);
|
||||
}
|
||||
}
|
||||
|
||||
// fog
|
||||
if (bpmem.fog.c_proj_fsel.fsel)
|
||||
{
|
||||
float ze;
|
||||
// branchless bounding box update
|
||||
BoundingBox::coords[BoundingBox::LEFT] = std::min((u16)Position[0], BoundingBox::coords[BoundingBox::LEFT]);
|
||||
BoundingBox::coords[BoundingBox::RIGHT] = std::max((u16)Position[0], BoundingBox::coords[BoundingBox::RIGHT]);
|
||||
BoundingBox::coords[BoundingBox::TOP] = std::min((u16)Position[1], BoundingBox::coords[BoundingBox::TOP]);
|
||||
BoundingBox::coords[BoundingBox::BOTTOM] = std::max((u16)Position[1], BoundingBox::coords[BoundingBox::BOTTOM]);
|
||||
|
||||
if (bpmem.fog.c_proj_fsel.proj == 0)
|
||||
{
|
||||
// perspective
|
||||
// ze = A/(B - (Zs >> B_SHF))
|
||||
s32 denom = bpmem.fog.b_magnitude - (Position[2] >> bpmem.fog.b_shift);
|
||||
//in addition downscale magnitude and zs to 0.24 bits
|
||||
ze = (bpmem.fog.a.GetA() * 16777215.0f) / (float)denom;
|
||||
}
|
||||
else
|
||||
{
|
||||
// orthographic
|
||||
// ze = a*Zs
|
||||
//in addition downscale zs to 0.24 bits
|
||||
ze = bpmem.fog.a.GetA() * ((float)Position[2] / 16777215.0f);
|
||||
// if we are only calculating the bounding box,
|
||||
// there's no need to actually draw anything
|
||||
if (BoundingBox::active)
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (bpmem.fogRange.Base.Enabled)
|
||||
{
|
||||
// TODO: This is untested and should definitely be checked against real hw.
|
||||
// - No idea if offset is really normalized against the viewport width or against the projection matrix or yet something else
|
||||
// - scaling of the "k" coefficient isn't clear either.
|
||||
|
||||
// First, calculate the offset from the viewport center (normalized to 0..1)
|
||||
float offset = (Position[0] - (bpmem.fogRange.Base.Center - 342)) / (float)xfmem.viewport.wd;
|
||||
|
||||
// Based on that, choose the index such that points which are far away from the z-axis use the 10th "k" value and such that central points use the first value.
|
||||
float floatindex = 9.f - std::abs(offset) * 9.f;
|
||||
floatindex = (floatindex < 0.f) ? 0.f : (floatindex > 9.f) ? 9.f : floatindex; // TODO: This shouldn't be necessary!
|
||||
|
||||
// Get the two closest integer indices, look up the corresponding samples
|
||||
int indexlower = (int)floor(floatindex);
|
||||
int indexupper = indexlower + 1;
|
||||
// Look up coefficient... Seems like multiplying by 4 makes Fortune Street work properly (fog is too strong without the factor)
|
||||
float klower = bpmem.fogRange.K[indexlower/2].GetValue(indexlower%2) * 4.f;
|
||||
float kupper = bpmem.fogRange.K[indexupper/2].GetValue(indexupper%2) * 4.f;
|
||||
|
||||
// linearly interpolate the samples and multiple ze by the resulting adjustment factor
|
||||
float factor = indexupper - floatindex;
|
||||
float k = klower * factor + kupper * (1.f - factor);
|
||||
float x_adjust = sqrt(offset*offset + k*k)/k;
|
||||
ze *= x_adjust; // NOTE: This is basically dividing by a cosine (hidden behind GXInitFogAdjTable): 1/cos = c/b = sqrt(a^2+b^2)/b
|
||||
}
|
||||
|
||||
ze -= bpmem.fog.c_proj_fsel.GetC();
|
||||
|
||||
// clamp 0 to 1
|
||||
float fog = (ze<0.0f) ? 0.0f : ((ze>1.0f) ? 1.0f : ze);
|
||||
|
||||
switch (bpmem.fog.c_proj_fsel.fsel)
|
||||
{
|
||||
case 4: // exp
|
||||
fog = 1.0f - pow(2.0f, -8.0f * fog);
|
||||
break;
|
||||
case 5: // exp2
|
||||
fog = 1.0f - pow(2.0f, -8.0f * fog * fog);
|
||||
break;
|
||||
case 6: // backward exp
|
||||
fog = 1.0f - fog;
|
||||
fog = pow(2.0f, -8.0f * fog);
|
||||
break;
|
||||
case 7: // backward exp2
|
||||
fog = 1.0f - fog;
|
||||
fog = pow(2.0f, -8.0f * fog * fog);
|
||||
break;
|
||||
}
|
||||
|
||||
// lerp from output to fog color
|
||||
u32 fogInt = (u32)(fog * 256);
|
||||
u32 invFog = 256 - fogInt;
|
||||
|
||||
output[RED_C] = (output[RED_C] * invFog + fogInt * bpmem.fog.color.r) >> 8;
|
||||
output[GRN_C] = (output[GRN_C] * invFog + fogInt * bpmem.fog.color.g) >> 8;
|
||||
output[BLU_C] = (output[BLU_C] * invFog + fogInt * bpmem.fog.color.b) >> 8;
|
||||
}
|
||||
|
||||
bool late_ztest = !bpmem.zcontrol.early_ztest || !g_SWVideoConfig.bZComploc;
|
||||
if (late_ztest && bpmem.zmode.testenable)
|
||||
{
|
||||
// TODO: Check against hw if these values get incremented even if depth testing is disabled
|
||||
EfbInterface::IncPerfCounterQuadCount(PQ_ZCOMP_INPUT);
|
||||
|
||||
if (!EfbInterface::ZCompare(Position[0], Position[1], Position[2]))
|
||||
return;
|
||||
|
||||
EfbInterface::IncPerfCounterQuadCount(PQ_ZCOMP_OUTPUT);
|
||||
}
|
||||
|
||||
#if ALLOW_TEV_DUMPS
|
||||
if (g_SWVideoConfig.bDumpTevStages)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "VideoCommon/RenderBase.h"
|
||||
#include "VideoCommon/Statistics.h"
|
||||
#include "VideoCommon/TextureDecoder.h"
|
||||
#include "VideoCommon/BoundingBox.h"
|
||||
#include "VideoCommon/VertexLoader.h"
|
||||
#include "VideoCommon/VertexShaderManager.h"
|
||||
#include "VideoCommon/VideoCommon.h"
|
||||
@@ -231,7 +232,7 @@ static void BPWritten(const BPCmd& bp)
|
||||
// here. Not sure if there's a better spot to put this.
|
||||
// the number of lines copied is determined by the y scale * source efb height
|
||||
|
||||
PixelEngine::bbox_active = false;
|
||||
BoundingBox::active = false;
|
||||
|
||||
float yScale;
|
||||
if (PE_copy.scale_invert)
|
||||
@@ -378,13 +379,13 @@ static void BPWritten(const BPCmd& bp)
|
||||
case BPMEM_CLEARBBOX2:
|
||||
// Don't compute bounding box if this frame is being skipped!
|
||||
// Wrong but valid values are better than bogus values...
|
||||
if (g_ActiveConfig.bUseBBox && !g_bSkipCurrentFrame)
|
||||
if (!g_bSkipCurrentFrame)
|
||||
{
|
||||
u8 offset = bp.address & 2;
|
||||
|
||||
PixelEngine::bbox[offset] = bp.newvalue & 0x3ff;
|
||||
PixelEngine::bbox[offset | 1] = bp.newvalue >> 10;
|
||||
PixelEngine::bbox_active = true;
|
||||
BoundingBox::coords[offset] = bp.newvalue & 0x3ff;
|
||||
BoundingBox::coords[offset + 1] = bp.newvalue >> 10;
|
||||
BoundingBox::active = true;
|
||||
}
|
||||
return;
|
||||
case BPMEM_TEXINVALIDATE:
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
// Copyright 2014 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "VideoCommon/PixelShaderManager.h"
|
||||
#include "VideoBackends/Software/SetupUnit.h"
|
||||
#include "VideoBackends/Software/TransformUnit.h"
|
||||
#include "VideoBackends/Software/Clipper.h"
|
||||
#include "VideoBackends/Software/Rasterizer.h"
|
||||
|
||||
#include "VideoCommon/BoundingBox.h"
|
||||
|
||||
namespace BoundingBox
|
||||
{
|
||||
|
||||
// External vars
|
||||
bool active = false;
|
||||
u16 coords[4] = { 0x80, 0xA0, 0x80, 0xA0 };
|
||||
u8 posMtxIdx;
|
||||
u8 texMtxIdx[8];
|
||||
|
||||
|
||||
// Internal vars
|
||||
SetupUnit vtxUnit;
|
||||
VAT myVat;
|
||||
u8 * bufferPos;
|
||||
TVtxDesc vertexDesc;
|
||||
PortableVertexDeclaration vertexDecl;
|
||||
|
||||
// Gets the pointer to the current buffer position
|
||||
void LOADERDECL SetVertexBufferPosition()
|
||||
{
|
||||
bufferPos = VertexManager::s_pCurBufferPointer;
|
||||
}
|
||||
|
||||
// Prepares the bounding box for new primitive data
|
||||
void Prepare(const VAT & vat, int primitive, const TVtxDesc & vtxDesc, const PortableVertexDeclaration & vtxDecl)
|
||||
{
|
||||
if (!active)
|
||||
return;
|
||||
|
||||
myVat = vat;
|
||||
vertexDesc = vtxDesc;
|
||||
vertexDecl = vtxDecl;
|
||||
|
||||
vtxUnit.Init(primitive);
|
||||
|
||||
// Initialize the SW renderer
|
||||
static bool SWinit = false;
|
||||
|
||||
if (!SWinit)
|
||||
{
|
||||
Clipper::Init();
|
||||
Rasterizer::Init();
|
||||
SWinit = true;
|
||||
}
|
||||
|
||||
// Update SW renderer values
|
||||
Clipper::SetViewOffset();
|
||||
Rasterizer::SetScissor();
|
||||
|
||||
for (u8 i = 0; i < 4; ++i)
|
||||
{
|
||||
Rasterizer::SetTevReg(i, 0, true, (s16)PixelShaderManager::constants.kcolors[i][0]);
|
||||
Rasterizer::SetTevReg(i, 1, true, (s16)PixelShaderManager::constants.kcolors[i][1]);
|
||||
Rasterizer::SetTevReg(i, 2, true, (s16)PixelShaderManager::constants.kcolors[i][2]);
|
||||
Rasterizer::SetTevReg(i, 3, true, (s16)PixelShaderManager::constants.kcolors[i][3]);
|
||||
|
||||
Rasterizer::SetTevReg(i, 0, false, (s16)PixelShaderManager::constants.colors[i][0]);
|
||||
Rasterizer::SetTevReg(i, 1, false, (s16)PixelShaderManager::constants.colors[i][1]);
|
||||
Rasterizer::SetTevReg(i, 2, false, (s16)PixelShaderManager::constants.colors[i][2]);
|
||||
Rasterizer::SetTevReg(i, 3, false, (s16)PixelShaderManager::constants.colors[i][3]);
|
||||
}
|
||||
}
|
||||
|
||||
// Updates the bounding box
|
||||
void LOADERDECL Update()
|
||||
{
|
||||
if (!active)
|
||||
return;
|
||||
|
||||
// Grab vertex input data and transform to output vertex
|
||||
InputVertexData myVertex;
|
||||
OutputVertexData * outVertex = vtxUnit.GetVertex();
|
||||
|
||||
// Feed vertex position and matrix
|
||||
myVertex.position = Vec3((const float *)bufferPos);
|
||||
myVertex.posMtx = vertexDesc.PosMatIdx ? posMtxIdx : MatrixIndexA.PosNormalMtxIdx;
|
||||
|
||||
// Transform position
|
||||
TransformUnit::TransformPosition(&myVertex, outVertex);
|
||||
|
||||
if (g_VtxDesc.Normal != NOT_PRESENT)
|
||||
{
|
||||
// Feed normal input data and transform
|
||||
myVat.g0.NormalIndex3;
|
||||
|
||||
memcpy((u8 *)myVertex.normal, bufferPos + vertexDecl.normals[0].offset, sizeof(float) * 3 * ((myVat.g0.NormalElements) ? 3 : 1));
|
||||
|
||||
TransformUnit::TransformNormal(&myVertex, myVat.g0.NormalElements, outVertex);
|
||||
}
|
||||
|
||||
// Feed color input data
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
if (vertexDecl.colors[i].enable)
|
||||
{
|
||||
u32 color;
|
||||
memcpy((u8 *)&color, bufferPos + vertexDecl.colors[i].offset, sizeof(u32));
|
||||
*(u32*)myVertex.color[i] = Common::swap32(color);
|
||||
}
|
||||
}
|
||||
|
||||
// Transform color
|
||||
TransformUnit::TransformColor(&myVertex, outVertex);
|
||||
|
||||
// Feed texture matrices
|
||||
int idx = 0;
|
||||
|
||||
myVertex.texMtx[0] = (vertexDesc.Tex0MatIdx) ? texMtxIdx[idx++] : MatrixIndexA.Tex0MtxIdx;
|
||||
myVertex.texMtx[1] = (vertexDesc.Tex1MatIdx) ? texMtxIdx[idx++] : MatrixIndexA.Tex1MtxIdx;
|
||||
myVertex.texMtx[2] = (vertexDesc.Tex2MatIdx) ? texMtxIdx[idx++] : MatrixIndexA.Tex2MtxIdx;
|
||||
myVertex.texMtx[3] = (vertexDesc.Tex3MatIdx) ? texMtxIdx[idx++] : MatrixIndexA.Tex3MtxIdx;
|
||||
myVertex.texMtx[4] = (vertexDesc.Tex4MatIdx) ? texMtxIdx[idx++] : MatrixIndexB.Tex4MtxIdx;
|
||||
myVertex.texMtx[5] = (vertexDesc.Tex5MatIdx) ? texMtxIdx[idx++] : MatrixIndexB.Tex5MtxIdx;
|
||||
myVertex.texMtx[6] = (vertexDesc.Tex6MatIdx) ? texMtxIdx[idx++] : MatrixIndexB.Tex6MtxIdx;
|
||||
myVertex.texMtx[7] = (vertexDesc.Tex7MatIdx) ? texMtxIdx[idx++] : MatrixIndexB.Tex7MtxIdx;
|
||||
|
||||
// Feed texture coordinate data
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
if (vertexDecl.texcoords[i].enable)
|
||||
memcpy((u8 *)&myVertex.texCoords[i], bufferPos + vertexDecl.texcoords[i].offset, sizeof(float) * 2);
|
||||
}
|
||||
|
||||
// Transform texture coordinate
|
||||
TransformUnit::TransformTexCoord(&myVertex, outVertex, false);
|
||||
|
||||
// Render the vertex in SW to calculate bbox
|
||||
vtxUnit.SetupVertex();
|
||||
}
|
||||
|
||||
// Save state
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
p.Do(active);
|
||||
p.Do(coords);
|
||||
}
|
||||
|
||||
} // namespace BoundingBox
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright 2014 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "VideoCommon/VertexLoader.h"
|
||||
|
||||
// Bounding Box manager
|
||||
|
||||
namespace BoundingBox
|
||||
{
|
||||
|
||||
// Determines if bounding box is active
|
||||
extern bool active;
|
||||
|
||||
// Bounding box current coordinates
|
||||
extern u16 coords[4];
|
||||
|
||||
enum
|
||||
{
|
||||
LEFT = 0,
|
||||
RIGHT = 1,
|
||||
TOP = 2,
|
||||
BOTTOM = 3
|
||||
};
|
||||
|
||||
// Current position matrix index
|
||||
extern u8 posMtxIdx;
|
||||
|
||||
// Texture matrix indexes
|
||||
extern u8 texMtxIdx[8];
|
||||
|
||||
void LOADERDECL SetVertexBufferPosition();
|
||||
void LOADERDECL Update();
|
||||
void Prepare(const VAT & vat, int primitive, const TVtxDesc & vtxDesc, const PortableVertexDeclaration & vtxDecl);
|
||||
|
||||
// Save state
|
||||
void DoState(PointerWrap &p);
|
||||
|
||||
}; // end of namespace BoundingBox
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "Core/HW/ProcessorInterface.h"
|
||||
#include "VideoCommon/CommandProcessor.h"
|
||||
#include "VideoCommon/PixelEngine.h"
|
||||
#include "VideoCommon/BoundingBox.h"
|
||||
#include "VideoCommon/RenderBase.h"
|
||||
#include "VideoCommon/VideoCommon.h"
|
||||
|
||||
@@ -106,9 +107,6 @@ static int et_SetFinishOnMainThread;
|
||||
static volatile u32 interruptSetToken = 0;
|
||||
static volatile u32 interruptSetFinish = 0;
|
||||
|
||||
u16 bbox[4];
|
||||
bool bbox_active;
|
||||
|
||||
enum
|
||||
{
|
||||
INT_CAUSE_PE_TOKEN = 0x200, // GP Token
|
||||
@@ -128,9 +126,6 @@ void DoState(PointerWrap &p)
|
||||
p.Do(g_bSignalFinishInterrupt);
|
||||
p.Do(interruptSetToken);
|
||||
p.Do(interruptSetFinish);
|
||||
|
||||
p.Do(bbox);
|
||||
p.Do(bbox_active);
|
||||
}
|
||||
|
||||
void UpdateInterrupts();
|
||||
@@ -155,13 +150,6 @@ void Init()
|
||||
|
||||
et_SetTokenOnMainThread = CoreTiming::RegisterEvent("SetToken", SetToken_OnMainThread);
|
||||
et_SetFinishOnMainThread = CoreTiming::RegisterEvent("SetFinish", SetFinish_OnMainThread);
|
||||
|
||||
bbox[0] = 0x80;
|
||||
bbox[1] = 0xA0;
|
||||
bbox[2] = 0x80;
|
||||
bbox[3] = 0xA0;
|
||||
|
||||
bbox_active = false;
|
||||
}
|
||||
|
||||
void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||
@@ -244,8 +232,8 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||
{
|
||||
mmio->Register(base | (PE_BBOX_LEFT + 2 * i),
|
||||
MMIO::ComplexRead<u16>([i](u32) {
|
||||
bbox_active = false;
|
||||
return bbox[i];
|
||||
BoundingBox::active = false;
|
||||
return BoundingBox::coords[i];
|
||||
}),
|
||||
MMIO::InvalidWrite<u16>()
|
||||
);
|
||||
|
||||
@@ -18,10 +18,10 @@ enum
|
||||
PE_ALPHAREAD = 0x08, // Alpha Read
|
||||
PE_CTRL_REGISTER = 0x0a, // Control
|
||||
PE_TOKEN_REG = 0x0e, // Token
|
||||
PE_BBOX_LEFT = 0x10, // Flip Left
|
||||
PE_BBOX_RIGHT = 0x12, // Flip Right
|
||||
PE_BBOX_TOP = 0x14, // Flip Top
|
||||
PE_BBOX_BOTTOM = 0x16, // Flip Bottom
|
||||
PE_BBOX_LEFT = 0x10, // Bounding Box Left Pixel
|
||||
PE_BBOX_RIGHT = 0x12, // Bounding Box Right Pixel
|
||||
PE_BBOX_TOP = 0x14, // Bounding Box Top Pixel
|
||||
PE_BBOX_BOTTOM = 0x16, // Bounding Box Bottom Pixel
|
||||
|
||||
// NOTE: Order not verified
|
||||
// These indicate the number of quads that are being used as input/output for each particular stage
|
||||
@@ -63,8 +63,4 @@ void SetToken(const u16 _token, const int _bSetTokenAcknowledge);
|
||||
void SetFinish();
|
||||
UPEAlphaReadReg GetAlphaReadMode();
|
||||
|
||||
// Bounding box functionality. Paper Mario (both) are a couple of the few games that use it.
|
||||
extern u16 bbox[4];
|
||||
extern bool bbox_active;
|
||||
|
||||
} // end of namespace PixelEngine
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
@@ -36,6 +36,7 @@
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemGroup>
|
||||
<ClCompile Include="AVIDump.cpp" />
|
||||
<ClCompile Include="BoundingBox.cpp" />
|
||||
<ClCompile Include="BPFunctions.cpp" />
|
||||
<ClCompile Include="BPMemory.cpp" />
|
||||
<ClCompile Include="BPStructs.cpp" />
|
||||
@@ -80,6 +81,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AVIDump.h" />
|
||||
<ClInclude Include="BoundingBox.h" />
|
||||
<ClInclude Include="BPFunctions.h" />
|
||||
<ClInclude Include="BPMemory.h" />
|
||||
<ClInclude Include="BPStructs.h" />
|
||||
@@ -147,4 +149,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Base">
|
||||
@@ -140,6 +140,9 @@
|
||||
<ClCompile Include="TextureDecoder_x64.cpp">
|
||||
<Filter>Decoding</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="BoundingBox.cpp">
|
||||
<Filter>Util</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="CommandProcessor.h" />
|
||||
@@ -269,8 +272,11 @@
|
||||
<ClInclude Include="VertexLoaderManager.h">
|
||||
<Filter>Vertex Loading</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="BoundingBox.h">
|
||||
<Filter>Util</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="CMakeLists.txt" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "VideoCommon/VertexShaderManager.h"
|
||||
#include "VideoCommon/VideoState.h"
|
||||
#include "VideoCommon/XFMemory.h"
|
||||
#include "VideoCommon/BoundingBox.h"
|
||||
|
||||
static void DoState(PointerWrap &p)
|
||||
{
|
||||
@@ -52,6 +53,10 @@ static void DoState(PointerWrap &p)
|
||||
VertexManager::DoState(p);
|
||||
p.DoMarker("VertexManager");
|
||||
|
||||
BoundingBox::DoState(p);
|
||||
p.DoMarker("BoundingBox");
|
||||
|
||||
|
||||
// TODO: search for more data that should be saved and add it here
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user