2013-04-18 03:09:55 +00:00
|
|
|
// Copyright 2013 Dolphin Emulator Project
|
|
|
|
// Licensed under GPLv2
|
|
|
|
// Refer to the license.txt file included.
|
2008-12-08 05:25:12 +00:00
|
|
|
|
2014-02-17 10:18:15 +00:00
|
|
|
#include "Common/Common.h"
|
|
|
|
#include "Common/MemoryUtil.h"
|
|
|
|
#include "Common/StringUtil.h"
|
|
|
|
#include "Common/x64ABI.h"
|
|
|
|
#include "Common/x64Emitter.h"
|
|
|
|
|
|
|
|
#include "Core/Host.h"
|
|
|
|
|
|
|
|
#include "VideoCommon/BPMemory.h"
|
|
|
|
#include "VideoCommon/DataReader.h"
|
|
|
|
#include "VideoCommon/IndexGenerator.h"
|
|
|
|
#include "VideoCommon/LookUpTables.h"
|
|
|
|
#include "VideoCommon/PixelEngine.h"
|
|
|
|
#include "VideoCommon/Statistics.h"
|
|
|
|
#include "VideoCommon/VertexLoader.h"
|
|
|
|
#include "VideoCommon/VertexLoader_Color.h"
|
|
|
|
#include "VideoCommon/VertexLoader_Normal.h"
|
|
|
|
#include "VideoCommon/VertexLoader_Position.h"
|
|
|
|
#include "VideoCommon/VertexLoader_TextCoord.h"
|
2014-02-19 01:27:20 +00:00
|
|
|
#include "VideoCommon/VertexLoaderManager.h"
|
2014-02-17 10:18:15 +00:00
|
|
|
#include "VideoCommon/VertexManagerBase.h"
|
|
|
|
#include "VideoCommon/VideoCommon.h"
|
|
|
|
#include "VideoCommon/VideoConfig.h"
|
2008-12-08 05:25:12 +00:00
|
|
|
|
2009-06-28 20:04:07 +00:00
|
|
|
//BBox
|
2014-02-17 10:18:15 +00:00
|
|
|
#include "VideoCommon/XFMemory.h"
|
2008-12-08 05:25:12 +00:00
|
|
|
|
2008-12-19 21:24:52 +00:00
|
|
|
#define COMPILED_CODE_SIZE 4096
|
2008-12-08 05:25:12 +00:00
|
|
|
|
|
|
|
NativeVertexFormat *g_nativeVertexFmt;
|
|
|
|
|
|
|
|
#ifndef _WIN32
|
|
|
|
#undef inline
|
|
|
|
#define inline
|
|
|
|
#endif
|
|
|
|
|
2008-12-25 21:44:56 +00:00
|
|
|
// Matrix components are first in GC format but later in PC format - we need to store it temporarily
|
|
|
|
// when decoding each vertex.
|
2014-01-25 18:04:15 +00:00
|
|
|
static u8 s_curposmtx = MatrixIndexA.PosNormalMtxIdx;
|
2008-12-08 05:25:12 +00:00
|
|
|
static u8 s_curtexmtx[8];
|
|
|
|
static int s_texmtxwrite = 0;
|
|
|
|
static int s_texmtxread = 0;
|
2008-12-25 21:44:56 +00:00
|
|
|
|
2008-12-08 05:25:12 +00:00
|
|
|
static int loop_counter;
|
|
|
|
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
|
2008-12-08 05:25:12 +00:00
|
|
|
// Vertex loaders read these. Although the scale ones should be baked into the shader.
|
|
|
|
int tcIndex;
|
|
|
|
int colIndex;
|
|
|
|
TVtxAttr* pVtxAttr;
|
|
|
|
int colElements[2];
|
|
|
|
float posScale;
|
2010-02-24 23:58:48 +00:00
|
|
|
float tcScale[8];
|
2008-12-08 05:25:12 +00:00
|
|
|
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
// bbox variables
|
2013-02-21 10:41:14 +00:00
|
|
|
// bbox must read vertex position, so convert it to this buffer
|
|
|
|
static float s_bbox_vertex_buffer[3];
|
|
|
|
static u8 *s_bbox_pCurBufferPointer_orig;
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
static int s_bbox_primitive;
|
|
|
|
static struct Point
|
|
|
|
{
|
|
|
|
s32 x;
|
|
|
|
s32 y;
|
|
|
|
float z;
|
|
|
|
} s_bbox_points[3];
|
|
|
|
static u8 s_bbox_currPoint;
|
|
|
|
static u8 s_bbox_loadedPoints;
|
|
|
|
static const u8 s_bbox_primitivePoints[8] = { 3, 0, 3, 3, 3, 2, 2, 1 };
|
2013-02-21 10:41:14 +00:00
|
|
|
|
2010-09-14 13:52:17 +00:00
|
|
|
static const float fractionTable[32] = {
|
|
|
|
1.0f / (1U << 0), 1.0f / (1U << 1), 1.0f / (1U << 2), 1.0f / (1U << 3),
|
|
|
|
1.0f / (1U << 4), 1.0f / (1U << 5), 1.0f / (1U << 6), 1.0f / (1U << 7),
|
|
|
|
1.0f / (1U << 8), 1.0f / (1U << 9), 1.0f / (1U << 10), 1.0f / (1U << 11),
|
|
|
|
1.0f / (1U << 12), 1.0f / (1U << 13), 1.0f / (1U << 14), 1.0f / (1U << 15),
|
|
|
|
1.0f / (1U << 16), 1.0f / (1U << 17), 1.0f / (1U << 18), 1.0f / (1U << 19),
|
|
|
|
1.0f / (1U << 20), 1.0f / (1U << 21), 1.0f / (1U << 22), 1.0f / (1U << 23),
|
|
|
|
1.0f / (1U << 24), 1.0f / (1U << 25), 1.0f / (1U << 26), 1.0f / (1U << 27),
|
|
|
|
1.0f / (1U << 28), 1.0f / (1U << 29), 1.0f / (1U << 30), 1.0f / (1U << 31),
|
|
|
|
};
|
2013-03-06 17:58:15 +00:00
|
|
|
|
2008-12-08 05:25:12 +00:00
|
|
|
using namespace Gen;
|
|
|
|
|
|
|
|
void LOADERDECL PosMtx_ReadDirect_UByte()
|
|
|
|
{
|
|
|
|
s_curposmtx = DataReadU8() & 0x3f;
|
|
|
|
PRIM_LOG("posmtx: %d, ", s_curposmtx);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LOADERDECL PosMtx_Write()
|
|
|
|
{
|
2013-02-22 08:19:59 +00:00
|
|
|
DataWrite<u8>(s_curposmtx);
|
|
|
|
DataWrite<u8>(0);
|
|
|
|
DataWrite<u8>(0);
|
|
|
|
DataWrite<u8>(0);
|
2014-01-25 18:04:15 +00:00
|
|
|
|
|
|
|
// Resetting current position matrix to default is needed for bbox to behave
|
|
|
|
s_curposmtx = (u8) MatrixIndexA.PosNormalMtxIdx;
|
2008-12-08 05:25:12 +00:00
|
|
|
}
|
|
|
|
|
2013-10-29 05:23:17 +00:00
|
|
|
void LOADERDECL UpdateBoundingBoxPrepare()
|
2013-02-21 10:41:14 +00:00
|
|
|
{
|
|
|
|
if (!PixelEngine::bbox_active)
|
|
|
|
return;
|
2013-10-29 05:23:17 +00:00
|
|
|
|
2013-02-21 10:41:14 +00:00
|
|
|
// set our buffer as videodata buffer, so we will get a copy of the vertex positions
|
|
|
|
// this is a big hack, but so we can use the same converting function then without bbox
|
|
|
|
s_bbox_pCurBufferPointer_orig = VertexManager::s_pCurBufferPointer;
|
|
|
|
VertexManager::s_pCurBufferPointer = (u8*)s_bbox_vertex_buffer;
|
|
|
|
}
|
|
|
|
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
inline bool UpdateBoundingBoxVars()
|
|
|
|
{
|
|
|
|
switch (s_bbox_primitive)
|
|
|
|
{
|
|
|
|
// Quads: fill 0,1,2 (check),1 (check, clear, repeat)
|
|
|
|
case 0:
|
|
|
|
++s_bbox_loadedPoints;
|
|
|
|
if (s_bbox_loadedPoints == 3)
|
|
|
|
{
|
|
|
|
s_bbox_currPoint = 1;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (s_bbox_loadedPoints == 4)
|
|
|
|
{
|
|
|
|
s_bbox_loadedPoints = 0;
|
|
|
|
s_bbox_currPoint = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
++s_bbox_currPoint;
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Triangles: 0,1,2 (check, clear, repeat)
|
|
|
|
case 2:
|
|
|
|
++s_bbox_loadedPoints;
|
|
|
|
if (s_bbox_loadedPoints == 3)
|
|
|
|
{
|
|
|
|
s_bbox_loadedPoints = 0;
|
|
|
|
s_bbox_currPoint = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
++s_bbox_currPoint;
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Triangle strip: 0, 1, 2 (check), 0 (check), 1, (check), 2 (check, repeat checking 0, 1, 2)
|
|
|
|
case 3:
|
|
|
|
if (++s_bbox_currPoint == 3)
|
|
|
|
s_bbox_currPoint = 0;
|
|
|
|
|
|
|
|
if (s_bbox_loadedPoints == 2)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
++s_bbox_loadedPoints;
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Triangle fan: 0,1,2 (check), 1 (check), 2 (check, repeat checking 1,2)
|
|
|
|
case 4:
|
|
|
|
s_bbox_currPoint ^= s_bbox_currPoint ? 3 : 1;
|
|
|
|
|
|
|
|
if (s_bbox_loadedPoints == 2)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
++s_bbox_loadedPoints;
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Lines: 0,1 (check, clear, repeat)
|
|
|
|
case 5:
|
|
|
|
++s_bbox_loadedPoints;
|
|
|
|
if (s_bbox_loadedPoints == 2)
|
|
|
|
{
|
|
|
|
s_bbox_loadedPoints = 0;
|
|
|
|
s_bbox_currPoint = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
++s_bbox_currPoint;
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Line strip: 0,1 (check), 0 (check), 1 (check, repeat checking 0,1)
|
|
|
|
case 6:
|
|
|
|
s_bbox_currPoint ^= 1;
|
|
|
|
|
|
|
|
if (s_bbox_loadedPoints == 1)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
++s_bbox_loadedPoints;
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Points: 0 (check, clear, repeat)
|
|
|
|
case 7:
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// This should not happen!
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-29 05:23:17 +00:00
|
|
|
void LOADERDECL UpdateBoundingBox()
|
2009-06-28 20:04:07 +00:00
|
|
|
{
|
2011-10-26 00:19:10 +00:00
|
|
|
if (!PixelEngine::bbox_active)
|
2009-06-28 20:04:07 +00:00
|
|
|
return;
|
2013-03-20 01:51:12 +00:00
|
|
|
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
// Reset videodata pointer
|
2013-02-21 10:41:14 +00:00
|
|
|
VertexManager::s_pCurBufferPointer = s_bbox_pCurBufferPointer_orig;
|
2013-03-20 01:51:12 +00:00
|
|
|
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
// Copy vertex pointers
|
2013-02-21 10:41:14 +00:00
|
|
|
memcpy(VertexManager::s_pCurBufferPointer, s_bbox_vertex_buffer, 12);
|
|
|
|
VertexManager::s_pCurBufferPointer += 12;
|
2009-06-28 20:04:07 +00:00
|
|
|
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
// We must transform the just loaded point by the current world and projection matrix - in software
|
|
|
|
float transformed[3];
|
|
|
|
float screenPoint[3];
|
|
|
|
|
|
|
|
// We need to get the raw projection values for the bounding box calculation
|
|
|
|
// to work properly. That means, no projection hacks!
|
|
|
|
const float * const orig_point = s_bbox_vertex_buffer;
|
2014-04-27 18:59:04 +00:00
|
|
|
const float * const world_matrix = (float*)xfmem.posMatrices + s_curposmtx * 4;
|
|
|
|
const float * const proj_matrix = xfmem.projection.rawProjection;
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
|
|
|
|
// Transform by world matrix
|
|
|
|
// Only calculate what we need, discard the rest
|
|
|
|
transformed[0] = orig_point[0] * world_matrix[0] + orig_point[1] * world_matrix[1] + orig_point[2] * world_matrix[2] + world_matrix[3];
|
|
|
|
transformed[1] = orig_point[0] * world_matrix[4] + orig_point[1] * world_matrix[5] + orig_point[2] * world_matrix[6] + world_matrix[7];
|
|
|
|
|
|
|
|
// Transform by projection matrix
|
2014-04-27 18:59:04 +00:00
|
|
|
switch (xfmem.projection.type)
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
{
|
|
|
|
// Perspective projection, we must divide by w
|
|
|
|
case GX_PERSPECTIVE:
|
|
|
|
transformed[2] = orig_point[0] * world_matrix[8] + orig_point[1] * world_matrix[9] + orig_point[2] * world_matrix[10] + world_matrix[11];
|
|
|
|
screenPoint[0] = (transformed[0] * proj_matrix[0] + transformed[2] * proj_matrix[1]) / (-transformed[2]);
|
|
|
|
screenPoint[1] = (transformed[1] * proj_matrix[2] + transformed[2] * proj_matrix[3]) / (-transformed[2]);
|
|
|
|
screenPoint[2] = ((transformed[2] * proj_matrix[4] + proj_matrix[5]) * (1.0f - (float) 1e-7)) / (-transformed[2]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Orthographic projection
|
|
|
|
case GX_ORTHOGRAPHIC:
|
|
|
|
screenPoint[0] = transformed[0] * proj_matrix[0] + proj_matrix[1];
|
|
|
|
screenPoint[1] = transformed[1] * proj_matrix[2] + proj_matrix[3];
|
|
|
|
|
|
|
|
// We don't really have to care about z here
|
|
|
|
screenPoint[2] = -0.2f;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2014-04-27 18:59:04 +00:00
|
|
|
ERROR_LOG(VIDEO, "Unknown projection type: %d", xfmem.projection.type);
|
2014-02-04 00:30:39 +00:00
|
|
|
screenPoint[0] = screenPoint[1] = screenPoint[2] = 1;
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Convert to screen space and add the point to the list - round like the real hardware
|
2014-04-27 18:59:04 +00:00
|
|
|
s_bbox_points[s_bbox_currPoint].x = (((s32) (0.5f + (16.0f * (screenPoint[0] * xfmem.viewport.wd + (xfmem.viewport.xOrig - 342.0f))))) + 3) >> 4;
|
|
|
|
s_bbox_points[s_bbox_currPoint].y = (((s32) (0.5f + (16.0f * (screenPoint[1] * xfmem.viewport.ht + (xfmem.viewport.yOrig - 342.0f))))) + 3) >> 4;
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
s_bbox_points[s_bbox_currPoint].z = screenPoint[2];
|
|
|
|
|
|
|
|
// Update point list for primitive
|
|
|
|
bool check_bbox = UpdateBoundingBoxVars();
|
|
|
|
|
|
|
|
// If we do not have enough points to check the bounding box yet, we are done for now
|
|
|
|
if (!check_bbox)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// How many points does our primitive have?
|
|
|
|
const u8 numPoints = s_bbox_primitivePoints[s_bbox_primitive];
|
|
|
|
|
|
|
|
// If the primitive is a point, update the bounding box now
|
|
|
|
if (numPoints == 1)
|
|
|
|
{
|
|
|
|
Point & p = s_bbox_points[0];
|
|
|
|
|
|
|
|
// Point is out of bounds
|
|
|
|
if (p.x < 0 || p.x > 607 || p.y < 0 || p.y > 479 || p.z >= 0.0f)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Point is in bounds. Update bounding box if necessary and return
|
|
|
|
PixelEngine::bbox[0] = (p.x < PixelEngine::bbox[0]) ? p.x : PixelEngine::bbox[0];
|
|
|
|
PixelEngine::bbox[1] = (p.x > PixelEngine::bbox[1]) ? p.x : PixelEngine::bbox[1];
|
|
|
|
PixelEngine::bbox[2] = (p.y < PixelEngine::bbox[2]) ? p.y : PixelEngine::bbox[2];
|
|
|
|
PixelEngine::bbox[3] = (p.y > PixelEngine::bbox[3]) ? p.y : PixelEngine::bbox[3];
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now comes the fun part. We must clip the triangles/lines to the viewport - also in software
|
|
|
|
Point & p0 = s_bbox_points[0], &p1 = s_bbox_points[1], &p2 = s_bbox_points[2];
|
|
|
|
|
|
|
|
// Check for z-clip. This crude method is required for Mickey's Magical Mirror, at least
|
|
|
|
if ((p0.z > 0.0f) || (p1.z > 0.0f) || ((numPoints == 3) && (p2.z > 0.0f)))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Check points for bounds
|
2014-03-18 03:00:38 +00:00
|
|
|
u8 b0 = ((p0.x > 0) ? 1 : 0) | ((p0.y > 0) ? 2 : 0) | ((p0.x > 607) ? 4 : 0) | ((p0.y > 479) ? 8 : 0);
|
|
|
|
u8 b1 = ((p1.x > 0) ? 1 : 0) | ((p1.y > 0) ? 2 : 0) | ((p1.x > 607) ? 4 : 0) | ((p1.y > 479) ? 8 : 0);
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
|
|
|
|
// Let's be practical... If we only have a line, setting b2 to 3 saves an "if"-clause later on
|
|
|
|
u8 b2 = 3;
|
|
|
|
|
|
|
|
// Otherwise if we have a triangle, we need to check the third point
|
|
|
|
if (numPoints == 3)
|
2014-03-18 03:00:38 +00:00
|
|
|
b2 = ((p2.x > 0) ? 1 : 0) | ((p2.y > 0) ? 2 : 0) | ((p2.x > 607) ? 4 : 0) | ((p2.y > 479) ? 8 : 0);
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
|
|
|
|
// These are the internal bbox vars
|
|
|
|
s32 left = 608, right = -1, top = 480, bottom = -1;
|
|
|
|
|
|
|
|
// If the polygon is inside viewport, let's update the bounding box and be done with it
|
|
|
|
if ((b0 == 3) && (b0 == b1) && (b0 == b2))
|
|
|
|
{
|
2014-03-26 23:24:48 +00:00
|
|
|
left = std::min(p0.x, p1.x);
|
|
|
|
top = std::min(p0.y, p1.y);
|
|
|
|
right = std::max(p0.x, p1.x);
|
|
|
|
bottom = std::max(p0.y, p1.y);
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
|
|
|
|
// Triangle
|
2014-03-26 23:24:48 +00:00
|
|
|
if (numPoints == 3)
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
{
|
2014-03-26 23:24:48 +00:00
|
|
|
left = std::min(left, p2.x);
|
|
|
|
top = std::min(top, p2.y);
|
|
|
|
right = std::max(right, p2.x);
|
|
|
|
bottom = std::max(bottom, p2.y);
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Update bounding box
|
|
|
|
PixelEngine::bbox[0] = (left < PixelEngine::bbox[0]) ? left : PixelEngine::bbox[0];
|
|
|
|
PixelEngine::bbox[1] = (right > PixelEngine::bbox[1]) ? right : PixelEngine::bbox[1];
|
|
|
|
PixelEngine::bbox[2] = (top < PixelEngine::bbox[2]) ? top : PixelEngine::bbox[2];
|
|
|
|
PixelEngine::bbox[3] = (bottom > PixelEngine::bbox[3]) ? bottom : PixelEngine::bbox[3];
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If it is not inside, then either it is completely outside, or it needs clipping.
|
|
|
|
// Check the primitive's lines
|
|
|
|
u8 i0 = b0 ^ b1;
|
|
|
|
u8 i1 = (numPoints == 3) ? (b1 ^ b2) : i0;
|
|
|
|
u8 i2 = (numPoints == 3) ? (b0 ^ b2) : i0;
|
|
|
|
|
|
|
|
// Primitive out of bounds - return
|
|
|
|
if (!(i0 | i1 | i2))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// First point inside viewport - update internal bbox
|
|
|
|
if (b0 == 3)
|
|
|
|
{
|
|
|
|
left = p0.x;
|
|
|
|
top = p0.y;
|
|
|
|
right = p0.x;
|
|
|
|
bottom = p0.y;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Second point inside
|
|
|
|
if (b1 == 3)
|
|
|
|
{
|
2014-03-26 23:28:01 +00:00
|
|
|
left = std::min(p1.x, left);
|
|
|
|
top = std::min(p1.y, top);
|
|
|
|
right = std::max(p1.x, right);
|
|
|
|
bottom = std::max(p1.y, bottom);
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Third point inside
|
|
|
|
if ((b2 == 3) && (numPoints == 3))
|
|
|
|
{
|
2014-03-26 23:28:01 +00:00
|
|
|
left = std::min(p2.x, left);
|
|
|
|
top = std::min(p2.y, top);
|
|
|
|
right = std::max(p2.x, right);
|
|
|
|
bottom = std::max(p2.y, bottom);
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Triangle equation vars
|
|
|
|
float m, c;
|
2009-06-28 20:04:07 +00:00
|
|
|
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
// Some definitions to help with rounding later on
|
|
|
|
const float highNum = 89374289734.0f;
|
|
|
|
const float roundUp = 0.001f;
|
2009-06-28 20:04:07 +00:00
|
|
|
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
// Intersection result
|
|
|
|
s32 s;
|
2009-06-28 20:04:07 +00:00
|
|
|
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
// First line intersects
|
|
|
|
if (i0)
|
|
|
|
{
|
|
|
|
m = (p1.x - p0.x) ? ((p1.y - p0.y) / (p1.x - p0.x)) : highNum;
|
|
|
|
c = p0.y - (m * p0.x);
|
2014-03-26 23:28:01 +00:00
|
|
|
if (i0 & 1) { s = (s32)(c + roundUp); if (s >= 0 && s <= 479) left = 0; top = std::min(s, top); bottom = std::max(s, bottom); }
|
|
|
|
if (i0 & 2) { s = (s32)((-c / m) + roundUp); if (s >= 0 && s <= 607) top = 0; left = std::min(s, left); right = std::max(s, right); }
|
|
|
|
if (i0 & 4) { s = (s32)((m * 607) + c + roundUp); if (s >= 0 && s <= 479) right = 607; top = std::min(s, top); bottom = std::max(s, bottom); }
|
|
|
|
if (i0 & 8) { s = (s32)(((479 - c) / m) + roundUp); if (s >= 0 && s <= 607) bottom = 479; left = std::min(s, left); right = std::max(s, right); }
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
}
|
2011-10-26 00:19:10 +00:00
|
|
|
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
// Only check other lines if we are dealing with a triangle
|
|
|
|
if (numPoints == 3)
|
|
|
|
{
|
|
|
|
// Second line intersects
|
|
|
|
if (i1)
|
|
|
|
{
|
|
|
|
m = (p2.x - p1.x) ? ((p2.y - p1.y) / (p2.x - p1.x)) : highNum;
|
|
|
|
c = p1.y - (m * p1.x);
|
2014-03-26 23:28:01 +00:00
|
|
|
if (i1 & 1) { s = (s32)(c + roundUp); if (s >= 0 && s <= 479) left = 0; top = std::min(s, top); bottom = std::max(s, bottom); }
|
|
|
|
if (i1 & 2) { s = (s32)((-c / m) + roundUp); if (s >= 0 && s <= 607) top = 0; left = std::min(s, left); right = std::max(s, right); }
|
|
|
|
if (i1 & 4) { s = (s32)((m * 607) + c + roundUp); if (s >= 0 && s <= 479) right = 607; top = std::min(s, top); bottom = std::max(s, bottom); }
|
|
|
|
if (i1 & 8) { s = (s32)(((479 - c) / m) + roundUp); if (s >= 0 && s <= 607) bottom = 479; left = std::min(s, left); right = std::max(s, right); }
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
}
|
2009-06-28 20:04:07 +00:00
|
|
|
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
// Third line intersects
|
|
|
|
if (i2)
|
|
|
|
{
|
|
|
|
m = (p2.x - p0.x) ? ((p2.y - p0.y) / (p2.x - p0.x)) : highNum;
|
|
|
|
c = p0.y - (m * p0.x);
|
2014-03-26 23:28:01 +00:00
|
|
|
if (i2 & 1) { s = (s32)(c + roundUp); if (s >= 0 && s <= 479) left = 0; top = std::min(s, top); bottom = std::max(s, bottom); }
|
|
|
|
if (i2 & 2) { s = (s32)((-c / m) + roundUp); if (s >= 0 && s <= 607) top = 0; left = std::min(s, left); right = std::max(s, right); }
|
|
|
|
if (i2 & 4) { s = (s32)((m * 607) + c + roundUp); if (s >= 0 && s <= 479) right = 607; top = std::min(s, top); bottom = std::max(s, bottom); }
|
|
|
|
if (i2 & 8) { s = (s32)(((479 - c) / m) + roundUp); if (s >= 0 && s <= 607) bottom = 479; left = std::min(s, left); right = std::max(s, right); }
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
}
|
|
|
|
}
|
2011-10-28 20:12:12 +00:00
|
|
|
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
// Wrong bounding box values, discard this polygon (it is outside)
|
|
|
|
if (left > 607 || top > 479 || right < 0 || bottom < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Trim bounding box to viewport
|
|
|
|
left = (left < 0) ? 0 : left;
|
|
|
|
top = (top < 0) ? 0 : top;
|
|
|
|
right = (right > 607) ? 607 : right;
|
|
|
|
bottom = (bottom > 479) ? 479 : bottom;
|
|
|
|
|
|
|
|
// Update bounding box
|
|
|
|
PixelEngine::bbox[0] = (left < PixelEngine::bbox[0]) ? left : PixelEngine::bbox[0];
|
|
|
|
PixelEngine::bbox[1] = (right > PixelEngine::bbox[1]) ? right : PixelEngine::bbox[1];
|
|
|
|
PixelEngine::bbox[2] = (top < PixelEngine::bbox[2]) ? top : PixelEngine::bbox[2];
|
|
|
|
PixelEngine::bbox[3] = (bottom > PixelEngine::bbox[3]) ? bottom : PixelEngine::bbox[3];
|
2009-06-28 20:04:07 +00:00
|
|
|
}
|
|
|
|
|
2008-12-08 05:25:12 +00:00
|
|
|
void LOADERDECL TexMtx_ReadDirect_UByte()
|
|
|
|
{
|
2009-02-15 12:38:25 +00:00
|
|
|
s_curtexmtx[s_texmtxread] = DataReadU8() & 0x3f;
|
2008-12-08 05:25:12 +00:00
|
|
|
PRIM_LOG("texmtx%d: %d, ", s_texmtxread, s_curtexmtx[s_texmtxread]);
|
|
|
|
s_texmtxread++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LOADERDECL TexMtx_Write_Float()
|
|
|
|
{
|
2013-02-22 08:19:59 +00:00
|
|
|
DataWrite(float(s_curtexmtx[s_texmtxwrite++]));
|
2008-12-08 05:25:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void LOADERDECL TexMtx_Write_Float2()
|
|
|
|
{
|
2013-02-22 08:19:59 +00:00
|
|
|
DataWrite(0.f);
|
|
|
|
DataWrite(float(s_curtexmtx[s_texmtxwrite++]));
|
2008-12-08 05:25:12 +00:00
|
|
|
}
|
|
|
|
|
2010-01-12 00:08:02 +00:00
|
|
|
void LOADERDECL TexMtx_Write_Float4()
|
2008-12-08 05:25:12 +00:00
|
|
|
{
|
2013-02-22 08:19:59 +00:00
|
|
|
DataWrite(0.f);
|
|
|
|
DataWrite(0.f);
|
|
|
|
DataWrite(float(s_curtexmtx[s_texmtxwrite++]));
|
|
|
|
// Just to fill out with 0.
|
|
|
|
DataWrite(0.f);
|
2008-12-08 05:25:12 +00:00
|
|
|
}
|
|
|
|
|
2013-10-29 05:23:17 +00:00
|
|
|
VertexLoader::VertexLoader(const TVtxDesc &vtx_desc, const VAT &vtx_attr)
|
2008-12-08 05:25:12 +00:00
|
|
|
{
|
2014-03-09 20:14:26 +00:00
|
|
|
m_compiledCode = nullptr;
|
2008-12-08 05:25:12 +00:00
|
|
|
m_numLoadedVertices = 0;
|
|
|
|
m_VertexSize = 0;
|
2014-03-09 20:14:26 +00:00
|
|
|
m_NativeFmt = nullptr;
|
2008-12-08 05:25:12 +00:00
|
|
|
loop_counter = 0;
|
|
|
|
VertexLoader_Normal::Init();
|
2010-04-09 15:13:42 +00:00
|
|
|
VertexLoader_Position::Init();
|
|
|
|
VertexLoader_TextCoord::Init();
|
2008-12-08 05:25:12 +00:00
|
|
|
|
|
|
|
m_VtxDesc = vtx_desc;
|
|
|
|
SetVAT(vtx_attr.g0.Hex, vtx_attr.g1.Hex, vtx_attr.g2.Hex);
|
|
|
|
|
2014-02-23 14:14:27 +00:00
|
|
|
#ifdef USE_VERTEX_LOADER_JIT
|
2008-12-19 21:24:52 +00:00
|
|
|
AllocCodeSpace(COMPILED_CODE_SIZE);
|
2008-12-08 05:25:12 +00:00
|
|
|
CompileVertexTranslator();
|
2008-12-19 21:24:52 +00:00
|
|
|
WriteProtect();
|
2013-03-06 17:58:15 +00:00
|
|
|
#else
|
2014-02-23 14:14:27 +00:00
|
|
|
m_numPipelineStages = 0;
|
2013-03-06 17:58:15 +00:00
|
|
|
CompileVertexTranslator();
|
2013-02-26 19:49:00 +00:00
|
|
|
#endif
|
|
|
|
|
2008-12-08 05:25:12 +00:00
|
|
|
}
|
|
|
|
|
2013-10-29 05:23:17 +00:00
|
|
|
VertexLoader::~VertexLoader()
|
2008-12-08 05:25:12 +00:00
|
|
|
{
|
2014-02-23 14:14:27 +00:00
|
|
|
#ifdef USE_VERTEX_LOADER_JIT
|
2008-12-19 21:24:52 +00:00
|
|
|
FreeCodeSpace();
|
2013-02-26 19:49:00 +00:00
|
|
|
#endif
|
2008-12-08 05:25:12 +00:00
|
|
|
delete m_NativeFmt;
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexLoader::CompileVertexTranslator()
|
|
|
|
{
|
|
|
|
m_VertexSize = 0;
|
|
|
|
const TVtxAttr &vtx_attr = m_VtxAttr;
|
|
|
|
|
2014-02-23 14:14:27 +00:00
|
|
|
#ifdef USE_VERTEX_LOADER_JIT
|
2008-12-19 21:24:52 +00:00
|
|
|
if (m_compiledCode)
|
2013-04-24 13:21:54 +00:00
|
|
|
PanicAlert("Trying to recompile a vertex translator");
|
2008-12-19 21:24:52 +00:00
|
|
|
|
|
|
|
m_compiledCode = GetCodePtr();
|
2013-09-22 19:48:27 +00:00
|
|
|
ABI_PushAllCalleeSavedRegsAndAdjustStack();
|
2008-12-19 21:24:52 +00:00
|
|
|
|
2008-12-08 05:25:12 +00:00
|
|
|
// Start loop here
|
|
|
|
const u8 *loop_start = GetCodePtr();
|
|
|
|
|
|
|
|
// Reset component counters if present in vertex format only.
|
|
|
|
if (m_VtxDesc.Tex0Coord || m_VtxDesc.Tex1Coord || m_VtxDesc.Tex2Coord || m_VtxDesc.Tex3Coord ||
|
2013-04-24 13:21:54 +00:00
|
|
|
m_VtxDesc.Tex4Coord || m_VtxDesc.Tex5Coord || m_VtxDesc.Tex6Coord || m_VtxDesc.Tex7Coord)
|
|
|
|
{
|
2009-01-10 23:10:33 +00:00
|
|
|
WriteSetVariable(32, &tcIndex, Imm32(0));
|
2008-12-08 05:25:12 +00:00
|
|
|
}
|
2013-04-24 13:21:54 +00:00
|
|
|
if (m_VtxDesc.Color0 || m_VtxDesc.Color1)
|
|
|
|
{
|
2009-01-10 23:10:33 +00:00
|
|
|
WriteSetVariable(32, &colIndex, Imm32(0));
|
2008-12-08 05:25:12 +00:00
|
|
|
}
|
|
|
|
if (m_VtxDesc.Tex0MatIdx || m_VtxDesc.Tex1MatIdx || m_VtxDesc.Tex2MatIdx || m_VtxDesc.Tex3MatIdx ||
|
2013-04-24 13:21:54 +00:00
|
|
|
m_VtxDesc.Tex4MatIdx || m_VtxDesc.Tex5MatIdx || m_VtxDesc.Tex6MatIdx || m_VtxDesc.Tex7MatIdx)
|
|
|
|
{
|
2009-01-10 23:10:33 +00:00
|
|
|
WriteSetVariable(32, &s_texmtxwrite, Imm32(0));
|
|
|
|
WriteSetVariable(32, &s_texmtxread, Imm32(0));
|
2008-12-08 05:25:12 +00:00
|
|
|
}
|
2014-02-23 14:14:27 +00:00
|
|
|
#else
|
|
|
|
// Reset pipeline
|
|
|
|
m_numPipelineStages = 0;
|
2008-12-08 05:25:12 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// Colors
|
2012-12-10 06:40:28 +00:00
|
|
|
const u32 col[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1};
|
2008-12-08 05:25:12 +00:00
|
|
|
// TextureCoord
|
|
|
|
// Since m_VtxDesc.Text7Coord is broken across a 32 bit word boundary, retrieve its value manually.
|
|
|
|
// If we didn't do this, the vertex format would be read as one bit offset from where it should be, making
|
|
|
|
// 01 become 00, and 10/11 become 01
|
2012-12-10 06:40:28 +00:00
|
|
|
const u32 tc[8] = {
|
2008-12-08 05:25:12 +00:00
|
|
|
m_VtxDesc.Tex0Coord, m_VtxDesc.Tex1Coord, m_VtxDesc.Tex2Coord, m_VtxDesc.Tex3Coord,
|
2012-12-10 06:40:28 +00:00
|
|
|
m_VtxDesc.Tex4Coord, m_VtxDesc.Tex5Coord, m_VtxDesc.Tex6Coord, (const u32)((m_VtxDesc.Hex >> 31) & 3)
|
2008-12-08 05:25:12 +00:00
|
|
|
};
|
2013-10-29 05:23:17 +00:00
|
|
|
|
2014-01-15 15:58:36 +00:00
|
|
|
u32 components = 0;
|
2008-12-08 05:25:12 +00:00
|
|
|
|
|
|
|
// Position in pc vertex format.
|
|
|
|
int nat_offset = 0;
|
|
|
|
PortableVertexDeclaration vtx_decl;
|
|
|
|
memset(&vtx_decl, 0, sizeof(vtx_decl));
|
2013-10-29 05:23:17 +00:00
|
|
|
|
2008-12-08 05:25:12 +00:00
|
|
|
// Position Matrix Index
|
2013-04-24 13:21:54 +00:00
|
|
|
if (m_VtxDesc.PosMatIdx)
|
|
|
|
{
|
2008-12-08 05:25:12 +00:00
|
|
|
WriteCall(PosMtx_ReadDirect_UByte);
|
2014-01-15 15:58:36 +00:00
|
|
|
components |= VB_HAS_POSMTXIDX;
|
2008-12-08 05:25:12 +00:00
|
|
|
m_VertexSize += 1;
|
|
|
|
}
|
|
|
|
|
2014-01-15 15:58:36 +00:00
|
|
|
if (m_VtxDesc.Tex0MatIdx) {m_VertexSize += 1; components |= VB_HAS_TEXMTXIDX0; WriteCall(TexMtx_ReadDirect_UByte); }
|
|
|
|
if (m_VtxDesc.Tex1MatIdx) {m_VertexSize += 1; components |= VB_HAS_TEXMTXIDX1; WriteCall(TexMtx_ReadDirect_UByte); }
|
|
|
|
if (m_VtxDesc.Tex2MatIdx) {m_VertexSize += 1; components |= VB_HAS_TEXMTXIDX2; WriteCall(TexMtx_ReadDirect_UByte); }
|
|
|
|
if (m_VtxDesc.Tex3MatIdx) {m_VertexSize += 1; components |= VB_HAS_TEXMTXIDX3; WriteCall(TexMtx_ReadDirect_UByte); }
|
|
|
|
if (m_VtxDesc.Tex4MatIdx) {m_VertexSize += 1; components |= VB_HAS_TEXMTXIDX4; WriteCall(TexMtx_ReadDirect_UByte); }
|
|
|
|
if (m_VtxDesc.Tex5MatIdx) {m_VertexSize += 1; components |= VB_HAS_TEXMTXIDX5; WriteCall(TexMtx_ReadDirect_UByte); }
|
|
|
|
if (m_VtxDesc.Tex6MatIdx) {m_VertexSize += 1; components |= VB_HAS_TEXMTXIDX6; WriteCall(TexMtx_ReadDirect_UByte); }
|
|
|
|
if (m_VtxDesc.Tex7MatIdx) {m_VertexSize += 1; components |= VB_HAS_TEXMTXIDX7; WriteCall(TexMtx_ReadDirect_UByte); }
|
2008-12-08 05:25:12 +00:00
|
|
|
|
2010-02-28 08:41:02 +00:00
|
|
|
// Write vertex position loader
|
2014-03-10 11:30:55 +00:00
|
|
|
if (g_ActiveConfig.bUseBBox)
|
2013-04-24 13:21:54 +00:00
|
|
|
{
|
2013-02-21 10:41:14 +00:00
|
|
|
WriteCall(UpdateBoundingBoxPrepare);
|
|
|
|
WriteCall(VertexLoader_Position::GetFunction(m_VtxDesc.Position, m_VtxAttr.PosFormat, m_VtxAttr.PosElements));
|
|
|
|
WriteCall(UpdateBoundingBox);
|
2013-04-24 13:21:54 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-02-21 10:41:14 +00:00
|
|
|
WriteCall(VertexLoader_Position::GetFunction(m_VtxDesc.Position, m_VtxAttr.PosFormat, m_VtxAttr.PosElements));
|
|
|
|
}
|
2010-04-09 15:13:42 +00:00
|
|
|
m_VertexSize += VertexLoader_Position::GetSize(m_VtxDesc.Position, m_VtxAttr.PosFormat, m_VtxAttr.PosElements);
|
2010-02-28 08:41:02 +00:00
|
|
|
nat_offset += 12;
|
2014-01-24 13:46:05 +00:00
|
|
|
vtx_decl.position.components = 3;
|
|
|
|
vtx_decl.position.enable = true;
|
|
|
|
vtx_decl.position.offset = 0;
|
|
|
|
vtx_decl.position.type = VAR_FLOAT;
|
|
|
|
vtx_decl.position.integer = false;
|
2008-12-08 05:25:12 +00:00
|
|
|
|
|
|
|
// Normals
|
2011-03-21 05:46:33 +00:00
|
|
|
if (m_VtxDesc.Normal != NOT_PRESENT)
|
|
|
|
{
|
|
|
|
m_VertexSize += VertexLoader_Normal::GetSize(m_VtxDesc.Normal,
|
|
|
|
m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements, m_VtxAttr.NormalIndex3);
|
2013-10-29 05:23:17 +00:00
|
|
|
|
2011-03-21 05:46:33 +00:00
|
|
|
TPipelineFunction pFunc = VertexLoader_Normal::GetFunction(m_VtxDesc.Normal,
|
|
|
|
m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements, m_VtxAttr.NormalIndex3);
|
|
|
|
|
2014-03-09 20:14:26 +00:00
|
|
|
if (pFunc == nullptr)
|
2008-12-08 05:25:12 +00:00
|
|
|
{
|
2014-02-08 01:23:34 +00:00
|
|
|
Host_SysMessage(
|
2014-03-29 10:05:44 +00:00
|
|
|
StringFromFormat("VertexLoader_Normal::GetFunction(%i %i %i %i) returned zero!",
|
|
|
|
m_VtxDesc.Normal, m_VtxAttr.NormalFormat,
|
2014-02-08 01:23:34 +00:00
|
|
|
m_VtxAttr.NormalElements, m_VtxAttr.NormalIndex3).c_str());
|
2008-12-08 05:25:12 +00:00
|
|
|
}
|
|
|
|
WriteCall(pFunc);
|
|
|
|
|
2014-01-24 14:16:52 +00:00
|
|
|
for (int i = 0; i < (vtx_attr.NormalElements ? 3 : 1); i++)
|
2013-04-24 13:21:54 +00:00
|
|
|
{
|
2014-01-24 14:16:52 +00:00
|
|
|
vtx_decl.normals[i].components = 3;
|
|
|
|
vtx_decl.normals[i].enable = true;
|
|
|
|
vtx_decl.normals[i].offset = nat_offset;
|
|
|
|
vtx_decl.normals[i].type = VAR_FLOAT;
|
|
|
|
vtx_decl.normals[i].integer = false;
|
2011-01-19 13:57:15 +00:00
|
|
|
nat_offset += 12;
|
2013-03-20 01:51:12 +00:00
|
|
|
}
|
2008-12-08 05:25:12 +00:00
|
|
|
|
2014-01-15 15:58:36 +00:00
|
|
|
components |= VB_HAS_NRM0;
|
2014-03-26 21:54:40 +00:00
|
|
|
if (m_VtxAttr.NormalElements == 1)
|
2014-01-15 15:58:36 +00:00
|
|
|
components |= VB_HAS_NRM1 | VB_HAS_NRM2;
|
2008-12-08 05:25:12 +00:00
|
|
|
}
|
|
|
|
|
2013-04-24 13:21:54 +00:00
|
|
|
for (int i = 0; i < 2; i++)
|
|
|
|
{
|
2014-01-24 14:23:50 +00:00
|
|
|
vtx_decl.colors[i].components = 4;
|
|
|
|
vtx_decl.colors[i].type = VAR_UNSIGNED_BYTE;
|
|
|
|
vtx_decl.colors[i].integer = false;
|
2008-12-08 05:25:12 +00:00
|
|
|
switch (col[i])
|
|
|
|
{
|
2013-10-29 05:23:17 +00:00
|
|
|
case NOT_PRESENT:
|
2008-12-08 05:25:12 +00:00
|
|
|
break;
|
|
|
|
case DIRECT:
|
|
|
|
switch (m_VtxAttr.color[i].Comp)
|
|
|
|
{
|
2014-02-17 04:51:41 +00:00
|
|
|
case FORMAT_16B_565: m_VertexSize += 2; WriteCall(Color_ReadDirect_16b_565); break;
|
|
|
|
case FORMAT_24B_888: m_VertexSize += 3; WriteCall(Color_ReadDirect_24b_888); break;
|
|
|
|
case FORMAT_32B_888x: m_VertexSize += 4; WriteCall(Color_ReadDirect_32b_888x); break;
|
|
|
|
case FORMAT_16B_4444: m_VertexSize += 2; WriteCall(Color_ReadDirect_16b_4444); break;
|
|
|
|
case FORMAT_24B_6666: m_VertexSize += 3; WriteCall(Color_ReadDirect_24b_6666); break;
|
|
|
|
case FORMAT_32B_8888: m_VertexSize += 4; WriteCall(Color_ReadDirect_32b_8888); break;
|
2008-12-08 05:25:12 +00:00
|
|
|
default: _assert_(0); break;
|
|
|
|
}
|
|
|
|
break;
|
2013-03-20 01:51:12 +00:00
|
|
|
case INDEX8:
|
2008-12-08 05:25:12 +00:00
|
|
|
m_VertexSize += 1;
|
|
|
|
switch (m_VtxAttr.color[i].Comp)
|
|
|
|
{
|
2014-02-17 04:51:41 +00:00
|
|
|
case FORMAT_16B_565: WriteCall(Color_ReadIndex8_16b_565); break;
|
|
|
|
case FORMAT_24B_888: WriteCall(Color_ReadIndex8_24b_888); break;
|
|
|
|
case FORMAT_32B_888x: WriteCall(Color_ReadIndex8_32b_888x); break;
|
|
|
|
case FORMAT_16B_4444: WriteCall(Color_ReadIndex8_16b_4444); break;
|
|
|
|
case FORMAT_24B_6666: WriteCall(Color_ReadIndex8_24b_6666); break;
|
|
|
|
case FORMAT_32B_8888: WriteCall(Color_ReadIndex8_32b_8888); break;
|
2008-12-08 05:25:12 +00:00
|
|
|
default: _assert_(0); break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case INDEX16:
|
|
|
|
m_VertexSize += 2;
|
|
|
|
switch (m_VtxAttr.color[i].Comp)
|
|
|
|
{
|
2014-02-17 04:51:41 +00:00
|
|
|
case FORMAT_16B_565: WriteCall(Color_ReadIndex16_16b_565); break;
|
|
|
|
case FORMAT_24B_888: WriteCall(Color_ReadIndex16_24b_888); break;
|
|
|
|
case FORMAT_32B_888x: WriteCall(Color_ReadIndex16_32b_888x); break;
|
|
|
|
case FORMAT_16B_4444: WriteCall(Color_ReadIndex16_16b_4444); break;
|
|
|
|
case FORMAT_24B_6666: WriteCall(Color_ReadIndex16_24b_6666); break;
|
|
|
|
case FORMAT_32B_8888: WriteCall(Color_ReadIndex16_32b_8888); break;
|
2008-12-08 05:25:12 +00:00
|
|
|
default: _assert_(0); break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Common for the three bottom cases
|
2013-04-24 13:21:54 +00:00
|
|
|
if (col[i] != NOT_PRESENT)
|
|
|
|
{
|
2014-01-24 14:23:50 +00:00
|
|
|
components |= VB_HAS_COL0 << i;
|
|
|
|
vtx_decl.colors[i].offset = nat_offset;
|
|
|
|
vtx_decl.colors[i].enable = true;
|
2008-12-08 05:25:12 +00:00
|
|
|
nat_offset += 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Texture matrix indices (remove if corresponding texture coordinate isn't enabled)
|
2013-04-24 13:21:54 +00:00
|
|
|
for (int i = 0; i < 8; i++)
|
|
|
|
{
|
2014-01-24 14:32:27 +00:00
|
|
|
vtx_decl.texcoords[i].offset = nat_offset;
|
|
|
|
vtx_decl.texcoords[i].type = VAR_FLOAT;
|
|
|
|
vtx_decl.texcoords[i].integer = false;
|
|
|
|
|
2010-02-28 11:36:00 +00:00
|
|
|
const int format = m_VtxAttr.texCoord[i].Format;
|
|
|
|
const int elements = m_VtxAttr.texCoord[i].Elements;
|
|
|
|
|
2013-04-24 13:21:54 +00:00
|
|
|
if (tc[i] == NOT_PRESENT)
|
|
|
|
{
|
2014-01-15 15:58:36 +00:00
|
|
|
components &= ~(VB_HAS_UV0 << i);
|
2013-04-24 13:21:54 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-02-28 11:36:00 +00:00
|
|
|
_assert_msg_(VIDEO, DIRECT <= tc[i] && tc[i] <= INDEX16, "Invalid texture coordinates!\n(tc[i] = %d)", tc[i]);
|
|
|
|
_assert_msg_(VIDEO, FORMAT_UBYTE <= format && format <= FORMAT_FLOAT, "Invalid texture coordinates format!\n(format = %d)", format);
|
2013-04-19 13:21:45 +00:00
|
|
|
_assert_msg_(VIDEO, 0 <= elements && elements <= 1, "Invalid number of texture coordinates elements!\n(elements = %d)", elements);
|
2010-02-28 11:36:00 +00:00
|
|
|
|
2014-01-15 15:58:36 +00:00
|
|
|
components |= VB_HAS_UV0 << i;
|
2010-04-09 15:13:42 +00:00
|
|
|
WriteCall(VertexLoader_TextCoord::GetFunction(tc[i], format, elements));
|
|
|
|
m_VertexSize += VertexLoader_TextCoord::GetSize(tc[i], format, elements);
|
2008-12-08 05:25:12 +00:00
|
|
|
}
|
|
|
|
|
2014-01-15 15:58:36 +00:00
|
|
|
if (components & (VB_HAS_TEXMTXIDX0 << i))
|
2013-04-24 13:21:54 +00:00
|
|
|
{
|
2014-01-24 14:32:27 +00:00
|
|
|
vtx_decl.texcoords[i].enable = true;
|
2013-04-24 13:21:54 +00:00
|
|
|
if (tc[i] != NOT_PRESENT)
|
|
|
|
{
|
2008-12-08 05:25:12 +00:00
|
|
|
// if texmtx is included, texcoord will always be 3 floats, z will be the texmtx index
|
2014-01-24 14:32:27 +00:00
|
|
|
vtx_decl.texcoords[i].components = 3;
|
2008-12-08 05:25:12 +00:00
|
|
|
nat_offset += 12;
|
|
|
|
WriteCall(m_VtxAttr.texCoord[i].Elements ? TexMtx_Write_Float : TexMtx_Write_Float2);
|
|
|
|
}
|
2013-04-24 13:21:54 +00:00
|
|
|
else
|
|
|
|
{
|
2014-01-15 15:58:36 +00:00
|
|
|
components |= VB_HAS_UV0 << i; // have to include since using now
|
2014-01-24 14:32:27 +00:00
|
|
|
vtx_decl.texcoords[i].components = 4;
|
2010-01-12 00:08:02 +00:00
|
|
|
nat_offset += 16; // still include the texture coordinate, but this time as 6 + 2 bytes
|
|
|
|
WriteCall(TexMtx_Write_Float4);
|
2008-12-08 05:25:12 +00:00
|
|
|
}
|
|
|
|
}
|
2013-04-24 13:21:54 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (tc[i] != NOT_PRESENT)
|
|
|
|
{
|
2014-01-24 14:32:27 +00:00
|
|
|
vtx_decl.texcoords[i].enable = true;
|
|
|
|
vtx_decl.texcoords[i].components = vtx_attr.texCoord[i].Elements ? 2 : 1;
|
2008-12-08 05:25:12 +00:00
|
|
|
nat_offset += 4 * (vtx_attr.texCoord[i].Elements ? 2 : 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-24 13:21:54 +00:00
|
|
|
if (tc[i] == NOT_PRESENT)
|
|
|
|
{
|
2013-10-29 05:23:17 +00:00
|
|
|
// if there's more tex coords later, have to write a dummy call
|
2008-12-08 05:25:12 +00:00
|
|
|
int j = i + 1;
|
2013-04-24 13:21:54 +00:00
|
|
|
for (; j < 8; ++j)
|
|
|
|
{
|
|
|
|
if (tc[j] != NOT_PRESENT)
|
|
|
|
{
|
2010-04-09 15:13:42 +00:00
|
|
|
WriteCall(VertexLoader_TextCoord::GetDummyFunction()); // important to get indices right!
|
2008-12-08 05:25:12 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// tricky!
|
2014-01-15 15:58:36 +00:00
|
|
|
if (j == 8 && !((components & VB_HAS_TEXMTXIDXALL) & (VB_HAS_TEXMTXIDXALL << (i + 1))))
|
2013-04-24 13:21:54 +00:00
|
|
|
{
|
2008-12-08 05:25:12 +00:00
|
|
|
// no more tex coords and tex matrices, so exit loop
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-24 13:21:54 +00:00
|
|
|
if (m_VtxDesc.PosMatIdx)
|
|
|
|
{
|
2008-12-08 05:25:12 +00:00
|
|
|
WriteCall(PosMtx_Write);
|
2014-01-24 14:41:08 +00:00
|
|
|
vtx_decl.posmtx.components = 4;
|
|
|
|
vtx_decl.posmtx.enable = true;
|
|
|
|
vtx_decl.posmtx.offset = nat_offset;
|
|
|
|
vtx_decl.posmtx.type = VAR_UNSIGNED_BYTE;
|
2014-04-24 07:30:05 +00:00
|
|
|
vtx_decl.posmtx.integer = true;
|
2008-12-08 05:25:12 +00:00
|
|
|
nat_offset += 4;
|
2013-04-24 13:21:54 +00:00
|
|
|
}
|
2008-12-08 05:25:12 +00:00
|
|
|
|
|
|
|
native_stride = nat_offset;
|
|
|
|
vtx_decl.stride = native_stride;
|
|
|
|
|
2014-02-23 14:14:27 +00:00
|
|
|
#ifdef USE_VERTEX_LOADER_JIT
|
2008-12-08 05:25:12 +00:00
|
|
|
// End loop here
|
2014-03-02 11:21:50 +00:00
|
|
|
#if _M_X86_64
|
2009-01-10 23:10:33 +00:00
|
|
|
MOV(64, R(RAX), Imm64((u64)&loop_counter));
|
|
|
|
SUB(32, MatR(RAX), Imm8(1));
|
|
|
|
#else
|
2008-12-08 05:25:12 +00:00
|
|
|
SUB(32, M(&loop_counter), Imm8(1));
|
2009-01-10 23:10:33 +00:00
|
|
|
#endif
|
|
|
|
|
2008-12-08 05:25:12 +00:00
|
|
|
J_CC(CC_NZ, loop_start, true);
|
2013-09-22 19:48:27 +00:00
|
|
|
ABI_PopAllCalleeSavedRegsAndAdjustStack();
|
|
|
|
RET();
|
2008-12-08 05:25:12 +00:00
|
|
|
#endif
|
2014-01-15 15:58:36 +00:00
|
|
|
m_NativeFmt = g_vertex_manager->CreateNativeVertexFormat();
|
|
|
|
m_NativeFmt->m_components = components;
|
2008-12-08 05:25:12 +00:00
|
|
|
m_NativeFmt->Initialize(vtx_decl);
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexLoader::WriteCall(TPipelineFunction func)
|
|
|
|
{
|
2014-02-23 14:14:27 +00:00
|
|
|
#ifdef USE_VERTEX_LOADER_JIT
|
2014-03-02 11:21:50 +00:00
|
|
|
#if _M_X86_64
|
2009-01-10 23:10:33 +00:00
|
|
|
MOV(64, R(RAX), Imm64((u64)func));
|
|
|
|
CALLptr(R(RAX));
|
|
|
|
#else
|
2008-12-08 05:25:12 +00:00
|
|
|
CALL((void*)func);
|
2009-01-10 23:10:33 +00:00
|
|
|
#endif
|
2008-12-08 05:25:12 +00:00
|
|
|
#else
|
|
|
|
m_PipelineStages[m_numPipelineStages++] = func;
|
|
|
|
#endif
|
|
|
|
}
|
2013-02-26 19:49:00 +00:00
|
|
|
// ARMTODO: This should be done in a better way
|
|
|
|
#ifndef _M_GENERIC
|
2009-01-10 23:10:33 +00:00
|
|
|
void VertexLoader::WriteGetVariable(int bits, OpArg dest, void *address)
|
|
|
|
{
|
2014-02-23 14:14:27 +00:00
|
|
|
#ifdef USE_VERTEX_LOADER_JIT
|
2014-03-02 11:21:50 +00:00
|
|
|
#if _M_X86_64
|
2009-01-10 23:10:33 +00:00
|
|
|
MOV(64, R(RAX), Imm64((u64)address));
|
|
|
|
MOV(bits, dest, MatR(RAX));
|
|
|
|
#else
|
|
|
|
MOV(bits, dest, M(address));
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexLoader::WriteSetVariable(int bits, void *address, OpArg value)
|
|
|
|
{
|
2014-02-23 14:14:27 +00:00
|
|
|
#ifdef USE_VERTEX_LOADER_JIT
|
2014-03-02 11:21:50 +00:00
|
|
|
#if _M_X86_64
|
2009-01-10 23:10:33 +00:00
|
|
|
MOV(64, R(RAX), Imm64((u64)address));
|
|
|
|
MOV(bits, MatR(RAX), value);
|
|
|
|
#else
|
|
|
|
MOV(bits, M(address), value);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
2013-02-26 19:49:00 +00:00
|
|
|
#endif
|
2009-01-10 23:10:33 +00:00
|
|
|
|
2014-01-30 13:48:23 +00:00
|
|
|
void VertexLoader::SetupRunVertices(int vtx_attr_group, int primitive, int const count)
|
2008-12-08 05:25:12 +00:00
|
|
|
{
|
|
|
|
m_numLoadedVertices += count;
|
2011-03-04 22:48:54 +00:00
|
|
|
|
2008-12-08 05:25:12 +00:00
|
|
|
// Flush if our vertex format is different from the currently set.
|
2014-03-09 20:14:26 +00:00
|
|
|
if (g_nativeVertexFmt != nullptr && g_nativeVertexFmt != m_NativeFmt)
|
2008-12-08 05:25:12 +00:00
|
|
|
{
|
2009-09-26 21:00:04 +00:00
|
|
|
// We really must flush here. It's possible that the native representations
|
2013-10-29 05:23:17 +00:00
|
|
|
// of the two vtx formats are the same, but we have no way to easily check that
|
|
|
|
// now.
|
2009-09-26 21:00:04 +00:00
|
|
|
VertexManager::Flush();
|
2011-03-04 22:48:54 +00:00
|
|
|
// Also move the Set() here?
|
|
|
|
}
|
|
|
|
g_nativeVertexFmt = m_NativeFmt;
|
|
|
|
|
2008-12-08 05:25:12 +00:00
|
|
|
// Load position and texcoord scale factors.
|
2014-02-16 20:30:18 +00:00
|
|
|
m_VtxAttr.PosFrac = g_VtxAttr[vtx_attr_group].g0.PosFrac;
|
|
|
|
m_VtxAttr.texCoord[0].Frac = g_VtxAttr[vtx_attr_group].g0.Tex0Frac;
|
|
|
|
m_VtxAttr.texCoord[1].Frac = g_VtxAttr[vtx_attr_group].g1.Tex1Frac;
|
|
|
|
m_VtxAttr.texCoord[2].Frac = g_VtxAttr[vtx_attr_group].g1.Tex2Frac;
|
|
|
|
m_VtxAttr.texCoord[3].Frac = g_VtxAttr[vtx_attr_group].g1.Tex3Frac;
|
|
|
|
m_VtxAttr.texCoord[4].Frac = g_VtxAttr[vtx_attr_group].g2.Tex4Frac;
|
|
|
|
m_VtxAttr.texCoord[5].Frac = g_VtxAttr[vtx_attr_group].g2.Tex5Frac;
|
|
|
|
m_VtxAttr.texCoord[6].Frac = g_VtxAttr[vtx_attr_group].g2.Tex6Frac;
|
|
|
|
m_VtxAttr.texCoord[7].Frac = g_VtxAttr[vtx_attr_group].g2.Tex7Frac;
|
2008-12-08 05:25:12 +00:00
|
|
|
|
|
|
|
pVtxAttr = &m_VtxAttr;
|
2010-09-14 13:52:17 +00:00
|
|
|
posScale = fractionTable[m_VtxAttr.PosFrac];
|
2010-02-24 23:58:48 +00:00
|
|
|
if (m_NativeFmt->m_components & VB_HAS_UVALL)
|
|
|
|
for (int i = 0; i < 8; i++)
|
2010-09-14 13:52:17 +00:00
|
|
|
tcScale[i] = fractionTable[m_VtxAttr.texCoord[i].Frac];
|
2008-12-08 05:25:12 +00:00
|
|
|
for (int i = 0; i < 2; i++)
|
|
|
|
colElements[i] = m_VtxAttr.color[i].Elements;
|
2011-03-04 22:48:54 +00:00
|
|
|
|
Rewrote bounding box algotithm. Fixes issues 5967, 6154, 6196, 6211.
Instead of being vertex-based, it is now primitive (point, line or dissected triangle) based, with proper clipping.
Also, screen position is now calculated based on viewport values, instead of "guesstimating".
This fixes many graphical glitches in Paper Mario: TTYD and Super Paper Mario.
Also, the new code allows Mickey's Magical Mirror and Disney's Hide & Sneak to work (mostly) bug-free. I changed their inis to use bbox.
These changes have a slight cost in performance when bbox is being used (rare), mostly due to the new clipping algorithm.
Please check for any regressions or crashes.
2014-01-25 15:36:23 +00:00
|
|
|
// Prepare bounding box
|
|
|
|
s_bbox_primitive = primitive;
|
|
|
|
s_bbox_currPoint = 0;
|
|
|
|
s_bbox_loadedPoints = 0;
|
2008-12-08 05:25:12 +00:00
|
|
|
}
|
|
|
|
|
2013-02-21 10:36:10 +00:00
|
|
|
void VertexLoader::ConvertVertices ( int count )
|
|
|
|
{
|
2014-02-23 14:14:27 +00:00
|
|
|
#ifdef USE_VERTEX_LOADER_JIT
|
2013-04-24 13:21:54 +00:00
|
|
|
if (count > 0)
|
|
|
|
{
|
2013-02-21 10:36:10 +00:00
|
|
|
loop_counter = count;
|
|
|
|
((void (*)())(void*)m_compiledCode)();
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
for (int s = 0; s < count; s++)
|
|
|
|
{
|
|
|
|
tcIndex = 0;
|
|
|
|
colIndex = 0;
|
|
|
|
s_texmtxwrite = s_texmtxread = 0;
|
|
|
|
for (int i = 0; i < m_numPipelineStages; i++)
|
|
|
|
m_PipelineStages[i]();
|
|
|
|
PRIM_LOG("\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-01-30 13:48:23 +00:00
|
|
|
void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int const count)
|
|
|
|
{
|
|
|
|
if (bpmem.genMode.cullmode == 3 && primitive < 5)
|
|
|
|
{
|
|
|
|
// if cull mode is none, ignore triangles and quads
|
|
|
|
DataSkip(count * m_VertexSize);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
SetupRunVertices(vtx_attr_group, primitive, count);
|
|
|
|
VertexManager::PrepareForAdditionalData(primitive, count, native_stride);
|
|
|
|
ConvertVertices(count);
|
|
|
|
IndexGenerator::AddIndices(primitive, count);
|
|
|
|
|
|
|
|
ADDSTAT(stats.thisFrame.numPrims, count);
|
|
|
|
INCSTAT(stats.thisFrame.numPrimitiveJoins);
|
|
|
|
}
|
|
|
|
|
2013-10-29 05:23:17 +00:00
|
|
|
void VertexLoader::SetVAT(u32 _group0, u32 _group1, u32 _group2)
|
2008-12-08 05:25:12 +00:00
|
|
|
{
|
|
|
|
VAT vat;
|
|
|
|
vat.g0.Hex = _group0;
|
|
|
|
vat.g1.Hex = _group1;
|
|
|
|
vat.g2.Hex = _group2;
|
|
|
|
|
2014-02-16 20:30:18 +00:00
|
|
|
m_VtxAttr.PosElements = vat.g0.PosElements;
|
|
|
|
m_VtxAttr.PosFormat = vat.g0.PosFormat;
|
|
|
|
m_VtxAttr.PosFrac = vat.g0.PosFrac;
|
|
|
|
m_VtxAttr.NormalElements = vat.g0.NormalElements;
|
|
|
|
m_VtxAttr.NormalFormat = vat.g0.NormalFormat;
|
|
|
|
m_VtxAttr.color[0].Elements = vat.g0.Color0Elements;
|
|
|
|
m_VtxAttr.color[0].Comp = vat.g0.Color0Comp;
|
|
|
|
m_VtxAttr.color[1].Elements = vat.g0.Color1Elements;
|
|
|
|
m_VtxAttr.color[1].Comp = vat.g0.Color1Comp;
|
|
|
|
m_VtxAttr.texCoord[0].Elements = vat.g0.Tex0CoordElements;
|
|
|
|
m_VtxAttr.texCoord[0].Format = vat.g0.Tex0CoordFormat;
|
|
|
|
m_VtxAttr.texCoord[0].Frac = vat.g0.Tex0Frac;
|
|
|
|
m_VtxAttr.ByteDequant = vat.g0.ByteDequant;
|
|
|
|
m_VtxAttr.NormalIndex3 = vat.g0.NormalIndex3;
|
|
|
|
|
|
|
|
m_VtxAttr.texCoord[1].Elements = vat.g1.Tex1CoordElements;
|
|
|
|
m_VtxAttr.texCoord[1].Format = vat.g1.Tex1CoordFormat;
|
|
|
|
m_VtxAttr.texCoord[1].Frac = vat.g1.Tex1Frac;
|
|
|
|
m_VtxAttr.texCoord[2].Elements = vat.g1.Tex2CoordElements;
|
|
|
|
m_VtxAttr.texCoord[2].Format = vat.g1.Tex2CoordFormat;
|
|
|
|
m_VtxAttr.texCoord[2].Frac = vat.g1.Tex2Frac;
|
|
|
|
m_VtxAttr.texCoord[3].Elements = vat.g1.Tex3CoordElements;
|
|
|
|
m_VtxAttr.texCoord[3].Format = vat.g1.Tex3CoordFormat;
|
|
|
|
m_VtxAttr.texCoord[3].Frac = vat.g1.Tex3Frac;
|
|
|
|
m_VtxAttr.texCoord[4].Elements = vat.g1.Tex4CoordElements;
|
|
|
|
m_VtxAttr.texCoord[4].Format = vat.g1.Tex4CoordFormat;
|
|
|
|
|
|
|
|
m_VtxAttr.texCoord[4].Frac = vat.g2.Tex4Frac;
|
|
|
|
m_VtxAttr.texCoord[5].Elements = vat.g2.Tex5CoordElements;
|
|
|
|
m_VtxAttr.texCoord[5].Format = vat.g2.Tex5CoordFormat;
|
|
|
|
m_VtxAttr.texCoord[5].Frac = vat.g2.Tex5Frac;
|
|
|
|
m_VtxAttr.texCoord[6].Elements = vat.g2.Tex6CoordElements;
|
|
|
|
m_VtxAttr.texCoord[6].Format = vat.g2.Tex6CoordFormat;
|
|
|
|
m_VtxAttr.texCoord[6].Frac = vat.g2.Tex6Frac;
|
|
|
|
m_VtxAttr.texCoord[7].Elements = vat.g2.Tex7CoordElements;
|
|
|
|
m_VtxAttr.texCoord[7].Format = vat.g2.Tex7CoordFormat;
|
|
|
|
m_VtxAttr.texCoord[7].Frac = vat.g2.Tex7Frac;
|
2013-10-29 05:23:17 +00:00
|
|
|
|
2014-03-10 11:30:55 +00:00
|
|
|
if (!m_VtxAttr.ByteDequant) {
|
2013-03-29 13:27:33 +00:00
|
|
|
ERROR_LOG(VIDEO, "ByteDequant is set to zero");
|
|
|
|
}
|
2008-12-08 05:25:12 +00:00
|
|
|
};
|
|
|
|
|
2009-02-15 12:38:25 +00:00
|
|
|
void VertexLoader::AppendToString(std::string *dest) const
|
2009-02-06 19:52:23 +00:00
|
|
|
{
|
2009-02-09 20:35:30 +00:00
|
|
|
dest->reserve(250);
|
2008-12-08 05:25:12 +00:00
|
|
|
static const char *posMode[4] = {
|
2009-02-06 19:52:23 +00:00
|
|
|
"Inv",
|
|
|
|
"Dir",
|
2009-02-09 20:35:30 +00:00
|
|
|
"I8",
|
2009-02-06 19:52:23 +00:00
|
|
|
"I16",
|
2008-12-08 05:25:12 +00:00
|
|
|
};
|
|
|
|
static const char *posFormats[5] = {
|
2009-02-09 20:35:30 +00:00
|
|
|
"u8", "s8", "u16", "s16", "flt",
|
2009-02-06 19:52:23 +00:00
|
|
|
};
|
2009-02-09 20:35:30 +00:00
|
|
|
static const char *colorFormat[8] = {
|
|
|
|
"565",
|
|
|
|
"888",
|
|
|
|
"888x",
|
|
|
|
"4444",
|
|
|
|
"6666",
|
|
|
|
"8888",
|
|
|
|
"Inv",
|
|
|
|
"Inv",
|
|
|
|
};
|
|
|
|
|
|
|
|
dest->append(StringFromFormat("%ib skin: %i P: %i %s-%s ",
|
2009-02-06 19:52:23 +00:00
|
|
|
m_VertexSize, m_VtxDesc.PosMatIdx,
|
|
|
|
m_VtxAttr.PosElements ? 3 : 2, posMode[m_VtxDesc.Position], posFormats[m_VtxAttr.PosFormat]));
|
2013-04-24 13:21:54 +00:00
|
|
|
|
|
|
|
if (m_VtxDesc.Normal)
|
|
|
|
{
|
2009-02-09 20:35:30 +00:00
|
|
|
dest->append(StringFromFormat("Nrm: %i %s-%s ",
|
|
|
|
m_VtxAttr.NormalElements, posMode[m_VtxDesc.Normal], posFormats[m_VtxAttr.NormalFormat]));
|
|
|
|
}
|
2013-04-24 13:21:54 +00:00
|
|
|
|
2012-12-10 06:40:28 +00:00
|
|
|
u32 color_mode[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1};
|
2009-02-09 20:35:30 +00:00
|
|
|
for (int i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
if (color_mode[i])
|
|
|
|
{
|
|
|
|
dest->append(StringFromFormat("C%i: %i %s-%s ", i, m_VtxAttr.color[i].Elements, posMode[color_mode[i]], colorFormat[m_VtxAttr.color[i].Comp]));
|
|
|
|
}
|
|
|
|
}
|
2012-12-10 06:40:28 +00:00
|
|
|
u32 tex_mode[8] = {
|
2013-10-29 05:23:17 +00:00
|
|
|
m_VtxDesc.Tex0Coord, m_VtxDesc.Tex1Coord, m_VtxDesc.Tex2Coord, m_VtxDesc.Tex3Coord,
|
2009-02-06 19:52:23 +00:00
|
|
|
m_VtxDesc.Tex4Coord, m_VtxDesc.Tex5Coord, m_VtxDesc.Tex6Coord, m_VtxDesc.Tex7Coord
|
2008-12-08 05:25:12 +00:00
|
|
|
};
|
2009-02-06 19:52:23 +00:00
|
|
|
for (int i = 0; i < 8; i++)
|
|
|
|
{
|
|
|
|
if (tex_mode[i])
|
|
|
|
{
|
2009-02-09 20:35:30 +00:00
|
|
|
dest->append(StringFromFormat("T%i: %i %s-%s ",
|
2009-02-06 19:52:23 +00:00
|
|
|
i, m_VtxAttr.texCoord[i].Elements, posMode[tex_mode[i]], posFormats[m_VtxAttr.texCoord[i].Format]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dest->append(StringFromFormat(" - %i v\n", m_numLoadedVertices));
|
2008-12-08 05:25:12 +00:00
|
|
|
}
|