From 20369743a433f6fb3c7286201e2e029065c78806 Mon Sep 17 00:00:00 2001
From: Pierre Bourdon <delroth@gmail.com>
Date: Thu, 24 Jul 2014 01:12:12 +0200
Subject: [PATCH 1/4] VertexLoaderUID: remove global state dependency

---
 Source/Core/VideoCommon/VertexLoader.h          | 12 ++++++------
 Source/Core/VideoCommon/VertexLoaderManager.cpp |  3 +--
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/Source/Core/VideoCommon/VertexLoader.h b/Source/Core/VideoCommon/VertexLoader.h
index 7e40bc8003..080a5d48a8 100644
--- a/Source/Core/VideoCommon/VertexLoader.h
+++ b/Source/Core/VideoCommon/VertexLoader.h
@@ -40,13 +40,13 @@ public:
 	{
 	}
 
-	void InitFromCurrentState(int vtx_attr_group)
+	VertexLoaderUID(const TVtxDesc& vtx_desc, const VAT& vat)
 	{
-		vid[0] = g_VtxDesc.Hex & 0xFFFFFFFF;
-		vid[1] = g_VtxDesc.Hex >> 32;
-		vid[2] = g_VtxAttr[vtx_attr_group].g0.Hex & ~VAT_0_FRACBITS;
-		vid[3] = g_VtxAttr[vtx_attr_group].g1.Hex & ~VAT_1_FRACBITS;
-		vid[4] = g_VtxAttr[vtx_attr_group].g2.Hex & ~VAT_2_FRACBITS;
+		vid[0] = vtx_desc.Hex & 0xFFFFFFFF;
+		vid[1] = vtx_desc.Hex >> 32;
+		vid[2] = vat.g0.Hex & ~VAT_0_FRACBITS;
+		vid[3] = vat.g1.Hex & ~VAT_1_FRACBITS;
+		vid[4] = vat.g2.Hex & ~VAT_2_FRACBITS;
 		hash = CalculateHash();
 	}
 
