summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/Src/VertexLoader.cpp
diff options
context:
space:
mode:
authorskidau <skidau@gmail.com>2013-03-27 13:19:23 +1100
committerskidau <skidau@gmail.com>2013-03-27 13:19:23 +1100
commit7784fa4c67cc8d2545f45694d83805e7e89cd583 (patch)
tree7724133aabe971ec417d1dea0977a525bb8debfb /Source/Core/VideoCommon/Src/VertexLoader.cpp
parentd33c19b0cd2bae982c8d35e86a9d3551f9e5c72f (diff)
parent5cea0d9defeaa23e7af94adf7615a44fb2c9c173 (diff)
Merge branch 'master' into wii-network
# By Ryan Houdek (185) and others # Via degasus (12) and others * master: (625 commits) Revert "Don't open/close file for every file operation." as it was crashing PokePark in Windows builds. Array overrun fixed in VertexShaderCache for the DX11 plugin. Fixed DSPTool build. Windows build fix Go back to assuming every HID device is a wiimote on Windows. Fixed issue 6117. Unfixed issue 6031. VideoSoftware: Improve fog range adjustment by using less magic and more comments. revert RasterFont for VideoSoftware ogl: fix virtual xfb Windows build fix from web interface... Adjusted the audio loop criteria, using >= on the Wii and == on GC. This fixes the audio static that occurred in Wii games after hours of play. Forced the exception check only for ARAM DMA transfers. Removed the Eternal Darkness boot hack and replaced it with an exception check. VideoSoftware: Implement fog range adjustment, fixing issue 6147. implement 4xSSAA for OGL move ogl-only settings into backend Fix description of disable fog, and move it to enhancements tab. Reverted rd76ca5783743 as it was made obsolete by r1d550f4496e4. Removed the tracking of the FIFO Writes as it was made obsolete by r1d550f4496e4. Forced the external exception check to occur sooner by changing the downcount. Mark the Direct3D9 backend deprecated. Prefer D3D11 and OpenGL over D3D9 by default. ... Conflicts: CMakeLists.txt Source/Core/Common/Common.vcxproj.filters Source/Core/Common/Src/CommonPaths.h Source/Core/Core/Core.vcxproj.filters Source/Core/Core/Src/Core.cpp Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp Source/VSProps/Dolphin.Win32.props Source/VSProps/Dolphin.x64.props
Diffstat (limited to 'Source/Core/VideoCommon/Src/VertexLoader.cpp')
-rw-r--r--Source/Core/VideoCommon/Src/VertexLoader.cpp267
1 files changed, 94 insertions, 173 deletions
diff --git a/Source/Core/VideoCommon/Src/VertexLoader.cpp b/Source/Core/VideoCommon/Src/VertexLoader.cpp
index 5bffab8ee7..5df495a44c 100644
--- a/Source/Core/VideoCommon/Src/VertexLoader.cpp
+++ b/Source/Core/VideoCommon/Src/VertexLoader.cpp
@@ -23,7 +23,7 @@
#include "MemoryUtil.h"
#include "StringUtil.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "PixelEngine.h"
#include "Host.h"
@@ -43,8 +43,11 @@
//BBox
#include "XFMemory.h"
extern float GC_ALIGNED16(g_fProjectionMatrix[16]);
-
+#ifndef _M_GENERIC
+#ifndef __APPLE__
#define USE_JIT
+#endif
+#endif
#define COMPILED_CODE_SIZE 4096
@@ -72,6 +75,10 @@ int colElements[2];
float posScale;
float tcScale[8];
+// bbox must read vertex position, so convert it to this buffer
+static float s_bbox_vertex_buffer[3];
+static u8 *s_bbox_pCurBufferPointer_orig;
+
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),
@@ -93,10 +100,21 @@ void LOADERDECL PosMtx_ReadDirect_UByte()
void LOADERDECL PosMtx_Write()
{
- *VertexManager::s_pCurBufferPointer++ = s_curposmtx;
- *VertexManager::s_pCurBufferPointer++ = 0;
- *VertexManager::s_pCurBufferPointer++ = 0;
- *VertexManager::s_pCurBufferPointer++ = 0;
+ DataWrite<u8>(s_curposmtx);
+ DataWrite<u8>(0);
+ DataWrite<u8>(0);
+ DataWrite<u8>(0);
+}
+
+void LOADERDECL UpdateBoundingBoxPrepare()
+{
+ if (!PixelEngine::bbox_active)
+ return;
+
+ // 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;
}
void LOADERDECL UpdateBoundingBox()
@@ -104,12 +122,16 @@ void LOADERDECL UpdateBoundingBox()
if (!PixelEngine::bbox_active)
return;
- // Truly evil hack, reading backwards from the write pointer. If we were writing to write-only
- // memory like we might have been with a D3D vertex buffer, this would have been a bad idea.
- float *data = (float *)(VertexManager::s_pCurBufferPointer - 12);
+ // reset videodata pointer
+ VertexManager::s_pCurBufferPointer = s_bbox_pCurBufferPointer_orig;
+
+ // copy vertex pointers
+ memcpy(VertexManager::s_pCurBufferPointer, s_bbox_vertex_buffer, 12);
+ VertexManager::s_pCurBufferPointer += 12;
+
// We must transform the just loaded point by the current world and projection matrix - in software.
// Then convert to screen space and update the bounding box.
- float p[3] = {data[0], data[1], data[2]};
+ float p[3] = {s_bbox_vertex_buffer[0], s_bbox_vertex_buffer[1], s_bbox_vertex_buffer[2]};
const float *world_matrix = (float*)xfmem + MatrixIndexA.PosNormalMtxIdx * 4;
const float *proj_matrix = &g_fProjectionMatrix[0];
@@ -147,24 +169,22 @@ void LOADERDECL TexMtx_ReadDirect_UByte()
void LOADERDECL TexMtx_Write_Float()
{
- *(float*)VertexManager::s_pCurBufferPointer = (float)s_curtexmtx[s_texmtxwrite++];
- VertexManager::s_pCurBufferPointer += 4;
+ DataWrite(float(s_curtexmtx[s_texmtxwrite++]));
}
void LOADERDECL TexMtx_Write_Float2()
{
- ((float*)VertexManager::s_pCurBufferPointer)[0] = 0;
- ((float*)VertexManager::s_pCurBufferPointer)[1] = (float)s_curtexmtx[s_texmtxwrite++];
- VertexManager::s_pCurBufferPointer += 8;
+ DataWrite(0.f);
+ DataWrite(float(s_curtexmtx[s_texmtxwrite++]));
}
void LOADERDECL TexMtx_Write_Float4()
{
- ((float*)VertexManager::s_pCurBufferPointer)[0] = 0;
- ((float*)VertexManager::s_pCurBufferPointer)[1] = 0;
- ((float*)VertexManager::s_pCurBufferPointer)[2] = s_curtexmtx[s_texmtxwrite++];
- ((float*)VertexManager::s_pCurBufferPointer)[3] = 0; // Just to fill out with 0.
- VertexManager::s_pCurBufferPointer += 16;
+ DataWrite(0.f);
+ DataWrite(0.f);
+ DataWrite(float(s_curtexmtx[s_texmtxwrite++]));
+ // Just to fill out with 0.
+ DataWrite(0.f);
}
VertexLoader::VertexLoader(const TVtxDesc &vtx_desc, const VAT &vtx_attr)
@@ -182,14 +202,21 @@ VertexLoader::VertexLoader(const TVtxDesc &vtx_desc, const VAT &vtx_attr)
m_VtxDesc = vtx_desc;
SetVAT(vtx_attr.g0.Hex, vtx_attr.g1.Hex, vtx_attr.g2.Hex);
+ #ifdef USE_JIT
AllocCodeSpace(COMPILED_CODE_SIZE);
CompileVertexTranslator();
WriteProtect();
+ #else
+ CompileVertexTranslator();
+ #endif
+
}
VertexLoader::~VertexLoader()
{
+ #ifdef USE_JIT
FreeCodeSpace();
+ #endif
delete m_NativeFmt;
}
@@ -267,15 +294,16 @@ void VertexLoader::CompileVertexTranslator()
if (m_VtxDesc.Tex7MatIdx) {m_VertexSize += 1; m_NativeFmt->m_components |= VB_HAS_TEXMTXIDX7; WriteCall(TexMtx_ReadDirect_UByte); }
// Write vertex position loader
- WriteCall(VertexLoader_Position::GetFunction(m_VtxDesc.Position, m_VtxAttr.PosFormat, m_VtxAttr.PosElements));
+ if(g_ActiveConfig.bUseBBox) {
+ WriteCall(UpdateBoundingBoxPrepare);
+ WriteCall(VertexLoader_Position::GetFunction(m_VtxDesc.Position, m_VtxAttr.PosFormat, m_VtxAttr.PosElements));
+ WriteCall(UpdateBoundingBox);
+ } else {
+ WriteCall(VertexLoader_Position::GetFunction(m_VtxDesc.Position, m_VtxAttr.PosFormat, m_VtxAttr.PosElements));
+ }
m_VertexSize += VertexLoader_Position::GetSize(m_VtxDesc.Position, m_VtxAttr.PosFormat, m_VtxAttr.PosElements);
nat_offset += 12;
- // OK, so we just got a point. Let's go back and read it for the bounding box.
-
- if(g_ActiveConfig.bUseBBox)
- WriteCall(UpdateBoundingBox);
-
// Normals
vtx_decl.num_normals = 0;
if (m_VtxDesc.Normal != NOT_PRESENT)
@@ -307,7 +335,7 @@ void VertexLoader::CompileVertexTranslator()
nat_offset += 12;
vtx_decl.normal_offset[2] = nat_offset;
nat_offset += 12;
- }
+ }
int numNormals = (m_VtxAttr.NormalElements == 1) ? NRM_THREE : NRM_ONE;
m_NativeFmt->m_components |= VB_HAS_NRM0;
@@ -339,7 +367,7 @@ void VertexLoader::CompileVertexTranslator()
default: _assert_(0); break;
}
break;
- case INDEX8:
+ case INDEX8:
m_VertexSize += 1;
switch (m_VtxAttr.color[i].Comp)
{
@@ -474,7 +502,8 @@ void VertexLoader::WriteCall(TPipelineFunction func)
m_PipelineStages[m_numPipelineStages++] = func;
#endif
}
-
+// ARMTODO: This should be done in a better way
+#ifndef _M_GENERIC
void VertexLoader::WriteGetVariable(int bits, OpArg dest, void *address)
{
#ifdef USE_JIT
@@ -498,8 +527,9 @@ void VertexLoader::WriteSetVariable(int bits, void *address, OpArg value)
#endif
#endif
}
+#endif
-void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count)
+int VertexLoader::SetupRunVertices(int vtx_attr_group, int primitive, int const count)
{
m_numLoadedVertices += count;
@@ -518,7 +548,7 @@ void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count)
{
// if cull mode is none, ignore triangles and quads
DataSkip(count * m_VertexSize);
- return;
+ return 0;
}
m_NativeFmt->EnableComponents(m_NativeFmt->m_components);
@@ -528,7 +558,7 @@ void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count)
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[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;
@@ -542,158 +572,49 @@ void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count)
for (int i = 0; i < 2; i++)
colElements[i] = m_VtxAttr.color[i].Elements;
- // if strips or fans, make sure all vertices can fit in buffer, otherwise flush
- int granularity = 1;
- switch (primitive) {
- case 3: // strip .. hm, weird
- case 4: // fan
- if (VertexManager::GetRemainingSize() < 3 * native_stride)
- VertexManager::Flush();
- break;
- case 6: // line strip
- if (VertexManager::GetRemainingSize() < 2 * native_stride)
- VertexManager::Flush();
- break;
- case 0: granularity = 4; break; // quads
- case 2: granularity = 3; break; // tris
- case 5: granularity = 2; break; // lines
- }
-
- int startv = 0, extraverts = 0;
- int v = 0;
-
- //int remainingVerts2 = VertexManager::GetRemainingVertices(primitive);
- while (v < count)
- {
- int remainingVerts = VertexManager::GetRemainingSize() / native_stride;
- //if (remainingVerts2 - v + startv < remainingVerts)
- //remainingVerts = remainingVerts2 - v + startv;
- if (remainingVerts < granularity) {
- INCSTAT(stats.thisFrame.numBufferSplits);
- // This buffer full - break current primitive and flush, to switch to the next buffer.
- u8* plastptr = VertexManager::s_pCurBufferPointer;
- if (v - startv > 0)
- VertexManager::AddVertices(primitive, v - startv + extraverts);
- VertexManager::Flush();
- //remainingVerts2 = VertexManager::GetRemainingVertices(primitive);
- // Why does this need to be so complicated?
- switch (primitive) {
- case 3: // triangle strip, copy last two vertices
- // a little trick since we have to keep track of signs
- if (v & 1) {
- memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-2*native_stride, native_stride);
- memcpy_gc(VertexManager::s_pCurBufferPointer+native_stride, plastptr-native_stride*2, 2*native_stride);
- VertexManager::s_pCurBufferPointer += native_stride*3;
- extraverts = 3;
- }
- else {
- memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride*2, native_stride*2);
- VertexManager::s_pCurBufferPointer += native_stride*2;
- extraverts = 2;
- }
- break;
- case 4: // tri fan, copy first and last vert
- memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride*(v-startv+extraverts), native_stride);
- VertexManager::s_pCurBufferPointer += native_stride;
- memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride, native_stride);
- VertexManager::s_pCurBufferPointer += native_stride;
- extraverts = 2;
- break;
- case 6: // line strip
- memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride, native_stride);
- VertexManager::s_pCurBufferPointer += native_stride;
- extraverts = 1;
- break;
- default:
- extraverts = 0;
- break;
- }
- startv = v;
- }
- int remainingPrims = remainingVerts / granularity;
- remainingVerts = remainingPrims * granularity;
- if (count - v < remainingVerts)
- remainingVerts = count - v;
-
- #ifdef USE_JIT
- if (remainingVerts > 0) {
- loop_counter = remainingVerts;
- ((void (*)())(void*)m_compiledCode)();
- }
- #else
- for (int s = 0; s < remainingVerts; 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
- v += remainingVerts;
- }
-
- if (startv < count)
- VertexManager::AddVertices(primitive, count - startv + extraverts);
+ VertexManager::PrepareForAdditionalData(primitive, count, native_stride);
+
+ return count;
}
-
-
-
-void VertexLoader::RunCompiledVertices(int vtx_attr_group, int primitive, int count, u8* Data)
+void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int const count)
{
- m_numLoadedVertices += count;
+ auto const new_count = SetupRunVertices(vtx_attr_group, primitive, count);
+ ConvertVertices(new_count);
+ VertexManager::AddVertices(primitive, new_count);
+}
- // Flush if our vertex format is different from the currently set.
- if (g_nativeVertexFmt != NULL && g_nativeVertexFmt != m_NativeFmt)
- {
- // We really must flush here. It's possible that the native representations
- // of the two vtx formats are the same, but we have no way to easily check that
- // now.
- VertexManager::Flush();
- // Also move the Set() here?
+void VertexLoader::ConvertVertices ( int count )
+{
+#ifdef USE_JIT
+ if (count > 0) {
+ loop_counter = count;
+ ((void (*)())(void*)m_compiledCode)();
}
- g_nativeVertexFmt = m_NativeFmt;
-
- if (bpmem.genMode.cullmode == 3 && primitive < 5)
+#else
+ for (int s = 0; s < count; s++)
{
- // if cull mode is none, ignore triangles and quads
- DataSkip(count * m_VertexSize);
- return;
+ tcIndex = 0;
+ colIndex = 0;
+ s_texmtxwrite = s_texmtxread = 0;
+ for (int i = 0; i < m_numPipelineStages; i++)
+ m_PipelineStages[i]();
+ PRIM_LOG("\n");
}
+#endif
+}
- m_NativeFmt->EnableComponents(m_NativeFmt->m_components);
-
- // 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;
+void VertexLoader::RunCompiledVertices(int vtx_attr_group, int primitive, int const count, u8* Data)
+{
+ auto const new_count = SetupRunVertices(vtx_attr_group, primitive, count);
- pVtxAttr = &m_VtxAttr;
- posScale = fractionTable[m_VtxAttr.PosFrac];
- if (m_NativeFmt->m_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++)
- colElements[i] = m_VtxAttr.color[i].Elements;
+ memcpy_gc(VertexManager::s_pCurBufferPointer, Data, native_stride * new_count);
+ VertexManager::s_pCurBufferPointer += native_stride * new_count;
+ DataSkip(new_count * m_VertexSize);
- if(VertexManager::GetRemainingSize() < native_stride * count)
- VertexManager::Flush();
- memcpy_gc(VertexManager::s_pCurBufferPointer, Data, native_stride * count);
- VertexManager::s_pCurBufferPointer += native_stride * count;
- DataSkip(count * m_VertexSize);
- VertexManager::AddVertices(primitive, count);
+ VertexManager::AddVertices(primitive, new_count);
}
-
-
void VertexLoader::SetVAT(u32 _group0, u32 _group1, u32 _group2)
{
VAT vat;
@@ -724,7 +645,7 @@ void VertexLoader::SetVAT(u32 _group0, u32 _group1, u32 _group2)
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[3].Frac = vat.g1.Tex3Frac;
m_VtxAttr.texCoord[4].Elements = vat.g1.Tex4CoordElements;
m_VtxAttr.texCoord[4].Format = vat.g1.Tex4CoordFormat;