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-09-08 01:06:58 +00:00
|
|
|
#include "Common/CommonTypes.h"
|
2014-02-17 10:18:15 +00:00
|
|
|
#include "Common/MemoryUtil.h"
|
|
|
|
#include "Common/StringUtil.h"
|
|
|
|
#include "Common/x64ABI.h"
|
|
|
|
#include "Common/x64Emitter.h"
|
|
|
|
|
|
|
|
#include "Core/Host.h"
|
|
|
|
|
2014-09-17 01:04:37 +00:00
|
|
|
#include "VideoCommon/BoundingBox.h"
|
2014-02-17 10:18:15 +00:00
|
|
|
#include "VideoCommon/DataReader.h"
|
|
|
|
#include "VideoCommon/LookUpTables.h"
|
|
|
|
#include "VideoCommon/PixelEngine.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"
|
|
|
|
#include "VideoCommon/VideoCommon.h"
|
|
|
|
#include "VideoCommon/VideoConfig.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
|
|
|
|
|
|
|
#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-08-27 17:26:06 +00:00
|
|
|
static u8 s_curposmtx = g_main_cp_state.matrix_index_a.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
|
|
|
// Vertex loaders read these. Although the scale ones should be baked into the shader.
|
|
|
|
int tcIndex;
|
|
|
|
int colIndex;
|
|
|
|
int colElements[2];
|
|
|
|
float posScale;
|
2010-02-24 23:58:48 +00:00
|
|
|
float tcScale[8];
|
2008-12-08 05:25:12 +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;
|
|
|
|
|
2014-07-08 12:29:26 +00:00
|
|
|
static void LOADERDECL PosMtx_ReadDirect_UByte()
|
2008-12-08 05:25:12 +00:00
|
|
|
{
|
2014-09-14 16:52:51 +00:00
|
|
|
BoundingBox::posMtxIdx = s_curposmtx = DataReadU8() & 0x3f;
|
2008-12-08 05:25:12 +00:00
|
|
|
PRIM_LOG("posmtx: %d, ", s_curposmtx);
|
|
|
|
}
|
|
|
|
|
2014-07-08 12:29:26 +00:00
|
|
|
static void LOADERDECL PosMtx_Write()
|
2008-12-08 05:25:12 +00:00
|
|
|
{
|
2013-02-22 08:19:59 +00:00
|
|
|
DataWrite<u8>(s_curposmtx);
|
|
|
|
DataWrite<u8>(0);
|
|
|
|
DataWrite<u8>(0);
|
|
|
|
DataWrite<u8>(0);
|
2009-06-28 20:04:07 +00:00
|
|
|
}
|
|
|
|
|
2014-07-08 12:29:26 +00:00
|
|
|
static void LOADERDECL TexMtx_ReadDirect_UByte()
|
2008-12-08 05:25:12 +00:00
|
|
|
{
|
2014-09-14 16:52:51 +00:00
|
|
|
BoundingBox::texMtxIdx[s_texmtxread] = 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++;
|
|
|
|
}
|
|
|
|
|
2014-07-08 12:29:26 +00:00
|
|
|
static void LOADERDECL TexMtx_Write_Float()
|
2008-12-08 05:25:12 +00:00
|
|
|
{
|
2013-02-22 08:19:59 +00:00
|
|
|
DataWrite(float(s_curtexmtx[s_texmtxwrite++]));
|
2008-12-08 05:25:12 +00:00
|
|
|
}
|
|
|
|
|
2014-07-08 12:29:26 +00:00
|
|
|
static void LOADERDECL TexMtx_Write_Float2()
|
2008-12-08 05:25:12 +00:00
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
2014-07-08 12:29:26 +00:00
|
|
|
static 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-08-25 03:53:28 +00:00
|
|
|
m_native_vertex_format = nullptr;
|
2008-12-08 05:25:12 +00:00
|
|
|
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;
|
2014-07-23 23:25:23 +00:00
|
|
|
SetVAT(vtx_attr);
|
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
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
2014-08-27 03:17:51 +00:00
|
|
|
// We only use RAX (caller saved) and RBX (callee saved).
|
2014-10-17 02:21:55 +00:00
|
|
|
ABI_PushRegistersAndAdjustStack({RBX}, 8);
|
2014-08-27 03:17:51 +00:00
|
|
|
|
|
|
|
// save count
|
|
|
|
MOV(64, R(RBX), R(ABI_PARAM1));
|
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
|
|
|
|
|
2014-09-14 16:52:51 +00:00
|
|
|
// Get the pointer to this vertex's buffer data for the bounding box
|
2014-10-15 18:02:54 +00:00
|
|
|
WriteCall(BoundingBox::SetVertexBufferPosition);
|
2014-09-14 16:52:51 +00:00
|
|
|
|
2008-12-08 05:25:12 +00:00
|
|
|
// Colors
|
2014-09-01 09:00:25 +00:00
|
|
|
const u64 col[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1};
|
2008-12-08 05:25:12 +00:00
|
|
|
// TextureCoord
|
2014-09-01 09:00:25 +00:00
|
|
|
const u64 tc[8] = {
|
2008-12-08 05:25:12 +00:00
|
|
|
m_VtxDesc.Tex0Coord, m_VtxDesc.Tex1Coord, m_VtxDesc.Tex2Coord, m_VtxDesc.Tex3Coord,
|
2014-09-01 09:00:25 +00:00
|
|
|
m_VtxDesc.Tex4Coord, m_VtxDesc.Tex5Coord, m_VtxDesc.Tex6Coord, m_VtxDesc.Tex7Coord
|
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;
|
2014-07-25 23:10:44 +00:00
|
|
|
memset(&m_native_vtx_decl, 0, sizeof(m_native_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-09-14 16:52:51 +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-07-25 23:10:44 +00:00
|
|
|
m_native_vtx_decl.position.components = 3;
|
|
|
|
m_native_vtx_decl.position.enable = true;
|
|
|
|
m_native_vtx_decl.position.offset = 0;
|
|
|
|
m_native_vtx_decl.position.type = VAR_FLOAT;
|
|
|
|
m_native_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!",
|
2014-09-01 09:00:25 +00:00
|
|
|
(u32)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-07-25 23:10:44 +00:00
|
|
|
m_native_vtx_decl.normals[i].components = 3;
|
|
|
|
m_native_vtx_decl.normals[i].enable = true;
|
|
|
|
m_native_vtx_decl.normals[i].offset = nat_offset;
|
|
|
|
m_native_vtx_decl.normals[i].type = VAR_FLOAT;
|
|
|
|
m_native_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-07-25 23:10:44 +00:00
|
|
|
m_native_vtx_decl.colors[i].components = 4;
|
|
|
|
m_native_vtx_decl.colors[i].type = VAR_UNSIGNED_BYTE;
|
|
|
|
m_native_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;
|
2014-07-25 23:10:44 +00:00
|
|
|
m_native_vtx_decl.colors[i].offset = nat_offset;
|
|
|
|
m_native_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-07-25 23:10:44 +00:00
|
|
|
m_native_vtx_decl.texcoords[i].offset = nat_offset;
|
|
|
|
m_native_vtx_decl.texcoords[i].type = VAR_FLOAT;
|
|
|
|
m_native_vtx_decl.texcoords[i].integer = false;
|
2014-01-24 14:32:27 +00:00
|
|
|
|
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
|
|
|
|
{
|
2014-09-01 09:00:25 +00:00
|
|
|
_assert_msg_(VIDEO, DIRECT <= tc[i] && tc[i] <= INDEX16, "Invalid texture coordinates!\n(tc[i] = %d)", (u32)tc[i]);
|
2010-02-28 11:36:00 +00:00
|
|
|
_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-07-25 23:10:44 +00:00
|
|
|
m_native_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-07-25 23:10:44 +00:00
|
|
|
m_native_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-07-25 23:10:44 +00:00
|
|
|
m_native_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-07-25 23:10:44 +00:00
|
|
|
m_native_vtx_decl.texcoords[i].enable = true;
|
|
|
|
m_native_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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-14 16:52:51 +00:00
|
|
|
// Update the bounding box
|
2014-10-15 18:02:54 +00:00
|
|
|
WriteCall(BoundingBox::Update);
|
2014-09-14 16:52:51 +00:00
|
|
|
|
2013-04-24 13:21:54 +00:00
|
|
|
if (m_VtxDesc.PosMatIdx)
|
|
|
|
{
|
2008-12-08 05:25:12 +00:00
|
|
|
WriteCall(PosMtx_Write);
|
2014-07-25 23:10:44 +00:00
|
|
|
m_native_vtx_decl.posmtx.components = 4;
|
|
|
|
m_native_vtx_decl.posmtx.enable = true;
|
|
|
|
m_native_vtx_decl.posmtx.offset = nat_offset;
|
|
|
|
m_native_vtx_decl.posmtx.type = VAR_UNSIGNED_BYTE;
|
|
|
|
m_native_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
|
|
|
|
2014-07-25 23:10:44 +00:00
|
|
|
m_native_components = components;
|
|
|
|
m_native_vtx_decl.stride = nat_offset;
|
2008-12-08 05:25:12 +00:00
|
|
|
|
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-08-27 03:17:51 +00:00
|
|
|
SUB(64, R(RBX), Imm8(1));
|
2009-01-10 23:10:33 +00:00
|
|
|
|
2014-06-03 20:57:17 +00:00
|
|
|
J_CC(CC_NZ, loop_start);
|
2014-10-17 02:21:55 +00:00
|
|
|
ABI_PopRegistersAndAdjustStack({RBX}, 8);
|
2013-09-22 19:48:27 +00:00
|
|
|
RET();
|
2008-12-08 05:25:12 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexLoader::WriteCall(TPipelineFunction func)
|
|
|
|
{
|
2014-02-23 14:14:27 +00:00
|
|
|
#ifdef USE_VERTEX_LOADER_JIT
|
2009-01-10 23:10:33 +00:00
|
|
|
MOV(64, R(RAX), Imm64((u64)func));
|
|
|
|
CALLptr(R(RAX));
|
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
|
2009-01-10 23:10:33 +00:00
|
|
|
MOV(64, R(RAX), Imm64((u64)address));
|
|
|
|
MOV(bits, dest, MatR(RAX));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexLoader::WriteSetVariable(int bits, void *address, OpArg value)
|
|
|
|
{
|
2014-02-23 14:14:27 +00:00
|
|
|
#ifdef USE_VERTEX_LOADER_JIT
|
2009-01-10 23:10:33 +00:00
|
|
|
MOV(64, R(RAX), Imm64((u64)address));
|
|
|
|
MOV(bits, MatR(RAX), value);
|
|
|
|
#endif
|
|
|
|
}
|
2013-02-26 19:49:00 +00:00
|
|
|
#endif
|
2009-01-10 23:10:33 +00:00
|
|
|
|
2014-07-23 23:51:37 +00:00
|
|
|
void VertexLoader::SetupRunVertices(const VAT& vat, 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
|
|
|
// Load position and texcoord scale factors.
|
2014-07-23 23:51:37 +00:00
|
|
|
m_VtxAttr.PosFrac = vat.g0.PosFrac;
|
|
|
|
m_VtxAttr.texCoord[0].Frac = vat.g0.Tex0Frac;
|
|
|
|
m_VtxAttr.texCoord[1].Frac = vat.g1.Tex1Frac;
|
|
|
|
m_VtxAttr.texCoord[2].Frac = vat.g1.Tex2Frac;
|
|
|
|
m_VtxAttr.texCoord[3].Frac = vat.g1.Tex3Frac;
|
|
|
|
m_VtxAttr.texCoord[4].Frac = vat.g2.Tex4Frac;
|
|
|
|
m_VtxAttr.texCoord[5].Frac = vat.g2.Tex5Frac;
|
|
|
|
m_VtxAttr.texCoord[6].Frac = vat.g2.Tex6Frac;
|
|
|
|
m_VtxAttr.texCoord[7].Frac = vat.g2.Tex7Frac;
|
2008-12-08 05:25:12 +00:00
|
|
|
|
2010-09-14 13:52:17 +00:00
|
|
|
posScale = fractionTable[m_VtxAttr.PosFrac];
|
2014-07-25 23:10:44 +00:00
|
|
|
if (m_native_components & VB_HAS_UVALL)
|
2010-02-24 23:58:48 +00:00
|
|
|
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
|
2014-09-14 16:52:51 +00:00
|
|
|
BoundingBox::Prepare(vat, primitive, m_VtxDesc, m_native_vtx_decl);
|
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)
|
|
|
|
{
|
2014-08-27 03:17:51 +00:00
|
|
|
((void (*)(int))(void*)m_compiledCode)(count);
|
2013-02-21 10:36:10 +00:00
|
|
|
}
|
|
|
|
#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-07-23 23:51:37 +00:00
|
|
|
void VertexLoader::RunVertices(const VAT& vat, int primitive, int const count)
|
2014-01-30 13:48:23 +00:00
|
|
|
{
|
2014-07-23 23:51:37 +00:00
|
|
|
SetupRunVertices(vat, primitive, count);
|
2014-01-30 13:48:23 +00:00
|
|
|
ConvertVertices(count);
|
|
|
|
}
|
|
|
|
|
2014-07-23 23:25:23 +00:00
|
|
|
void VertexLoader::SetVAT(const VAT& vat)
|
2008-12-08 05:25:12 +00:00
|
|
|
{
|
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-08-30 20:51:27 +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 ",
|
2014-09-01 09:00:25 +00:00
|
|
|
m_VertexSize, (u32)m_VtxDesc.PosMatIdx,
|
2009-02-06 19:52:23 +00:00
|
|
|
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
|
|
|
|
2014-09-01 09:00:25 +00:00
|
|
|
u64 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]));
|
|
|
|
}
|
|
|
|
}
|
2014-09-01 09:00:25 +00:00
|
|
|
u64 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
|
|
|
}
|
2014-08-25 03:53:28 +00:00
|
|
|
|
|
|
|
NativeVertexFormat* VertexLoader::GetNativeVertexFormat()
|
|
|
|
{
|
|
|
|
if (m_native_vertex_format)
|
|
|
|
return m_native_vertex_format;
|
|
|
|
auto& native = s_native_vertex_map[m_native_vtx_decl];
|
|
|
|
if (!native)
|
|
|
|
{
|
|
|
|
auto raw_pointer = g_vertex_manager->CreateNativeVertexFormat();
|
|
|
|
native = std::unique_ptr<NativeVertexFormat>(raw_pointer);
|
|
|
|
native->Initialize(m_native_vtx_decl);
|
|
|
|
native->m_components = m_native_components;
|
|
|
|
}
|
|
|
|
m_native_vertex_format = native.get();
|
|
|
|
return native.get();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-08-28 02:37:08 +00:00
|
|
|
std::unordered_map<PortableVertexDeclaration, std::unique_ptr<NativeVertexFormat>> VertexLoader::s_native_vertex_map;
|