diff options
| author | Rodolfo Osvaldo Bogado <rodolfoosvaldobogado@gmail.com> | 2010-08-29 23:08:56 +0000 |
|---|---|---|
| committer | Rodolfo Osvaldo Bogado <rodolfoosvaldobogado@gmail.com> | 2010-08-29 23:08:56 +0000 |
| commit | 3e7dafbbd7708f574059bc4722c260b4f6edd6cb (patch) | |
| tree | 84730fc53fdd895cf7f8fad7833f177f5272aef7 /Source/Core/VideoCommon | |
| parent | 4229d9e01ec062714f9c784930ba60d0f0967456 (diff) | |
fully implemented display list cache with vertex data included and added in all the plugins.
still experimental, not totally optimized but must bring a nice speed up
please test for regressions an error. an please Linux people fix scons :)
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6149 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source/Core/VideoCommon')
| -rw-r--r-- | Source/Core/VideoCommon/Src/DLCache.cpp | 598 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/Src/DLCache.h | 32 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/Src/NativeVertexWriter.h | 1 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/Src/VertexLoader.cpp | 57 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/Src/VertexLoader.h | 1 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/Src/VertexLoaderManager.cpp | 8 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/Src/VertexLoaderManager.h | 1 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/VideoCommon.vcproj | 10 |
8 files changed, 707 insertions, 1 deletions
diff --git a/Source/Core/VideoCommon/Src/DLCache.cpp b/Source/Core/VideoCommon/Src/DLCache.cpp new file mode 100644 index 0000000000..f542952c85 --- /dev/null +++ b/Source/Core/VideoCommon/Src/DLCache.cpp @@ -0,0 +1,598 @@ +// Copyright (C) 2003-2009 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +// TODO: Handle cache-is-full condition :p + +#include <map> + +#include "Common.h" +#include "VideoCommon.h" +#include "Hash.h" +#include "MemoryUtil.h" +#include "DataReader.h" +#include "Statistics.h" +#include "OpcodeDecoding.h" // For the GX_ constants. + +#include "XFMemory.h" +#include "CPMemory.h" +#include "BPMemory.h" + +#include "VertexLoaderManager.h" +#include "NativeVertexWriter.h" +#include "x64Emitter.h" +#include "ABI.h" + +#include "DLCache.h" + +#define DL_CODE_CACHE_SIZE (1024*1024*16) +extern int frameCount; + +using namespace Gen; + +namespace DLCache +{ + +// Currently just recompiles the DLs themselves, doesn't bother with the vertex data. +// The speed boost is pretty small. The real big boost will come when we also store +// vertex arrays in the cached DLs. + +enum DisplayListPass { + DLPASS_ANALYZE, + DLPASS_COMPILE, + DLPASS_RUN, +}; + +struct VDataHashRegion +{ + u32 hash; + u32 start_address; + int size; +}; +typedef u8* DataPointer; +typedef std::map<u8, DataPointer> VdataMap; + +struct CachedDisplayList +{ + CachedDisplayList() + : uncachable(false), + pass(DLPASS_ANALYZE), + next_check(1), + BufferCount(0), + num_xf_reg(0), + num_cp_reg(0), + num_bp_reg(0), + num_index_xf(0), + num_draw_call(0) + { + frame_count = frameCount; + } + + bool uncachable; // if set, this DL will always be interpreted. This gets set if hash ever changes. + + int pass; + u64 dl_hash; + + int check; + int next_check; + + int frame_count; + + // ... Something containing cached vertex buffers here ... + u8 BufferCount; + VdataMap Vdata; + + int num_xf_reg; + int num_cp_reg; + int num_bp_reg; + int num_index_xf; + int num_draw_call; + + // Compile the commands themselves down to native code. + const u8* compiled_code; +}; + +// We want to allow caching DLs that start at the same address but have different lengths, +// so the size has to be in the ID. +inline u64 CreateMapId(u32 address, u32 size) +{ + return ((u64)address << 32) | size; +} + +typedef std::map<u64, CachedDisplayList> DLMap; + +static DLMap dl_map; +static DataPointer dlcode_cache; + +static Gen::XEmitter emitter; + +// First pass - analyze +bool AnalyzeAndRunDisplayList(u32 address, int size, CachedDisplayList *dl) +{ + int num_xf_reg = 0; + int num_cp_reg = 0; + int num_bp_reg = 0; + int num_index_xf = 0; + int num_draw_call = 0; + + u8* old_pVideoData = g_pVideoData; + u8* startAddress = Memory_GetPtr(address); + + // Avoid the crash if Memory_GetPtr failed .. + if (startAddress != 0) + { + g_pVideoData = startAddress; + + // temporarily swap dl and non-dl (small "hack" for the stats) + Statistics::SwapDL(); + + u8 *end = g_pVideoData + size; + while (g_pVideoData < end) + { + // Yet another reimplementation of the DL reading... + int cmd_byte = DataReadU8(); + switch (cmd_byte) + { + case GX_NOP: + break; + + case GX_LOAD_CP_REG: //0x08 + { + u8 sub_cmd = DataReadU8(); + u32 value = DataReadU32(); + LoadCPReg(sub_cmd, value); + INCSTAT(stats.thisFrame.numCPLoads); + num_cp_reg++; + } + break; + + case GX_LOAD_XF_REG: + { + u32 Cmd2 = DataReadU32(); + int transfer_size = ((Cmd2 >> 16) & 15) + 1; + u32 xf_address = Cmd2 & 0xFFFF; + // TODO - speed this up. pshufb? + u32 data_buffer[16]; + for (int i = 0; i < transfer_size; i++) + data_buffer[i] = DataReadU32(); + LoadXFReg(transfer_size, xf_address, data_buffer); + INCSTAT(stats.thisFrame.numXFLoads); + num_xf_reg++; + } + break; + + case GX_LOAD_INDX_A: //used for position matrices + { + LoadIndexedXF(DataReadU32(), 0xC); + num_index_xf++; + } + break; + case GX_LOAD_INDX_B: //used for normal matrices + { + LoadIndexedXF(DataReadU32(), 0xD); + num_index_xf++; + } + break; + case GX_LOAD_INDX_C: //used for postmatrices + { + LoadIndexedXF(DataReadU32(), 0xE); + num_index_xf++; + } + break; + case GX_LOAD_INDX_D: //used for lights + { + LoadIndexedXF(DataReadU32(), 0xF); + num_index_xf++; + } + break; + case GX_CMD_CALL_DL: + { + u32 addr = DataReadU32(); + u32 count = DataReadU32(); + ExecuteDisplayList(addr, count); + } + break; + case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that + DEBUG_LOG(VIDEO, "GX 0x44: %08x", cmd_byte); + break; + case GX_CMD_INVL_VC: // Invalidate Vertex Cache + DEBUG_LOG(VIDEO, "Invalidate (vertex cache?)"); + break; + case GX_LOAD_BP_REG: //0x61 + { + u32 bp_cmd = DataReadU32(); + LoadBPReg(bp_cmd); + INCSTAT(stats.thisFrame.numBPLoads); + num_bp_reg++; + } + break; + + // draw primitives + default: + if (cmd_byte & 0x80) + { + // load vertices (use computed vertex size from FifoCommandRunnable above) + u16 numVertices = DataReadU16(); + + VertexLoaderManager::RunVertices( + cmd_byte & GX_VAT_MASK, // Vertex loader index (0 - 7) + (cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT, + numVertices); + num_draw_call++; + } + else + { + ERROR_LOG(VIDEO, "OpcodeDecoding::Decode: Illegal command %02x", cmd_byte); + break; + } + break; + } + } + INCSTAT(stats.numDListsCalled); + INCSTAT(stats.thisFrame.numDListsCalled); + // un-swap + Statistics::SwapDL(); + } + dl->num_bp_reg = num_bp_reg; + dl->num_cp_reg = num_cp_reg; + dl->num_draw_call = num_draw_call; + dl->num_index_xf = num_index_xf; + dl->num_xf_reg = num_xf_reg; + // reset to the old pointer + g_pVideoData = old_pVideoData; + return true; +} + +// The only sensible way to detect changes to vertex data is to convert several times +// and hash the output. + +// Second pass - compile +// Since some commands can affect the size of other commands, we really have no choice +// but to compile as we go, interpreting the list. We can't compile and then execute, we must +// compile AND execute at the same time. The second time the display list gets called, we already +// have the compiled code so we don't have to interpret anymore, we just run it. +bool CompileAndRunDisplayList(u32 address, int size, CachedDisplayList *dl) +{ + u8* old_pVideoData = g_pVideoData; + u8* startAddress = Memory_GetPtr(address); + + // Avoid the crash if Memory_GetPtr failed .. + if (startAddress != 0) + { + g_pVideoData = startAddress; + + // temporarily swap dl and non-dl (small "hack" for the stats) + Statistics::SwapDL(); + + u8 *end = g_pVideoData + size; + + emitter.AlignCode4(); + dl->compiled_code = emitter.GetCodePtr(); + emitter.ABI_EmitPrologue(4); + + while (g_pVideoData < end) + { + // Yet another reimplementation of the DL reading... + int cmd_byte = DataReadU8(); + switch (cmd_byte) + { + case GX_NOP: + // Execute + // Compile + break; + + case GX_LOAD_CP_REG: //0x08 + { + // Execute + u8 sub_cmd = DataReadU8(); + u32 value = DataReadU32(); + LoadCPReg(sub_cmd, value); + INCSTAT(stats.thisFrame.numCPLoads); + + // Compile + emitter.ABI_CallFunctionCC((void *)&LoadCPReg, sub_cmd, value); + } + break; + + case GX_LOAD_XF_REG: + { + // Execute + u32 Cmd2 = DataReadU32(); + int transfer_size = ((Cmd2 >> 16) & 15) + 1; + u32 xf_address = Cmd2 & 0xFFFF; + // TODO - speed this up. pshufb? + DataPointer real_data_buffer = (DataPointer) new u8[transfer_size * 4]; + u32 *data_buffer = (u32*)real_data_buffer; + for (int i = 0; i < transfer_size; i++) + data_buffer[i] = DataReadU32(); + LoadXFReg(transfer_size, xf_address, data_buffer); + INCSTAT(stats.thisFrame.numXFLoads); + dl->Vdata[dl->BufferCount] = real_data_buffer; + dl->BufferCount++; + // Compile + emitter.ABI_CallFunctionCCP((void *)&LoadXFReg, transfer_size, xf_address, data_buffer); + } + break; + + case GX_LOAD_INDX_A: //used for position matrices + { + u32 value = DataReadU32(); + // Execute + LoadIndexedXF(value, 0xC); + // Compile + emitter.ABI_CallFunctionCC((void *)&LoadIndexedXF, value, 0xC); + } + break; + case GX_LOAD_INDX_B: //used for normal matrices + { + u32 value = DataReadU32(); + // Execute + LoadIndexedXF(value, 0xD); + // Compile + emitter.ABI_CallFunctionCC((void *)&LoadIndexedXF, value, 0xD); + } + break; + case GX_LOAD_INDX_C: //used for postmatrices + { + u32 value = DataReadU32(); + // Execute + LoadIndexedXF(value, 0xE); + // Compile + emitter.ABI_CallFunctionCC((void *)&LoadIndexedXF, value, 0xE); + } + break; + case GX_LOAD_INDX_D: //used for lights + { + u32 value = DataReadU32(); + // Execute + LoadIndexedXF(value, 0xF); + // Compile + emitter.ABI_CallFunctionCC((void *)&LoadIndexedXF, value, 0xF); + } + break; + + case GX_CMD_CALL_DL: + { + u32 addr= DataReadU32(); + u32 count = DataReadU32(); + ExecuteDisplayList(addr, count); + emitter.ABI_CallFunctionCC((void *)&ExecuteDisplayList, address, count); + } + break; + + case GX_CMD_UNKNOWN_METRICS: + // zelda 4 swords calls it and checks the metrics registers after that + break; + + case GX_CMD_INVL_VC:// Invalidate (vertex cache?) + DEBUG_LOG(VIDEO, "Invalidate (vertex cache?)"); + break; + + case GX_LOAD_BP_REG: //0x61 + { + u32 bp_cmd = DataReadU32(); + // Execute + LoadBPReg(bp_cmd); + INCSTAT(stats.thisFrame.numBPLoads); + // Compile + emitter.ABI_CallFunctionC((void *)&LoadBPReg, bp_cmd); + } + break; + + // draw primitives + default: + if (cmd_byte & 0x80) + { + // load vertices (use computed vertex size from FifoCommandRunnable above) + + // Execute + u16 numVertices = DataReadU16(); + + u64 pre_draw_video_data = (u64)g_pVideoData; + + u8* StartAddress = VertexManager::s_pBaseBufferPointer; + VertexManager::Flush(); + VertexLoaderManager::RunVertices( + cmd_byte & GX_VAT_MASK, // Vertex loader index (0 - 7) + (cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT, + numVertices); + u8* EndAddress = VertexManager::s_pCurBufferPointer; + u32 Vdatasize = (u32)(EndAddress - StartAddress); + if (size > 0) + { + // Compile + DataPointer NewData = (DataPointer)new u8[Vdatasize]; + memcpy(NewData,StartAddress,Vdatasize); + dl->Vdata[dl->BufferCount] = NewData; + dl->BufferCount++; + emitter.ABI_CallFunctionCCCP((void *)&VertexLoaderManager::RunCompiledVertices,cmd_byte & GX_VAT_MASK, (cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT, numVertices, NewData); + } + } + else + { + ERROR_LOG(VIDEO, "DLCache::CompileAndRun: Illegal command %02x", cmd_byte); + break; + } + break; + } + } + emitter.ABI_EmitEpilogue(4); + INCSTAT(stats.numDListsCalled); + INCSTAT(stats.thisFrame.numDListsCalled); + Statistics::SwapDL(); + } + g_pVideoData = old_pVideoData; + return true; +} + +void Init() +{ + dlcode_cache = (DataPointer)AllocateExecutableMemory(DL_CODE_CACHE_SIZE, false); // Don't need low memory. + emitter.SetCodePtr(dlcode_cache); +} + +void Shutdown() +{ + Clear(); + FreeMemoryPages(dlcode_cache, DL_CODE_CACHE_SIZE); + dlcode_cache = NULL; +} + +void Clear() +{ + DLMap::iterator iter = dl_map.begin(); + while (iter != dl_map.end()) { + CachedDisplayList &entry = iter->second; + VdataMap::iterator viter = entry.Vdata.begin(); + while (viter != entry.Vdata.end()) + { + DataPointer &ventry = viter->second; + delete [] ventry; + entry.Vdata.erase(viter++); + } + iter++; + } + dl_map.clear(); + // Reset the cache pointers. + emitter.SetCodePtr(dlcode_cache); +} + +void ProgressiveCleanup() +{ + DLMap::iterator iter = dl_map.begin(); + while (iter != dl_map.end()) { + CachedDisplayList &entry = iter->second; + int limit = iter->second.uncachable ? 1200 : 400; + if (entry.frame_count < frameCount - limit) { + // entry.Destroy(); + VdataMap::iterator viter = entry.Vdata.begin(); + while (viter != entry.Vdata.end()) + { + DataPointer &ventry = viter->second; + delete [] ventry; + entry.Vdata.erase(viter++); + } + dl_map.erase(iter++); // (this is gcc standard!) + } + else + ++iter; + } +} + +} // namespace + +// NOTE - outside the namespace on purpose. +bool HandleDisplayList(u32 address, u32 size) +{ + // Disable display list caching since the benefit isn't much to write home about + // right now... + //Fixed DlistCaching now is fully functional benefits still marginal but when vertex data is stored here the story will be diferent :) + //to test remove the next line; + + if(size == 0) return false; + u64 dl_id = DLCache::CreateMapId(address, size); + DLCache::DLMap::iterator iter = DLCache::dl_map.find(dl_id); + + stats.numDListsAlive = (int)DLCache::dl_map.size(); + if (iter != DLCache::dl_map.end()) + { + DLCache::CachedDisplayList &dl = iter->second; + if (dl.uncachable) + { + // We haven't compiled it - let's return false so it gets + // interpreted. + return false; + } + + // Got one! And it's been compiled too, so let's run the compiled code! + switch (dl.pass) + { + case DLCache::DLPASS_ANALYZE: + PanicAlert("DLPASS_ANALYZE - should have been done the first pass"); + break; + case DLCache::DLPASS_COMPILE: + // First, check that the hash is the same as the last time. + if (dl.dl_hash != GetHash64(Memory_GetPtr(address), size,0)) + { + // PanicAlert("uncachable %08x", address); + dl.uncachable = true; + return false; + } + DLCache::CompileAndRunDisplayList(address, size, &dl); + dl.pass = DLCache::DLPASS_RUN; + break; + case DLCache::DLPASS_RUN: + { + // Every N draws, check hash + dl.check--; + if (dl.check <= 0) + { + if (dl.dl_hash != GetHash64(Memory_GetPtr(address), size,0)) + { + dl.uncachable = true; + DLCache::VdataMap::iterator viter = dl.Vdata.begin(); + while (viter != dl.Vdata.end()) + { + DLCache::DataPointer &ventry = viter->second; + delete [] ventry; + dl.Vdata.erase(viter++); + } + dl.BufferCount = 0; + return false; + } + dl.check = dl.next_check; + dl.next_check *= 2; + if (dl.next_check > 1024) + dl.next_check = 1024; + } + dl.frame_count= frameCount; + u8 *old_datareader = g_pVideoData; + ((void (*)())(void*)(dl.compiled_code))(); + Statistics::SwapDL(); + ADDSTAT(stats.thisFrame.numCPLoadsInDL,dl.num_cp_reg); + ADDSTAT(stats.thisFrame.numXFLoadsInDL,dl.num_xf_reg); + ADDSTAT(stats.thisFrame.numBPLoadsInDL,dl.num_bp_reg); + + ADDSTAT(stats.thisFrame.numCPLoads,dl.num_cp_reg); + ADDSTAT(stats.thisFrame.numXFLoads,dl.num_xf_reg); + ADDSTAT(stats.thisFrame.numBPLoads,dl.num_bp_reg); + + INCSTAT(stats.numDListsCalled); + INCSTAT(stats.thisFrame.numDListsCalled); + + Statistics::SwapDL(); + g_pVideoData = old_datareader; + break; + } + } + return true; + } + + DLCache::CachedDisplayList dl; + + if (DLCache::AnalyzeAndRunDisplayList(address, size, &dl)) { + dl.dl_hash = GetHash64(Memory_GetPtr(address), size,0); + dl.pass = DLCache::DLPASS_COMPILE; + dl.check = 1; + dl.next_check = 1; + DLCache::dl_map[dl_id] = dl; + return true; + } else { + dl.uncachable = true; + DLCache::dl_map[dl_id] = dl; + return true; // don't also interpret the list. + } +} diff --git a/Source/Core/VideoCommon/Src/DLCache.h b/Source/Core/VideoCommon/Src/DLCache.h new file mode 100644 index 0000000000..9286f52637 --- /dev/null +++ b/Source/Core/VideoCommon/Src/DLCache.h @@ -0,0 +1,32 @@ +// Copyright (C) 2003-2009 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef _DLCACHE_H +#define _DLCACHE_H + +bool HandleDisplayList(u32 address, u32 size); + +namespace DLCache { + +void Init(); +void Shutdown(); +void ProgressiveCleanup(); +void Clear(); + +} // namespace + +#endif // _DLCACHE_H diff --git a/Source/Core/VideoCommon/Src/NativeVertexWriter.h b/Source/Core/VideoCommon/Src/NativeVertexWriter.h index 6764c7abcd..d24af1feea 100644 --- a/Source/Core/VideoCommon/Src/NativeVertexWriter.h +++ b/Source/Core/VideoCommon/Src/NativeVertexWriter.h @@ -23,6 +23,7 @@ namespace VertexManager { void AddVertices(int primitive, int numvertices); +void AddCompiledVertices(int primitive, int numvertices, u8* Vdata); void Flush(); // flushes the current buffer int GetRemainingSize(); // remaining space in the current buffer. int GetRemainingVertices(int primitive); // remaining number of vertices that can be processed in one AddVertices call diff --git a/Source/Core/VideoCommon/Src/VertexLoader.cpp b/Source/Core/VideoCommon/Src/VertexLoader.cpp index a09d81c9b6..072e239d9e 100644 --- a/Source/Core/VideoCommon/Src/VertexLoader.cpp +++ b/Source/Core/VideoCommon/Src/VertexLoader.cpp @@ -680,6 +680,63 @@ void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count) VertexManager::AddVertices(primitive, count - startv + extraverts); } + + + +void VertexLoader::RunCompiledVertices(int vtx_attr_group, int primitive, int count, u8* Data) +{ + DVSTARTPROFILE(); + + m_numLoadedVertices += 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? + } + g_nativeVertexFmt = m_NativeFmt; + + if (bpmem.genMode.cullmode == 3 && primitive < 5) + { + // if cull mode is none, ignore triangles and quads + DataSkip(count * m_VertexSize); + return; + } + + 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; + + pVtxAttr = &m_VtxAttr; + posScale = 1.0f / float(1 << m_VtxAttr.PosFrac); + if (m_NativeFmt->m_components & VB_HAS_UVALL) + for (int i = 0; i < 8; i++) + tcScale[i] = texCoordFrac[m_VtxAttr.texCoord[i].Frac]; + for (int i = 0; i < 2; i++) + colElements[i] = m_VtxAttr.color[i].Elements; + + if(VertexManager::GetRemainingSize() < native_stride * count) + VertexManager::Flush(); + memcpy_gc(VertexManager::s_pCurBufferPointer, Data, native_stride * count); + VertexManager::s_pCurBufferPointer += native_stride * count; + VertexManager::AddVertices(primitive, count); +} + + + void VertexLoader::SetVAT(u32 _group0, u32 _group1, u32 _group2) { VAT vat; diff --git a/Source/Core/VideoCommon/Src/VertexLoader.h b/Source/Core/VideoCommon/Src/VertexLoader.h index 8c72954530..4ec3c5f64a 100644 --- a/Source/Core/VideoCommon/Src/VertexLoader.h +++ b/Source/Core/VideoCommon/Src/VertexLoader.h @@ -84,6 +84,7 @@ public: int GetVertexSize() const {return m_VertexSize;} void RunVertices(int vtx_attr_group, int primitive, int count); + void RunCompiledVertices(int vtx_attr_group, int primitive, int count, u8* Data); // For debugging / profiling void AppendToString(std::string *dest) const; diff --git a/Source/Core/VideoCommon/Src/VertexLoaderManager.cpp b/Source/Core/VideoCommon/Src/VertexLoaderManager.cpp index 176e9ad0c7..c03f0d94fd 100644 --- a/Source/Core/VideoCommon/Src/VertexLoaderManager.cpp +++ b/Source/Core/VideoCommon/Src/VertexLoaderManager.cpp @@ -143,6 +143,14 @@ void RunVertices(int vtx_attr_group, int primitive, int count) g_VertexLoaders[vtx_attr_group]->RunVertices(vtx_attr_group, primitive, count); } +void RunCompiledVertices(int vtx_attr_group, int primitive, int count, u8* Data) +{ + if (!count || !Data) + return; + RefreshLoader(vtx_attr_group); + g_VertexLoaders[vtx_attr_group]->RunCompiledVertices(vtx_attr_group, primitive, count,Data); +} + int GetVertexSize(int vtx_attr_group) { RefreshLoader(vtx_attr_group); diff --git a/Source/Core/VideoCommon/Src/VertexLoaderManager.h b/Source/Core/VideoCommon/Src/VertexLoaderManager.h index 91d8397870..e61977b07e 100644 --- a/Source/Core/VideoCommon/Src/VertexLoaderManager.h +++ b/Source/Core/VideoCommon/Src/VertexLoaderManager.h @@ -30,6 +30,7 @@ namespace VertexLoaderManager int GetVertexSize(int vtx_attr_group); void RunVertices(int vtx_attr_group, int primitive, int count); + void RunCompiledVertices(int vtx_attr_group, int primitive, int count, u8* Data); // For debugging void AppendListToString(std::string *dest); diff --git a/Source/Core/VideoCommon/VideoCommon.vcproj b/Source/Core/VideoCommon/VideoCommon.vcproj index af82f36aa4..fd9c57a138 100644 --- a/Source/Core/VideoCommon/VideoCommon.vcproj +++ b/Source/Core/VideoCommon/VideoCommon.vcproj @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="Windows-1252"?> <VisualStudioProject ProjectType="Visual C++" - Version="9.00" + Version="9,00" Name="VideoCommon" ProjectGUID="{E5D1F0C0-AA07-4841-A4EB-4CF4DAA6B0FA}" RootNamespace="VideoCommon" @@ -635,6 +635,14 @@ > </File> <File + RelativePath=".\Src\DLCache.cpp" + > + </File> + <File + RelativePath=".\Src\DLCache.h" + > + </File> + <File RelativePath=".\Src\VertexLoader.cpp" > </File> |