diff --git a/Source/Core/VideoCommon/VertexLoaderManager.cpp b/Source/Core/VideoCommon/VertexLoaderManager.cpp
index dd1196a48e..d8417042b7 100644
--- a/Source/Core/VideoCommon/VertexLoaderManager.cpp
+++ b/Source/Core/VideoCommon/VertexLoaderManager.cpp
@@ -104,8 +104,7 @@ static VertexLoader* RefreshLoader(int vtx_attr_group)
 {
 	if ((s_attr_dirty >> vtx_attr_group) & 1)
 	{
-		VertexLoaderUID uid;
-		uid.InitFromCurrentState(vtx_attr_group);
+		VertexLoaderUID uid(g_VtxDesc, g_VtxAttr[vtx_attr_group]);
 		VertexLoaderMap::iterator iter = g_VertexLoaderMap.find(uid);
 		if (iter != g_VertexLoaderMap.end())
 		{

From 069801a7d16653ec6c8b95b59e84b37d93a0d349 Mon Sep 17 00:00:00 2001
From: Pierre Bourdon <delroth@gmail.com>
Date: Thu, 24 Jul 2014 01:25:23 +0200
Subject: [PATCH 2/4] VertexLoader: Simplify SetVAT

---
 Source/Core/VideoCommon/VertexLoader.cpp | 9 ++-------
 Source/Core/VideoCommon/VertexLoader.h   | 2 +-
 2 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/Source/Core/VideoCommon/VertexLoader.cpp b/Source/Core/VideoCommon/VertexLoader.cpp
index 4087554716..f83565ae26 100644
--- a/Source/Core/VideoCommon/VertexLoader.cpp
+++ b/Source/Core/VideoCommon/VertexLoader.cpp
@@ -468,7 +468,7 @@ VertexLoader::VertexLoader(const TVtxDesc &vtx_desc, const VAT &vtx_attr)
 	VertexLoader_TextCoord::Init();
 
 	m_VtxDesc = vtx_desc;
-	SetVAT(vtx_attr.g0.Hex, vtx_attr.g1.Hex, vtx_attr.g2.Hex);
+	SetVAT(vtx_attr);
 
 	#ifdef USE_VERTEX_LOADER_JIT
 	AllocCodeSpace(COMPILED_CODE_SIZE);
@@ -887,13 +887,8 @@ void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int const coun
 	INCSTAT(stats.thisFrame.numPrimitiveJoins);
 }
 
-void VertexLoader::SetVAT(u32 _group0, u32 _group1, u32 _group2)
+void VertexLoader::SetVAT(const VAT& vat)
 {
-	VAT vat;
-	vat.g0.Hex = _group0;
-	vat.g1.Hex = _group1;
-	vat.g2.Hex = _group2;
-
 	m_VtxAttr.PosElements          = vat.g0.PosElements;
 	m_VtxAttr.PosFormat            = vat.g0.PosFormat;
 	m_VtxAttr.PosFrac              = vat.g0.PosFrac;
diff --git a/Source/Core/VideoCommon/VertexLoader.h b/Source/Core/VideoCommon/VertexLoader.h
index 080a5d48a8..d912159e7d 100644
--- a/Source/Core/VideoCommon/VertexLoader.h
+++ b/Source/Core/VideoCommon/VertexLoader.h
@@ -135,7 +135,7 @@ private:
 
 	int m_numLoadedVertices;
 
-	void SetVAT(u32 _group0, u32 _group1, u32 _group2);
+	void SetVAT(const VAT& vat);
 
 	void CompileVertexTranslator();
 	void ConvertVertices(int count);

From 78c3a220600b6cbbd063693d89d423a985125408 Mon Sep 17 00:00:00 2001
From: Pierre Bourdon <delroth@gmail.com>
Date: Thu, 24 Jul 2014 01:51:37 +0200
Subject: [PATCH 3/4] VertexLoader: take the VAT object directly for
 RunVertices

---
 Source/Core/VideoCommon/VertexLoader.cpp      | 24 +++++++++----------
 Source/Core/VideoCommon/VertexLoader.h        |  4 ++--
 .../Core/VideoCommon/VertexLoaderManager.cpp  |  2 +-
 3 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/Source/Core/VideoCommon/VertexLoader.cpp b/Source/Core/VideoCommon/VertexLoader.cpp
index f83565ae26..bb73193c04 100644
--- a/Source/Core/VideoCommon/VertexLoader.cpp
+++ b/Source/Core/VideoCommon/VertexLoader.cpp
@@ -813,7 +813,7 @@ void VertexLoader::WriteSetVariable(int bits, void *address, OpArg value)
 }
 #endif
 
-void VertexLoader::SetupRunVertices(int vtx_attr_group, int primitive, int const count)
+void VertexLoader::SetupRunVertices(const VAT& vat, int primitive, int const count)
 {
 	m_numLoadedVertices += count;
 
@@ -826,15 +826,15 @@ void VertexLoader::SetupRunVertices(int vtx_attr_group, int primitive, int const
 	g_nativeVertexFmt = m_NativeFmt;
 
 	// Load position and texcoord scale factors.
-	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;
+	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;
 
 	posScale = fractionTable[m_VtxAttr.PosFrac];
 	if (m_NativeFmt->m_components & VB_HAS_UVALL)
@@ -870,7 +870,7 @@ void VertexLoader::ConvertVertices ( int count )
 #endif
 }
 
-void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int const count)
+void VertexLoader::RunVertices(const VAT& vat, int primitive, int const count)
 {
 	if (bpmem.genMode.cullmode == 3 && primitive < 5)
 	{
@@ -878,7 +878,7 @@ void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int const coun
 		DataSkip(count * m_VertexSize);
 		return;
 	}
-	SetupRunVertices(vtx_attr_group, primitive, count);
+	SetupRunVertices(vat, primitive, count);
 	VertexManager::PrepareForAdditionalData(primitive, count, native_stride);
 	ConvertVertices(count);
 	IndexGenerator::AddIndices(primitive, count);
diff --git a/Source/Core/VideoCommon/VertexLoader.h b/Source/Core/VideoCommon/VertexLoader.h
index d912159e7d..a438ba8933 100644
--- a/Source/Core/VideoCommon/VertexLoader.h
+++ b/Source/Core/VideoCommon/VertexLoader.h
@@ -107,8 +107,8 @@ public:
 
 	int GetVertexSize() const {return m_VertexSize;}
 
-	void SetupRunVertices(int vtx_attr_group, int primitive, int const count);
-	void RunVertices(int vtx_attr_group, int primitive, int count);
+	void SetupRunVertices(const VAT& vat, int primitive, int const count);
+	void RunVertices(const VAT& vat, int primitive, int count);
 
 	// For debugging / profiling
 	void AppendToString(std::string *dest) const;
diff --git a/Source/Core/VideoCommon/VertexLoaderManager.cpp b/Source/Core/VideoCommon/VertexLoaderManager.cpp
index d8417042b7..16bb4689ac 100644
--- a/Source/Core/VideoCommon/VertexLoaderManager.cpp
+++ b/Source/Core/VideoCommon/VertexLoaderManager.cpp
@@ -126,7 +126,7 @@ void RunVertices(int vtx_attr_group, int primitive, int count)
 {
 	if (!count)
 		return;
-	RefreshLoader(vtx_attr_group)->RunVertices(vtx_attr_group, primitive, count);
+	RefreshLoader(vtx_attr_group)->RunVertices(g_VtxAttr[vtx_attr_group], primitive, count);
 }
 
 int GetVertexSize(int vtx_attr_group)

From 73f9a22e2ef8af906a116ad67f1054cc964ae3f0 Mon Sep 17 00:00:00 2001
From: Pierre Bourdon <delroth@gmail.com>
Date: Sat, 26 Jul 2014 01:10:44 +0200
Subject: [PATCH 4/4] VertexLoader: Remove global state dependency on
 g_nativeVertexFmt

---
 .../Core/VideoBackends/D3D/VertexManager.cpp  | 17 ++--
 .../Core/VideoBackends/OGL/VertexManager.cpp  | 12 +--
 Source/Core/VideoCommon/VertexLoader.cpp      | 80 ++++++++-----------
 Source/Core/VideoCommon/VertexLoader.h        |  8 +-
 .../Core/VideoCommon/VertexLoaderManager.cpp  | 38 ++++++---
 Source/Core/VideoCommon/VertexLoaderManager.h |  2 +-
 6 files changed, 83 insertions(+), 74 deletions(-)

diff --git a/Source/Core/VideoBackends/D3D/VertexManager.cpp b/Source/Core/VideoBackends/D3D/VertexManager.cpp
index 6ae5f17a3f..f6d7685a52 100644
--- a/Source/Core/VideoBackends/D3D/VertexManager.cpp
+++ b/Source/Core/VideoBackends/D3D/VertexManager.cpp
@@ -16,7 +16,7 @@
 #include "VideoCommon/RenderBase.h"
 #include "VideoCommon/Statistics.h"
 #include "VideoCommon/TextureCacheBase.h"
-#include "VideoCommon/VertexLoader.h"
+#include "VideoCommon/VertexLoaderManager.h"
 #include "VideoCommon/VertexShaderManager.h"
 #include "VideoCommon/VideoConfig.h"
 
@@ -136,6 +136,7 @@ static const float LINE_PT_TEX_OFFSETS[8] = {
 
 void VertexManager::Draw(UINT stride)
 {
+	u32 components = VertexLoaderManager::GetCurrentVertexFormat()->m_components;
 	D3D::context->IASetVertexBuffers(0, 1, &m_vertex_buffers[m_current_vertex_buffer], &stride, &m_vertex_draw_offset);
 	D3D::context->IASetIndexBuffer(m_index_buffers[m_current_index_buffer], DXGI_FORMAT_R16_UINT, 0);
 
@@ -157,7 +158,7 @@ void VertexManager::Draw(UINT stride)
 		for (int i = 0; i < 8; ++i)
 			texOffsetEnable[i] = bpmem.texcoords[i].s.line_offset;
 
-		if (m_lineShader.SetShader(g_nativeVertexFmt->m_components, lineWidth,
+		if (m_lineShader.SetShader(components, lineWidth,
 			texOffset, vpWidth, vpHeight, texOffsetEnable))
 		{
 			((DX11::Renderer*)g_renderer)->ApplyCullDisable(); // Disable culling for lines and points
@@ -181,7 +182,7 @@ void VertexManager::Draw(UINT stride)
 		for (int i = 0; i < 8; ++i)
 			texOffsetEnable[i] = bpmem.texcoords[i].s.point_offset;
 
-		if (m_pointShader.SetShader(g_nativeVertexFmt->m_components, pointSize,
+		if (m_pointShader.SetShader(components, pointSize,
 			texOffset, vpWidth, vpHeight, texOffsetEnable))
 		{
 			((DX11::Renderer*)g_renderer)->ApplyCullDisable(); // Disable culling for lines and points
@@ -197,21 +198,21 @@ void VertexManager::Draw(UINT stride)
 
 void VertexManager::vFlush(bool useDstAlpha)
 {
+	u32 components = VertexLoaderManager::GetCurrentVertexFormat()->m_components;
 	if (!PixelShaderCache::SetShader(
-		useDstAlpha ? DSTALPHA_DUAL_SOURCE_BLEND : DSTALPHA_NONE,
-		g_nativeVertexFmt->m_components))
+		useDstAlpha ? DSTALPHA_DUAL_SOURCE_BLEND : DSTALPHA_NONE, components))
 	{
 		GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
 		return;
 	}
-	if (!VertexShaderCache::SetShader(g_nativeVertexFmt->m_components))
+	if (!VertexShaderCache::SetShader(components))
 	{
 		GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
 		return;
 	}
 	PrepareDrawBuffers();
-	unsigned int stride = g_nativeVertexFmt->GetVertexStride();
-	g_nativeVertexFmt->SetupVertexPointers();
+	unsigned int stride = VertexLoaderManager::GetCurrentVertexFormat()->GetVertexStride();
+	VertexLoaderManager::GetCurrentVertexFormat()->SetupVertexPointers();
 	g_renderer->ApplyState(useDstAlpha);
 
 	Draw(stride);
diff --git a/Source/Core/VideoBackends/OGL/VertexManager.cpp b/Source/Core/VideoBackends/OGL/VertexManager.cpp
index 0ac59041b7..6dce46c239 100644
--- a/Source/Core/VideoBackends/OGL/VertexManager.cpp
+++ b/Source/Core/VideoBackends/OGL/VertexManager.cpp
@@ -24,7 +24,7 @@
 #include "VideoCommon/IndexGenerator.h"
 #include "VideoCommon/PixelShaderManager.h"
 #include "VideoCommon/Statistics.h"
-#include "VideoCommon/VertexLoader.h"
+#include "VideoCommon/VertexLoaderManager.h"
 #include "VideoCommon/VertexShaderGen.h"
 #include "VideoCommon/VertexShaderManager.h"
 #include "VideoCommon/VideoConfig.h"
@@ -126,7 +126,7 @@ void VertexManager::Draw(u32 stride)
 
 void VertexManager::vFlush(bool useDstAlpha)
 {
-	GLVertexFormat *nativeVertexFmt = (GLVertexFormat*)g_nativeVertexFmt;
+	GLVertexFormat *nativeVertexFmt = (GLVertexFormat*)VertexLoaderManager::GetCurrentVertexFormat();
 	u32 stride  = nativeVertexFmt->GetVertexStride();
 
 	if (m_last_vao != nativeVertexFmt->VAO) {
@@ -144,18 +144,18 @@ void VertexManager::vFlush(bool useDstAlpha)
 	// the same pass as regular rendering.
 	if (useDstAlpha && dualSourcePossible)
 	{
-		ProgramShaderCache::SetShader(DSTALPHA_DUAL_SOURCE_BLEND, g_nativeVertexFmt->m_components);
+		ProgramShaderCache::SetShader(DSTALPHA_DUAL_SOURCE_BLEND, nativeVertexFmt->m_components);
 	}
 	else
 	{
-		ProgramShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components);
+		ProgramShaderCache::SetShader(DSTALPHA_NONE, nativeVertexFmt->m_components);
 	}
 
 	// upload global constants
 	ProgramShaderCache::UploadConstants();
 
 	// setup the pointers
-	g_nativeVertexFmt->SetupVertexPointers();
+	nativeVertexFmt->SetupVertexPointers();
 	GL_REPORT_ERRORD();
 
 	Draw(stride);
@@ -163,7 +163,7 @@ void VertexManager::vFlush(bool useDstAlpha)
 	// run through vertex groups again to set alpha
 	if (useDstAlpha && !dualSourcePossible)
 	{
-		ProgramShaderCache::SetShader(DSTALPHA_ALPHA_PASS,g_nativeVertexFmt->m_components);
+		ProgramShaderCache::SetShader(DSTALPHA_ALPHA_PASS, nativeVertexFmt->m_components);
 
 		// only update alpha
 		glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
diff --git a/Source/Core/VideoCommon/VertexLoader.cpp b/Source/Core/VideoCommon/VertexLoader.cpp
index bb73193c04..9417b7e78f 100644
--- a/Source/Core/VideoCommon/VertexLoader.cpp
+++ b/Source/Core/VideoCommon/VertexLoader.cpp
@@ -22,7 +22,6 @@
 #include "VideoCommon/VertexLoader_Position.h"
 #include "VideoCommon/VertexLoader_TextCoord.h"
 #include "VideoCommon/VertexLoaderManager.h"
-#include "VideoCommon/VertexManagerBase.h"
 #include "VideoCommon/VideoCommon.h"
 #include "VideoCommon/VideoConfig.h"
 
@@ -31,8 +30,6 @@
 
 #define COMPILED_CODE_SIZE 4096
 
-NativeVertexFormat *g_nativeVertexFmt;
-
 #ifndef _WIN32
 	#undef inline
 	#define inline
@@ -539,8 +536,7 @@ void VertexLoader::CompileVertexTranslator()
 
 	// Position in pc vertex format.
 	int nat_offset = 0;
-	PortableVertexDeclaration vtx_decl;
-	memset(&vtx_decl, 0, sizeof(vtx_decl));
+	memset(&m_native_vtx_decl, 0, sizeof(m_native_vtx_decl));
 
 	// Position Matrix Index
 	if (m_VtxDesc.PosMatIdx)
@@ -572,11 +568,11 @@ void VertexLoader::CompileVertexTranslator()
 	}
 	m_VertexSize += VertexLoader_Position::GetSize(m_VtxDesc.Position, m_VtxAttr.PosFormat, m_VtxAttr.PosElements);
 	nat_offset += 12;
-	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;
+	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;
 
 	// Normals
 	if (m_VtxDesc.Normal != NOT_PRESENT)
@@ -598,11 +594,11 @@ void VertexLoader::CompileVertexTranslator()
 
 		for (int i = 0; i < (vtx_attr.NormalElements ? 3 : 1); i++)
 		{
-			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;
+			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;
 			nat_offset += 12;
 		}
 
@@ -613,9 +609,9 @@ void VertexLoader::CompileVertexTranslator()
 
 	for (int i = 0; i < 2; i++)
 	{
-		vtx_decl.colors[i].components = 4;
-		vtx_decl.colors[i].type = VAR_UNSIGNED_BYTE;
-		vtx_decl.colors[i].integer = false;
+		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;
 		switch (col[i])
 		{
 		case NOT_PRESENT:
@@ -663,8 +659,8 @@ void VertexLoader::CompileVertexTranslator()
 		if (col[i] != NOT_PRESENT)
 		{
 			components |= VB_HAS_COL0 << i;
-			vtx_decl.colors[i].offset = nat_offset;
-			vtx_decl.colors[i].enable = true;
+			m_native_vtx_decl.colors[i].offset = nat_offset;
+			m_native_vtx_decl.colors[i].enable = true;
 			nat_offset += 4;
 		}
 	}
@@ -672,9 +668,9 @@ void VertexLoader::CompileVertexTranslator()
 	// Texture matrix indices (remove if corresponding texture coordinate isn't enabled)
 	for (int i = 0; i < 8; i++)
 	{
-		vtx_decl.texcoords[i].offset = nat_offset;
-		vtx_decl.texcoords[i].type = VAR_FLOAT;
-		vtx_decl.texcoords[i].integer = false;
+		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;
 
 		const int format = m_VtxAttr.texCoord[i].Format;
 		const int elements = m_VtxAttr.texCoord[i].Elements;
@@ -696,18 +692,18 @@ void VertexLoader::CompileVertexTranslator()
 
 		if (components & (VB_HAS_TEXMTXIDX0 << i))
 		{
-			vtx_decl.texcoords[i].enable = true;
+			m_native_vtx_decl.texcoords[i].enable = true;
 			if (tc[i] != NOT_PRESENT)
 			{
 				// if texmtx is included, texcoord will always be 3 floats, z will be the texmtx index
-				vtx_decl.texcoords[i].components = 3;
+				m_native_vtx_decl.texcoords[i].components = 3;
 				nat_offset += 12;
 				WriteCall(m_VtxAttr.texCoord[i].Elements ? TexMtx_Write_Float : TexMtx_Write_Float2);
 			}
 			else
 			{
 				components |= VB_HAS_UV0 << i; // have to include since using now
-				vtx_decl.texcoords[i].components = 4;
+				m_native_vtx_decl.texcoords[i].components = 4;
 				nat_offset += 16; // still include the texture coordinate, but this time as 6 + 2 bytes
 				WriteCall(TexMtx_Write_Float4);
 			}
@@ -716,8 +712,8 @@ void VertexLoader::CompileVertexTranslator()
 		{
 			if (tc[i] != NOT_PRESENT)
 			{
-				vtx_decl.texcoords[i].enable = true;
-				vtx_decl.texcoords[i].components = vtx_attr.texCoord[i].Elements ? 2 : 1;
+				m_native_vtx_decl.texcoords[i].enable = true;
+				m_native_vtx_decl.texcoords[i].components = vtx_attr.texCoord[i].Elements ? 2 : 1;
 				nat_offset += 4 * (vtx_attr.texCoord[i].Elements ? 2 : 1);
 			}
 		}
@@ -746,16 +742,16 @@ void VertexLoader::CompileVertexTranslator()
 	if (m_VtxDesc.PosMatIdx)
 	{
 		WriteCall(PosMtx_Write);
-		vtx_decl.posmtx.components = 4;
-		vtx_decl.posmtx.enable = true;
-		vtx_decl.posmtx.offset = nat_offset;
-		vtx_decl.posmtx.type = VAR_UNSIGNED_BYTE;
-		vtx_decl.posmtx.integer = true;
+		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;
 		nat_offset += 4;
 	}
 
-	native_stride = nat_offset;
-	vtx_decl.stride = native_stride;
+	m_native_components = components;
+	m_native_vtx_decl.stride = nat_offset;
 
 #ifdef USE_VERTEX_LOADER_JIT
 	// End loop here
@@ -770,7 +766,6 @@ void VertexLoader::CompileVertexTranslator()
 	ABI_PopAllCalleeSavedRegsAndAdjustStack();
 	RET();
 #endif
-	m_NativeFmt = VertexLoaderManager::GetNativeVertexFormat(vtx_decl, components);
 }
 
 void VertexLoader::WriteCall(TPipelineFunction func)
@@ -817,14 +812,6 @@ void VertexLoader::SetupRunVertices(const VAT& vat, int primitive, int const cou
 {
 	m_numLoadedVertices += count;
 
-	// Flush if our vertex format is different from the currently set.
-	if (g_nativeVertexFmt != nullptr && g_nativeVertexFmt != m_NativeFmt)
-	{
-		VertexManager::Flush();
-		// Also move the Set() here?
-	}
-	g_nativeVertexFmt = m_NativeFmt;
-
 	// Load position and texcoord scale factors.
 	m_VtxAttr.PosFrac          = vat.g0.PosFrac;
 	m_VtxAttr.texCoord[0].Frac = vat.g0.Tex0Frac;
@@ -837,7 +824,7 @@ void VertexLoader::SetupRunVertices(const VAT& vat, int primitive, int const cou
 	m_VtxAttr.texCoord[7].Frac = vat.g2.Tex7Frac;
 
 	posScale = fractionTable[m_VtxAttr.PosFrac];
-	if (m_NativeFmt->m_components & VB_HAS_UVALL)
+	if (m_native_components & VB_HAS_UVALL)
 		for (int i = 0; i < 8; i++)
 			tcScale[i] = fractionTable[m_VtxAttr.texCoord[i].Frac];
 	for (int i = 0; i < 2; i++)
@@ -879,7 +866,8 @@ void VertexLoader::RunVertices(const VAT& vat, int primitive, int const count)
 		return;
 	}
 	SetupRunVertices(vat, primitive, count);
-	VertexManager::PrepareForAdditionalData(primitive, count, native_stride);
+	VertexManager::PrepareForAdditionalData(primitive, count,
+			m_native_vtx_decl.stride);
 	ConvertVertices(count);
 	IndexGenerator::AddIndices(primitive, count);
 
diff --git a/Source/Core/VideoCommon/VertexLoader.h b/Source/Core/VideoCommon/VertexLoader.h
index a438ba8933..8738b99963 100644
--- a/Source/Core/VideoCommon/VertexLoader.h
+++ b/Source/Core/VideoCommon/VertexLoader.h
@@ -24,7 +24,6 @@
 #endif
 
 // They are used for the communication with the loader functions
-extern NativeVertexFormat *g_nativeVertexFmt;
 extern int tcIndex;
 extern int colIndex;
 extern int colElements[2];
@@ -106,6 +105,9 @@ public:
 	~VertexLoader();
 
 	int GetVertexSize() const {return m_VertexSize;}
+	u32 GetNativeComponents() const { return m_native_components; }
+	const PortableVertexDeclaration& GetNativeVertexDeclaration() const
+		{ return m_native_vtx_decl; }
 
 	void SetupRunVertices(const VAT& vat, int primitive, int const count);
 	void RunVertices(const VAT& vat, int primitive, int count);
@@ -122,8 +124,8 @@ private:
 	TVtxDesc m_VtxDesc;  // Not really used currently - or well it is, but could be easily avoided.
 
 	// PC vertex format
-	NativeVertexFormat *m_NativeFmt;
-	int native_stride;
+	u32 m_native_components;
+	PortableVertexDeclaration m_native_vtx_decl;
 
 #ifndef USE_VERTEX_LOADER_JIT
 	// Pipeline.
diff --git a/Source/Core/VideoCommon/VertexLoaderManager.cpp b/Source/Core/VideoCommon/VertexLoaderManager.cpp
index 16bb4689ac..d5e74a0e11 100644
--- a/Source/Core/VideoCommon/VertexLoaderManager.cpp
+++ b/Source/Core/VideoCommon/VertexLoaderManager.cpp
@@ -12,11 +12,13 @@
 #include "VideoCommon/Statistics.h"
 #include "VideoCommon/VertexLoader.h"
 #include "VideoCommon/VertexLoaderManager.h"
+#include "VideoCommon/VertexManagerBase.h"
 #include "VideoCommon/VertexShaderManager.h"
 #include "VideoCommon/VideoCommon.h"
 
 static int s_attr_dirty;  // bitfield
 
+static NativeVertexFormat* s_current_vtx_fmt;
 static VertexLoader *g_VertexLoaders[8];
 
 namespace std
@@ -122,10 +124,34 @@ static VertexLoader* RefreshLoader(int vtx_attr_group)
 	return g_VertexLoaders[vtx_attr_group];
 }
 
+static NativeVertexFormat* GetNativeVertexFormat(const PortableVertexDeclaration& format,
+                                                 u32 components)
+{
+	auto& native = s_native_vertex_map[format];
+	if (!native)
+	{
+		auto raw_pointer = g_vertex_manager->CreateNativeVertexFormat();
+		native = std::unique_ptr<NativeVertexFormat>(raw_pointer);
+		native->Initialize(format);
+		native->m_components = components;
+	}
+	return native.get();
+}
+
 void RunVertices(int vtx_attr_group, int primitive, int count)
 {
 	if (!count)
 		return;
+	VertexLoader* loader = RefreshLoader(vtx_attr_group);
+
+	// If the native vertex format changed, force a flush.
+	NativeVertexFormat* required_vtx_fmt = GetNativeVertexFormat(
+			loader->GetNativeVertexDeclaration(),
+			loader->GetNativeComponents());
+	if (required_vtx_fmt != s_current_vtx_fmt)
+		VertexManager::Flush();
+	s_current_vtx_fmt = required_vtx_fmt;
+
 	RefreshLoader(vtx_attr_group)->RunVertices(g_VtxAttr[vtx_attr_group], primitive, count);
 }
 
@@ -134,17 +160,9 @@ int GetVertexSize(int vtx_attr_group)
 	return RefreshLoader(vtx_attr_group)->GetVertexSize();
 }
 
-NativeVertexFormat* GetNativeVertexFormat(const PortableVertexDeclaration& format, u32 components)
+NativeVertexFormat* GetCurrentVertexFormat()
 {
-	auto& native = s_native_vertex_map[format];
-	if (!native)
-	{
-		auto raw_pointer = g_vertex_manager->CreateNativeVertexFormat();
-		native = std::unique_ptr<NativeVertexFormat>(raw_pointer);
-		native->m_components = components;
-		native->Initialize(format);
-	}
-	return native.get();
+	return s_current_vtx_fmt;
 }
 
 }  // namespace
diff --git a/Source/Core/VideoCommon/VertexLoaderManager.h b/Source/Core/VideoCommon/VertexLoaderManager.h
index 909701bf6d..17bf13c3ba 100644
--- a/Source/Core/VideoCommon/VertexLoaderManager.h
+++ b/Source/Core/VideoCommon/VertexLoaderManager.h
@@ -22,7 +22,7 @@ namespace VertexLoaderManager
 	// For debugging
 	void AppendListToString(std::string *dest);
 
-	NativeVertexFormat* GetNativeVertexFormat(const PortableVertexDeclaration& format, u32 components);
+	NativeVertexFormat* GetCurrentVertexFormat();
 };
 
 void RecomputeCachedArraybases();