2010-10-03 10:20:24 +02:00
|
|
|
|
|
|
|
#include "Common.h"
|
|
|
|
|
|
|
|
#include "Statistics.h"
|
|
|
|
#include "OpcodeDecoding.h"
|
|
|
|
#include "IndexGenerator.h"
|
2010-10-20 00:24:27 +02:00
|
|
|
#include "VertexShaderManager.h"
|
|
|
|
#include "PixelShaderManager.h"
|
|
|
|
#include "NativeVertexFormat.h"
|
|
|
|
#include "TextureCacheBase.h"
|
2010-11-18 03:21:26 +01:00
|
|
|
#include "RenderBase.h"
|
2012-12-21 21:04:53 +01:00
|
|
|
#include "BPStructs.h"
|
2010-10-03 10:20:24 +02:00
|
|
|
|
|
|
|
#include "VertexManagerBase.h"
|
2013-02-22 08:41:52 +01:00
|
|
|
#include "MainBase.h"
|
2011-04-30 19:34:08 +02:00
|
|
|
#include "VideoConfig.h"
|
2010-10-03 10:20:24 +02:00
|
|
|
|
|
|
|
VertexManager *g_vertex_manager;
|
|
|
|
|
2013-02-21 12:36:29 +01:00
|
|
|
u8 *VertexManager::s_pCurBufferPointer;
|
2013-02-22 08:41:52 +01:00
|
|
|
u8 *VertexManager::s_pBaseBufferPointer;
|
2013-02-21 12:36:29 +01:00
|
|
|
u8 *VertexManager::s_pEndBufferPointer;
|
2010-10-03 10:20:24 +02:00
|
|
|
|
|
|
|
VertexManager::VertexManager()
|
|
|
|
{
|
2013-02-27 05:47:50 +01:00
|
|
|
LocalVBuffer.resize(MAXVBUFFERSIZE);
|
|
|
|
s_pCurBufferPointer = s_pBaseBufferPointer = &LocalVBuffer[0];
|
|
|
|
s_pEndBufferPointer = s_pBaseBufferPointer + LocalVBuffer.size();
|
2010-10-03 10:20:24 +02:00
|
|
|
|
2013-02-27 05:47:50 +01:00
|
|
|
TIBuffer.resize(MAXIBUFFERSIZE);
|
|
|
|
LIBuffer.resize(MAXIBUFFERSIZE);
|
|
|
|
PIBuffer.resize(MAXIBUFFERSIZE);
|
2010-10-03 10:20:24 +02:00
|
|
|
|
2013-02-22 08:41:52 +01:00
|
|
|
ResetBuffer();
|
2010-10-03 10:20:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
VertexManager::~VertexManager()
|
2013-04-24 15:21:54 +02:00
|
|
|
{
|
|
|
|
}
|
2010-10-03 10:20:24 +02:00
|
|
|
|
2013-02-22 08:41:52 +01:00
|
|
|
void VertexManager::ResetBuffer()
|
|
|
|
{
|
|
|
|
s_pCurBufferPointer = s_pBaseBufferPointer;
|
2013-02-27 05:47:50 +01:00
|
|
|
IndexGenerator::Start(GetTriangleIndexBuffer(), GetLineIndexBuffer(), GetPointIndexBuffer());
|
2013-02-22 08:41:52 +01:00
|
|
|
}
|
|
|
|
|
2013-02-27 05:47:50 +01:00
|
|
|
u32 VertexManager::GetRemainingSize()
|
2010-10-03 10:20:24 +02:00
|
|
|
{
|
2013-02-27 05:47:50 +01:00
|
|
|
return (u32)(s_pEndBufferPointer - s_pCurBufferPointer);
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexManager::PrepareForAdditionalData(int primitive, u32 count, u32 stride)
|
2013-10-29 06:23:17 +01:00
|
|
|
{
|
2013-02-27 05:47:50 +01:00
|
|
|
u32 const needed_vertex_bytes = count * stride;
|
2013-10-29 06:23:17 +01:00
|
|
|
|
2013-03-23 00:18:35 +01:00
|
|
|
if (count > IndexGenerator::GetRemainingIndices() || count > GetRemainingIndices(primitive) || needed_vertex_bytes > GetRemainingSize())
|
2013-02-27 05:47:50 +01:00
|
|
|
{
|
|
|
|
Flush();
|
2013-10-29 06:23:17 +01:00
|
|
|
|
2013-03-23 00:18:35 +01:00
|
|
|
if(count > IndexGenerator::GetRemainingIndices())
|
2013-04-01 01:10:21 +02:00
|
|
|
ERROR_LOG(VIDEO, "Too little remaining index values. Use 32-bit or reset them on flush.");
|
2013-03-06 12:33:02 +01:00
|
|
|
if (count > GetRemainingIndices(primitive))
|
|
|
|
ERROR_LOG(VIDEO, "VertexManager: Buffer not large enough for all indices! "
|
2013-04-01 01:10:21 +02:00
|
|
|
"Increase MAXIBUFFERSIZE or we need primitive breaking after all.");
|
2013-03-23 00:18:35 +01:00
|
|
|
if (needed_vertex_bytes > GetRemainingSize())
|
|
|
|
ERROR_LOG(VIDEO, "VertexManager: Buffer not large enough for all vertices! "
|
2013-04-01 01:10:21 +02:00
|
|
|
"Increase MAXVBUFFERSIZE or we need primitive breaking after all.");
|
2013-02-27 05:47:50 +01:00
|
|
|
}
|
2010-10-03 10:20:24 +02:00
|
|
|
}
|
|
|
|
|
2013-02-22 08:41:52 +01:00
|
|
|
bool VertexManager::IsFlushed() const
|
|
|
|
{
|
|
|
|
return s_pBaseBufferPointer == s_pCurBufferPointer;
|
|
|
|
}
|
|
|
|
|
2013-02-27 05:47:50 +01:00
|
|
|
u32 VertexManager::GetRemainingIndices(int primitive)
|
2010-10-03 10:20:24 +02:00
|
|
|
{
|
2013-10-29 06:23:17 +01:00
|
|
|
|
2013-04-24 15:21:54 +02:00
|
|
|
if(g_Config.backend_info.bSupportsPrimitiveRestart)
|
|
|
|
{
|
2013-03-29 14:27:33 +01:00
|
|
|
switch (primitive)
|
|
|
|
{
|
|
|
|
case GX_DRAW_QUADS:
|
|
|
|
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 5 * 4;
|
|
|
|
case GX_DRAW_TRIANGLES:
|
|
|
|
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 4 * 3;
|
|
|
|
case GX_DRAW_TRIANGLE_STRIP:
|
|
|
|
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 1 - 1;
|
|
|
|
case GX_DRAW_TRIANGLE_FAN:
|
2013-04-10 12:45:44 +02:00
|
|
|
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 6 * 4 + 1;
|
2013-03-29 14:27:33 +01:00
|
|
|
|
|
|
|
case GX_DRAW_LINES:
|
|
|
|
return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen());
|
|
|
|
case GX_DRAW_LINE_STRIP:
|
|
|
|
return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2 + 1;
|
|
|
|
|
|
|
|
case GX_DRAW_POINTS:
|
|
|
|
return (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen());
|
|
|
|
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
2013-04-24 15:21:54 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-03-29 14:27:33 +01:00
|
|
|
switch (primitive)
|
|
|
|
{
|
|
|
|
case GX_DRAW_QUADS:
|
|
|
|
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 6 * 4;
|
|
|
|
case GX_DRAW_TRIANGLES:
|
|
|
|
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen());
|
|
|
|
case GX_DRAW_TRIANGLE_STRIP:
|
|
|
|
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3 + 2;
|
|
|
|
case GX_DRAW_TRIANGLE_FAN:
|
|
|
|
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3 + 2;
|
|
|
|
|
|
|
|
case GX_DRAW_LINES:
|
|
|
|
return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen());
|
|
|
|
case GX_DRAW_LINE_STRIP:
|
|
|
|
return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2 + 1;
|
|
|
|
|
|
|
|
case GX_DRAW_POINTS:
|
|
|
|
return (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen());
|
|
|
|
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
2013-10-29 06:23:17 +01:00
|
|
|
}
|
2010-10-03 10:20:24 +02:00
|
|
|
}
|
|
|
|
|
2013-02-22 02:10:00 +01:00
|
|
|
void VertexManager::AddVertices(int primitive, u32 numVertices)
|
2010-10-03 10:20:24 +02:00
|
|
|
{
|
|
|
|
if (numVertices <= 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
ADDSTAT(stats.thisFrame.numPrims, numVertices);
|
|
|
|
INCSTAT(stats.thisFrame.numPrimitiveJoins);
|
2013-03-20 02:51:12 +01:00
|
|
|
|
2013-02-22 02:10:00 +01:00
|
|
|
IndexGenerator::AddIndices(primitive, numVertices);
|
2010-10-03 10:20:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void VertexManager::Flush()
|
|
|
|
{
|
2013-02-22 08:41:52 +01:00
|
|
|
if (g_vertex_manager->IsFlushed())
|
|
|
|
return;
|
2013-03-20 02:51:12 +01:00
|
|
|
|
2012-12-21 21:04:53 +01:00
|
|
|
// loading a state will invalidate BP, so check for it
|
2012-12-23 13:32:23 +01:00
|
|
|
g_video_backend->CheckInvalidState();
|
2013-03-20 02:51:12 +01:00
|
|
|
|
2013-02-22 08:41:52 +01:00
|
|
|
VideoFifo_CheckEFBAccess();
|
2013-03-20 02:51:12 +01:00
|
|
|
|
2013-12-09 23:49:09 +01:00
|
|
|
// TODO: need to merge more stuff into VideoCommon
|
2010-10-03 10:20:24 +02:00
|
|
|
g_vertex_manager->vFlush();
|
2013-03-20 02:51:12 +01:00
|
|
|
|
2013-02-22 08:41:52 +01:00
|
|
|
g_vertex_manager->ResetBuffer();
|
2010-10-03 10:20:24 +02:00
|
|
|
}
|
2010-10-20 00:24:27 +02:00
|
|
|
|
2012-01-04 09:42:22 +01:00
|
|
|
void VertexManager::DoState(PointerWrap& p)
|
|
|
|
{
|
|
|
|
g_vertex_manager->vDoState(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexManager::DoStateShared(PointerWrap& p)
|
|
|
|
{
|
2013-02-27 05:47:50 +01:00
|
|
|
// It seems we half-assume to be flushed here
|
|
|
|
// We update s_pCurBufferPointer yet don't worry about IndexGenerator's outdated pointers
|
|
|
|
// and maybe other things are overlooked
|
2013-10-29 06:23:17 +01:00
|
|
|
|
2013-02-27 05:47:50 +01:00
|
|
|
p.Do(LocalVBuffer);
|
|
|
|
p.Do(TIBuffer);
|
|
|
|
p.Do(LIBuffer);
|
|
|
|
p.Do(PIBuffer);
|
2013-10-29 06:23:17 +01:00
|
|
|
|
2013-02-27 05:47:50 +01:00
|
|
|
s_pBaseBufferPointer = &LocalVBuffer[0];
|
|
|
|
s_pEndBufferPointer = s_pBaseBufferPointer + LocalVBuffer.size();
|
|
|
|
p.DoPointer(s_pCurBufferPointer, s_pBaseBufferPointer);
|
2012-01-04 09:42:22 +01:00
|
|
|
}
|