#include "Common.h" #include "Statistics.h" #include "OpcodeDecoding.h" #include "IndexGenerator.h" #include "VertexShaderManager.h" #include "PixelShaderManager.h" #include "NativeVertexFormat.h" #include "TextureCacheBase.h" #include "RenderBase.h" #include "BPStructs.h" #include "VertexManagerBase.h" #include "MainBase.h" #include "VideoConfig.h" VertexManager *g_vertex_manager; u8 *VertexManager::s_pCurBufferPointer; u8 *VertexManager::s_pBaseBufferPointer; u8 *VertexManager::s_pEndBufferPointer; VertexManager::VertexManager() { LocalVBuffer.resize(MAXVBUFFERSIZE); s_pCurBufferPointer = s_pBaseBufferPointer = &LocalVBuffer[0]; s_pEndBufferPointer = s_pBaseBufferPointer + LocalVBuffer.size(); TIBuffer.resize(MAXIBUFFERSIZE); LIBuffer.resize(MAXIBUFFERSIZE); PIBuffer.resize(MAXIBUFFERSIZE); ResetBuffer(); } VertexManager::~VertexManager() { } void VertexManager::ResetBuffer() { s_pCurBufferPointer = s_pBaseBufferPointer; IndexGenerator::Start(GetTriangleIndexBuffer(), GetLineIndexBuffer(), GetPointIndexBuffer()); } u32 VertexManager::GetRemainingSize() { return (u32)(s_pEndBufferPointer - s_pCurBufferPointer); } void VertexManager::PrepareForAdditionalData(int primitive, u32 count, u32 stride) { u32 const needed_vertex_bytes = count * stride; if (count > IndexGenerator::GetRemainingIndices() || count > GetRemainingIndices(primitive) || needed_vertex_bytes > GetRemainingSize()) { Flush(); if(count > IndexGenerator::GetRemainingIndices()) ERROR_LOG(VIDEO, "Too little remaining index values. Use 32-bit or reset them on flush."); if (count > GetRemainingIndices(primitive)) ERROR_LOG(VIDEO, "VertexManager: Buffer not large enough for all indices! " "Increase MAXIBUFFERSIZE or we need primitive breaking after all."); if (needed_vertex_bytes > GetRemainingSize()) ERROR_LOG(VIDEO, "VertexManager: Buffer not large enough for all vertices! " "Increase MAXVBUFFERSIZE or we need primitive breaking after all."); } } bool VertexManager::IsFlushed() const { return s_pBaseBufferPointer == s_pCurBufferPointer; } u32 VertexManager::GetRemainingIndices(int primitive) { if(g_Config.backend_info.bSupportsPrimitiveRestart) { 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: return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 6 * 4 + 1; 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; } } else { 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; } } } void VertexManager::AddVertices(int primitive, u32 numVertices) { if (numVertices <= 0) return; ADDSTAT(stats.thisFrame.numPrims, numVertices); INCSTAT(stats.thisFrame.numPrimitiveJoins); IndexGenerator::AddIndices(primitive, numVertices); } void VertexManager::Flush() { if (g_vertex_manager->IsFlushed()) return; // loading a state will invalidate BP, so check for it g_video_backend->CheckInvalidState(); VideoFifo_CheckEFBAccess(); // TODO: need to merge more stuff into VideoCommon g_vertex_manager->vFlush(); g_vertex_manager->ResetBuffer(); } void VertexManager::DoState(PointerWrap& p) { g_vertex_manager->vDoState(p); } void VertexManager::DoStateShared(PointerWrap& p) { // 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 p.Do(LocalVBuffer); p.Do(TIBuffer); p.Do(LIBuffer); p.Do(PIBuffer); s_pBaseBufferPointer = &LocalVBuffer[0]; s_pEndBufferPointer = s_pBaseBufferPointer + LocalVBuffer.size(); p.DoPointer(s_pCurBufferPointer, s_pBaseBufferPointer); }