VideoCommon: remove Cache Displaylist

This option was known to break every second game and only boost a bit.
It also seems to be broken because of streaming into pinned memory and buffer storage buffers.

v2: also remove dlc_desc
This commit is contained in:
degasus 2014-01-30 15:51:20 +01:00
parent 72cc6431e5
commit 010a0d481a
24 changed files with 4 additions and 931 deletions

View File

@ -91,7 +91,6 @@ public final class UserPreferences
editor.putString("externalFrameBuffer", "Real");
}
editor.putBoolean("cacheDisplayLists", getConfig("gfx_opengl.ini", "Hacks", "DlistCachingEnable", "False").equals("True"));
editor.putBoolean("disableDestinationAlpha", getConfig("gfx_opengl.ini", "Settings", "DstAlphaPass", "False").equals("True"));
editor.putBoolean("fastDepthCalculation", getConfig("gfx_opengl.ini", "Settings", "FastDepthCalc", "True").equals("True"));
@ -234,7 +233,6 @@ public final class UserPreferences
NativeLibrary.SetConfig("gfx_opengl.ini", "Settings", "UseRealXFB", "True");
}
NativeLibrary.SetConfig("gfx_opengl.ini", "Hacks", "DlistCachingEnable", dlistCachingEnabled ? "True" : "False");
NativeLibrary.SetConfig("gfx_opengl.ini", "Settings", "DstAlphaPass", disableDstAlphaPass ? "True" : "False");
NativeLibrary.SetConfig("gfx_opengl.ini", "Settings", "FastDepthCalc", useFastDepthCalc ? "True" : "False");

View File

@ -117,7 +117,6 @@ wxString use_ffv1_desc = wxTRANSLATE("Encode frame dumps using the FFV1 codec.\n
#endif
wxString free_look_desc = wxTRANSLATE("This feature allows you to change the game's camera.\nMove the mouse while holding the right mouse button to pan and while holding the middle button to move.\nHold SHIFT and press one of the WASD keys to move the camera by a certain step distance (SHIFT+0 to move faster and SHIFT+9 to move slower). Press SHIFT+R to reset the camera.\n\nIf unsure, leave this unchecked.");
wxString crop_desc = wxTRANSLATE("Crop the picture from 4:3 to 5:4 or from 16:9 to 16:10.\n\nIf unsure, leave this unchecked.");
wxString dlc_desc = wxTRANSLATE("[EXPERIMENTAL]\nSpeeds up emulation a bit by caching display lists.\nPossibly causes issues though.\n\nIf unsure, leave this unchecked.");
wxString omp_desc = wxTRANSLATE("Use multiple threads to decode textures.\nMight result in a speedup (especially on CPUs with more than two cores).\n\nIf unsure, leave this unchecked.");
wxString ppshader_desc = wxTRANSLATE("Apply a post-processing effect after finishing a frame.\n\nIf unsure, select (off).");
wxString cache_efb_copies_desc = wxTRANSLATE("Slightly speeds up EFB to RAM copies by sacrificing emulation accuracy.\nSometimes also increases visual quality.\nIf you're experiencing any issues, try raising texture cache accuracy or disable this option.\n\nIf unsure, leave this unchecked.");
@ -495,7 +494,6 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con
// - other hacks
{
wxGridSizer* const szr_other = new wxGridSizer(2, 5, 5);
szr_other->Add(CreateCheckBox(page_hacks, _("Cache Display Lists"), wxGetTranslation(dlc_desc), vconfig.bDlistCachingEnable));
szr_other->Add(CreateCheckBox(page_hacks, _("Disable Destination Alpha"), wxGetTranslation(disable_dstalpha_desc), vconfig.bDstAlphaPass));
szr_other->Add(CreateCheckBox(page_hacks, _("OpenMP Texture Decoder"), wxGetTranslation(omp_desc), vconfig.bOMPDecoder));
szr_other->Add(CreateCheckBox(page_hacks, _("Fast Depth Calculation"), wxGetTranslation(fast_depth_calc_desc), vconfig.bFastDepthCalc));

View File

@ -8,7 +8,6 @@
#include "Timer.h"
#include "Debugger.h"
#include "DLCache.h"
#include "EmuWindow.h"
#include "Fifo.h"
#include "OnScreenDisplay.h"
@ -950,7 +949,6 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangle& r
GFX_DEBUGGER_PAUSE_AT(NEXT_FRAME, true);
DLCache::ProgressiveCleanup();
TextureCache::Cleanup();
// Enable configuration changes

View File

@ -20,7 +20,6 @@
#include "Host.h"
#include "Debugger/DebuggerPanel.h"
#include "DLCache.h"
#include "EmuWindow.h"
#include "IndexGenerator.h"
#include "FileUtil.h"
@ -201,7 +200,6 @@ void VideoBackend::Video_Prepare()
PixelShaderManager::Init();
CommandProcessor::Init();
PixelEngine::Init();
DLCache::Init();
// Tell the host that the window is ready
Host_Message(WM_USER_CREATE);
@ -219,7 +217,6 @@ void VideoBackend::Shutdown()
s_swapRequested = FALSE;
// VideoCommon
DLCache::Shutdown();
Fifo_Shutdown();
CommandProcessor::Shutdown();
PixelShaderManager::Shutdown();

View File

@ -33,7 +33,6 @@
#include "TextureCache.h"
#include "RasterFont.h"
#include "VertexShaderGen.h"
#include "DLCache.h"
#include "ProgramShaderCache.h"
#include "VertexShaderManager.h"
#include "VertexLoaderManager.h"
@ -1588,7 +1587,6 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangle& r
}
// Clean out old stuff from caches. It's not worth it to clean out the shader caches.
DLCache::ProgressiveCleanup();
TextureCache::Cleanup();
frameCount++;

View File

@ -76,7 +76,6 @@ Make AA apply instantly during gameplay if possible
#include "TextureConverter.h"
#include "PostProcessing.h"
#include "OnScreenDisplay.h"
#include "DLCache.h"
#include "FramebufferManager.h"
#include "Core.h"
#include "Host.h"
@ -225,9 +224,6 @@ void VideoBackend::Video_Prepare()
GL_REPORT_ERRORD();
VertexLoaderManager::Init();
TextureConverter::Init();
#ifndef _M_GENERIC
DLCache::Init();
#endif
// Notify the core that the video backend is ready
Host_Message(WM_USER_CREATE);
@ -250,9 +246,6 @@ void VideoBackend::Video_Cleanup() {
s_efbAccessRequested = false;
s_FifoShuttingDown = false;
s_swapRequested = false;
#ifndef _M_GENERIC
DLCache::Shutdown();
#endif
Fifo_Shutdown();
// The following calls are NOT Thread Safe

View File

@ -40,11 +40,9 @@ set(SRCS BPFunctions.cpp
set(LIBS core png)
if(NOT _M_GENERIC)
set(SRCS ${SRCS} TextureDecoder_x64.cpp
DLCache_x64.cpp)
set(SRCS ${SRCS} TextureDecoder_x64.cpp)
else()
set(SRCS ${SRCS} TextureDecoder_Generic.cpp
DLCache_Generic.cpp)
set(SRCS ${SRCS} TextureDecoder_Generic.cpp)
endif()
if(NOT ${CL} STREQUAL CL-NOTFOUND)
list(APPEND LIBS ${CL})

View File

@ -17,7 +17,6 @@
#include "HW/ProcessorInterface.h"
#include "HW/GPFifo.h"
#include "HW/Memmap.h"
#include "DLCache.h"
#include "HW/SystemTimers.h"
#include "Core.h"
@ -409,7 +408,6 @@ void Write16(const u16 _Value, const u32 _Address)
{
ResetVideoBuffer();
}
IncrementCheckContextId();
DEBUG_LOG(COMMANDPROCESSOR,"Try to write to FIFO_RW_DISTANCE_HI : %04x", _Value);
break;
case FIFO_RW_DISTANCE_LO:
@ -527,7 +525,6 @@ void SetCpStatus(bool isCPUThread)
{
INFO_LOG(COMMANDPROCESSOR, "Hit breakpoint at %i", fifo.CPReadPointer);
fifo.bFF_Breakpoint = true;
IncrementCheckContextId();
}
}
else

View File

@ -1,20 +0,0 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#ifndef _DLCACHE_H
#define _DLCACHE_H
bool HandleDisplayList(u32 address, u32 size);
void IncrementCheckContextId();
namespace DLCache {
void Init();
void Shutdown();
void ProgressiveCleanup();
void Clear();
} // namespace
#endif // _DLCACHE_H

View File

@ -1,52 +0,0 @@
// 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 "Common.h"
#include "DLCache.h"
namespace DLCache
{
void Init()
{
}
void Shutdown()
{
}
void Clear()
{
}
void ProgressiveCleanup()
{
}
} // namespace
// NOTE - outside the namespace on purpose.
bool HandleDisplayList(u32 address, u32 size)
{
return false;
}
void IncrementCheckContextId()
{
}

View File

@ -1,775 +0,0 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
// TODO: Handle cache-is-full condition :p
#include <unordered_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 "HW/Memmap.h"
#include "XFMemory.h"
#include "CPMemory.h"
#include "BPMemory.h"
#include "VertexLoaderManager.h"
#include "VertexManagerBase.h"
#include "x64Emitter.h"
#include "x64ABI.h"
#include "DLCache.h"
#include "VideoConfig.h"
#define DL_CODE_CACHE_SIZE (1024*1024*16)
#define DL_CODE_CLEAR_THRESHOLD (16 * 1024)
extern int frameCount;
static u32 CheckContextId;
using namespace Gen;
namespace DLCache
{
enum DisplayListPass {
DLPASS_ANALYZE,
DLPASS_COMPILE,
DLPASS_RUN,
};
#define DL_HASH_STEPS 512
struct ReferencedDataRegion
{
ReferencedDataRegion()
:hash(0),
start_address(NULL),
NextRegion(NULL),
size(0),
MustClean(0)
{}
u64 hash;
u8* start_address;
ReferencedDataRegion* NextRegion;
u32 size;
u32 MustClean;
int IntersectsMemoryRange(u8* range_address, u32 range_size)
{
if (start_address + size < range_address)
return -1;
if (start_address >= range_address + range_size)
return 1;
return 0;
}
};
struct CachedDisplayList
{
CachedDisplayList()
: Regions(NULL),
LastRegion(NULL),
uncachable(false),
num_xf_reg(0),
num_cp_reg(0),
num_bp_reg(0),
num_index_xf(0),
num_draw_call(0),
pass(DLPASS_ANALYZE),
BufferCount(0)
{
frame_count = frameCount;
}
u64 dl_hash;
// ... Something containing cached vertex buffers here ...
ReferencedDataRegion* Regions;
ReferencedDataRegion* LastRegion;
// Compile the commands themselves down to native code.
const u8* compiled_code;
u32 uncachable; // if set, this DL will always be interpreted. This gets set if hash ever changes.
// Analytic data
u32 num_xf_reg;
u32 num_cp_reg;
u32 num_bp_reg;
u32 num_index_xf;
u32 num_draw_call;
u32 pass;
u32 check;
int frame_count;
u32 BufferCount;
void InsertRegion(ReferencedDataRegion* NewRegion)
{
if(LastRegion)
{
LastRegion->NextRegion = NewRegion;
}
LastRegion = NewRegion;
if(!Regions)
{
Regions = LastRegion;
}
BufferCount++;
}
void InsertOverlapingRegion(u8* RegionStartAddress, u32 Size)
{
ReferencedDataRegion* NewRegion = FindOverlapingRegion(RegionStartAddress, Size);
if(NewRegion)
{
bool RegionChanged = false;
if(RegionStartAddress < NewRegion->start_address)
{
NewRegion->start_address = RegionStartAddress;
RegionChanged = true;
}
if(RegionStartAddress + Size > NewRegion->start_address + NewRegion->size)
{
NewRegion->size += (u32)((RegionStartAddress + Size) - (NewRegion->start_address + NewRegion->size));
RegionChanged = true;
}
if(RegionChanged)
NewRegion->hash = GetHash64(NewRegion->start_address, NewRegion->size, DL_HASH_STEPS);
}
else
{
NewRegion = new ReferencedDataRegion;
NewRegion->MustClean = false;
NewRegion->size = Size;
NewRegion->start_address = RegionStartAddress;
NewRegion->hash = GetHash64(RegionStartAddress, Size, DL_HASH_STEPS);
InsertRegion(NewRegion);
}
}
bool CheckRegions()
{
ReferencedDataRegion* Current = Regions;
while(Current)
{
if(Current->hash)
{
if(Current->hash != GetHash64(Current->start_address, Current->size, DL_HASH_STEPS))
return false;
}
Current = Current->NextRegion;
}
return true;
}
ReferencedDataRegion* FindOverlapingRegion(u8* RegionStart, u32 Regionsize)
{
ReferencedDataRegion* Current = Regions;
while(Current)
{
if(!Current->IntersectsMemoryRange(RegionStart, Regionsize))
return Current;
Current = Current->NextRegion;
}
return Current;
}
void ClearRegions()
{
ReferencedDataRegion* Current = Regions;
while(Current)
{
ReferencedDataRegion* temp = Current;
Current = Current->NextRegion;
if(temp->MustClean)
delete [] temp->start_address;
delete temp;
}
LastRegion = NULL;
Regions = NULL;
}
};
// 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;
}
inline u64 CreateVMapId(u32 VATUSED)
{
u64 vmap_id = 0x9368e53c2f6af274ULL ^ g_VtxDesc.Hex;
for(int i = 0; i < 8 ; i++)
{
if(VATUSED & (1 << i))
{
vmap_id ^= (((u64)g_VtxAttr[i].g0.Hex) | (((u64)g_VtxAttr[i].g1.Hex) << 32)) ^ (((u64)g_VtxAttr[i].g2.Hex) << i);
}
}
for(int i = 0; i < 12; i++)
{
if(VATUSED & (1 << (i + 16)))
vmap_id ^= (((u64)arraybases[i]) ^ (((u64)arraystrides[i]) << 32));
}
return vmap_id;
}
typedef std::unordered_map<u64, CachedDisplayList> DLMap;
struct VDlist
{
DLMap dl_map;
u32 VATUsed;
u32 count;
};
typedef std::unordered_map<u64, VDlist> VDLMap;
static VDLMap dl_map;
static u8* dlcode_cache;
static Gen::XEmitter emitter;
// First pass - analyze
u32 AnalyzeAndRunDisplayList(u32 address, u32 size, CachedDisplayList *dl)
{
u8* old_pVideoData = g_pVideoData;
u8* startAddress = Memory::GetPointer(address);
u32 num_xf_reg = 0;
u32 num_cp_reg = 0;
u32 num_bp_reg = 0;
u32 num_index_xf = 0;
u32 num_draw_call = 0;
u32 result = 0;
// Avoid the crash if Memory::GetPointer 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;
GC_ALIGNED128(u32 data_buffer[16]);
DataReadU32xFuncs[transfer_size-1](data_buffer);
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();
if(numVertices > 0)
{
result |= 1 << (cmd_byte & GX_VAT_MASK);
VertexLoaderManager::RunVertices(
cmd_byte & GX_VAT_MASK, // Vertex loader index (0 - 7)
(cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT,
numVertices);
num_draw_call++;
const u32 tc[12] = {
g_VtxDesc.Position, g_VtxDesc.Normal, g_VtxDesc.Color0, g_VtxDesc.Color1, g_VtxDesc.Tex0Coord, g_VtxDesc.Tex1Coord,
g_VtxDesc.Tex2Coord, g_VtxDesc.Tex3Coord, g_VtxDesc.Tex4Coord, g_VtxDesc.Tex5Coord, g_VtxDesc.Tex6Coord, (const u32)((g_VtxDesc.Hex >> 31) & 3)
};
for(int i = 0; i < 12; i++)
{
if(tc[i] > 1)
{
result |= 1 << (i + 16);
}
}
}
}
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 result;
}
// 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.
void CompileAndRunDisplayList(u32 address, u32 size, CachedDisplayList *dl)
{
u8* old_pVideoData = g_pVideoData;
u8* startAddress = Memory::GetPointer(address);
// Avoid the crash if Memory::GetPointer 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_PushAllCalleeSavedRegsAndAdjustStack();
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;
ReferencedDataRegion* NewRegion = new ReferencedDataRegion;
NewRegion->MustClean = true;
NewRegion->size = transfer_size * 4;
NewRegion->start_address = (u8*) new u8[NewRegion->size+15+12]; // alignment and guaranteed space
NewRegion->hash = 0;
dl->InsertRegion(NewRegion);
u32 *data_buffer = (u32*)(u8*)(((size_t)NewRegion->start_address+0xf)&~0xf);
DataReadU32xFuncs[transfer_size-1](data_buffer);
LoadXFReg(transfer_size, xf_address, data_buffer);
INCSTAT(stats.thisFrame.numXFLoads);
// 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, addr, 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)
u16 numVertices = DataReadU16();
if(numVertices > 0)
{
// Execute
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);
u32 Vdatasize = (u32)(VertexManager::s_pCurBufferPointer - StartAddress);
if (Vdatasize > 0)
{
// Compile
ReferencedDataRegion* NewRegion = new ReferencedDataRegion;
NewRegion->MustClean = true;
NewRegion->size = Vdatasize;
NewRegion->start_address = (u8*)new u8[Vdatasize];
NewRegion->hash = 0;
dl->InsertRegion(NewRegion);
memcpy(NewRegion->start_address, StartAddress, Vdatasize);
emitter.ABI_CallFunctionCCCP((void *)&VertexLoaderManager::RunCompiledVertices, cmd_byte & GX_VAT_MASK, (cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT, numVertices, NewRegion->start_address);
const u32 tc[12] = {
g_VtxDesc.Position, g_VtxDesc.Normal, g_VtxDesc.Color0, g_VtxDesc.Color1, g_VtxDesc.Tex0Coord, g_VtxDesc.Tex1Coord,
g_VtxDesc.Tex2Coord, g_VtxDesc.Tex3Coord, g_VtxDesc.Tex4Coord, g_VtxDesc.Tex5Coord, g_VtxDesc.Tex6Coord, (const u32)((g_VtxDesc.Hex >> 31) & 3)
};
for(int i = 0; i < 12; i++)
{
if(tc[i] > 1)
{
u8* saddr = cached_arraybases[i];
int arraySize = arraystrides[i] * ((tc[i] == 2)? numVertices : ((numVertices < 1024)? 2 * numVertices : numVertices));
dl->InsertOverlapingRegion(saddr, arraySize);
}
}
}
}
}
else
{
ERROR_LOG(VIDEO, "DLCache::CompileAndRun: Illegal command %02x", cmd_byte);
break;
}
break;
}
}
emitter.ABI_PopAllCalleeSavedRegsAndAdjustStack();
emitter.RET();
INCSTAT(stats.numDListsCalled);
INCSTAT(stats.thisFrame.numDListsCalled);
Statistics::SwapDL();
}
g_pVideoData = old_pVideoData;
}
void Init()
{
CheckContextId = 0;
dlcode_cache = (u8*)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()
{
VDLMap::iterator iter = dl_map.begin();
while (iter != dl_map.end())
{
VDlist &ParentEntry = iter->second;
DLMap::iterator childiter = ParentEntry.dl_map.begin();
while (childiter != ParentEntry.dl_map.end())
{
CachedDisplayList &entry = childiter->second;
entry.ClearRegions();
childiter++;
}
ParentEntry.dl_map.clear();
iter++;
}
dl_map.clear();
// Reset the cache pointers.
emitter.SetCodePtr(dlcode_cache);
}
void ProgressiveCleanup()
{
VDLMap::iterator iter = dl_map.begin();
while (iter != dl_map.end())
{
VDlist &ParentEntry = iter->second;
DLMap::iterator childiter = ParentEntry.dl_map.begin();
while (childiter != ParentEntry.dl_map.end())
{
CachedDisplayList &entry = childiter->second;
int limit = 3600;
if (entry.frame_count < frameCount - limit)
{
entry.ClearRegions();
ParentEntry.dl_map.erase(childiter++); // (this is gcc standard!)
}
else
{
++childiter;
}
}
if(ParentEntry.dl_map.empty())
{
dl_map.erase(iter++);
}
else
{
iter++;
}
}
}
static size_t GetSpaceLeft()
{
return DL_CODE_CACHE_SIZE - (emitter.GetCodePtr() - dlcode_cache);
}
} // namespace
// NOTE - outside the namespace on purpose.
bool HandleDisplayList(u32 address, u32 size)
{
//Fixed DlistCaching now is fully functional still some things to workout
if(!g_ActiveConfig.bDlistCachingEnable)
return false;
if(size == 0)
return false;
// TODO: Is this thread safe?
if (DLCache::GetSpaceLeft() < DL_CODE_CLEAR_THRESHOLD)
{
DLCache::Clear();
}
u64 dl_id = DLCache::CreateMapId(address, size);
u64 vhash = 0;
DLCache::VDLMap::iterator Parentiter = DLCache::dl_map.find(dl_id);
DLCache::DLMap::iterator iter;
bool childexist = false;
if (Parentiter != DLCache::dl_map.end())
{
vhash = DLCache::CreateVMapId(Parentiter->second.VATUsed);
iter = Parentiter->second.dl_map.find(vhash);
childexist = iter != Parentiter->second.dl_map.end();
}
if (Parentiter != DLCache::dl_map.end() && childexist)
{
DLCache::CachedDisplayList &dl = iter->second;
if (dl.uncachable)
{
return false;
}
switch (dl.pass)
{
case DLCache::DLPASS_COMPILE:
// First, check that the hash is the same as the last time.
if (dl.dl_hash != GetHash64(Memory::GetPointer(address), size, 0))
{
dl.uncachable = true;
return false;
}
DLCache::CompileAndRunDisplayList(address, size, &dl);
dl.pass = DLCache::DLPASS_RUN;
break;
case DLCache::DLPASS_RUN:
{
bool DlistChanged = false;
if (dl.check != CheckContextId)
{
dl.check = CheckContextId;
DlistChanged = !dl.CheckRegions() || dl.dl_hash != GetHash64(Memory::GetPointer(address), size, 0);
}
if (DlistChanged)
{
dl.uncachable = true;
dl.ClearRegions();
return false;
}
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;
u32 dlvatused = DLCache::AnalyzeAndRunDisplayList(address, size, &dl);
dl.dl_hash = GetHash64(Memory::GetPointer(address), size,0);
dl.pass = DLCache::DLPASS_COMPILE;
dl.check = CheckContextId;
vhash = DLCache::CreateVMapId(dlvatused);
if(Parentiter != DLCache::dl_map.end())
{
DLCache::VDlist &vdl = Parentiter->second;
vdl.dl_map[vhash] = dl;
vdl.VATUsed = dlvatused;
vdl.count++;
}
else
{
DLCache::VDlist vdl;
vdl.dl_map[vhash] = dl;
vdl.VATUsed = dlvatused;
vdl.count = 1;
DLCache::dl_map[dl_id] = vdl;
}
return true;
}
void IncrementCheckContextId()
{
CheckContextId++;
}

View File

@ -112,15 +112,6 @@ void InterpretDisplayList(u32 address, u32 size)
g_pVideoData = old_pVideoData;
}
// Defer to backend-specific DL cache.
extern bool HandleDisplayList(u32 address, u32 size);
void ExecuteDisplayList(u32 address, u32 size)
{
if (!HandleDisplayList(address, size))
InterpretDisplayList(address, size);
}
u32 FifoCommandRunnable(u32 &command_size)
{
u32 cycleTime = 0;
@ -337,7 +328,7 @@ static void Decode()
{
u32 address = DataReadU32();
u32 count = DataReadU32();
ExecuteDisplayList(address, count);
InterpretDisplayList(address, count);
}
break;

View File

@ -38,5 +38,5 @@ extern bool g_bRecordFifoData;
void OpcodeDecoder_Init();
void OpcodeDecoder_Shutdown();
u32 OpcodeDecoder_Run(bool skipped_frame);
void ExecuteDisplayList(u32 address, u32 size);
void InterpretDisplayList(u32 address, u32 size);
#endif // _OPCODE_DECODING_H

View File

@ -17,7 +17,6 @@
#include "RenderBase.h"
#include "CommandProcessor.h"
#include "HW/ProcessorInterface.h"
#include "DLCache.h"
#include "State.h"
namespace PixelEngine
@ -380,7 +379,6 @@ void SetToken_OnMainThread(u64 userdata, int cyclesLate)
UpdateInterrupts();
}
CommandProcessor::interruptTokenWaiting = false;
IncrementCheckContextId();
}
void SetFinish_OnMainThread(u64 userdata, int cyclesLate)
@ -402,7 +400,6 @@ void SetToken(const u16 _token, const int _bSetTokenAcknowledge)
CommandProcessor::interruptTokenWaiting = true;
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
IncrementCheckContextId();
}
// SetFinish
@ -412,7 +409,6 @@ void SetFinish()
CommandProcessor::interruptFinishWaiting = true;
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetFinishOnMainThread, 0);
INFO_LOG(PIXELENGINE, "VIDEO Set Finish");
IncrementCheckContextId();
}
//This function is used in CommandProcessor when write CTRL_REGISTER and the new fifo is attached.

View File

@ -59,7 +59,6 @@ int Renderer::s_LastEFBScale;
bool Renderer::s_skipSwap;
bool Renderer::XFBWrited;
bool Renderer::s_EnableDLCachingAfterRecording;
unsigned int Renderer::prev_efb_format = (unsigned int)-1;
unsigned int Renderer::efb_scale_numeratorX = 1;
@ -490,19 +489,11 @@ void Renderer::CheckFifoRecording()
{
if (!wasRecording)
{
// Disable display list caching because the recorder does not handle it
s_EnableDLCachingAfterRecording = g_ActiveConfig.bDlistCachingEnable;
g_ActiveConfig.bDlistCachingEnable = false;
RecordVideoMemory();
}
FifoRecorder::GetInstance().EndFrame(CommandProcessor::fifo.CPBase, CommandProcessor::fifo.CPEnd);
}
else if (wasRecording)
{
g_ActiveConfig.bDlistCachingEnable = s_EnableDLCachingAfterRecording;
}
}
void Renderer::RecordVideoMemory()

View File

@ -151,8 +151,6 @@ protected:
static bool s_skipSwap;
static bool XFBWrited;
static bool s_EnableDLCachingAfterRecording;
private:
static unsigned int prev_efb_format;
static unsigned int efb_scale_numeratorX;

View File

@ -915,17 +915,6 @@ void VertexLoader::ConvertVertices ( int count )
#endif
}
void VertexLoader::RunCompiledVertices(int vtx_attr_group, int primitive, int const count, u8* Data)
{
auto const new_count = SetupRunVertices(vtx_attr_group, primitive, count);
memcpy_gc(VertexManager::s_pCurBufferPointer, Data, native_stride * new_count);
VertexManager::s_pCurBufferPointer += native_stride * new_count;
DataSkip(new_count * m_VertexSize);
VertexManager::AddVertices(primitive, new_count);
}
void VertexLoader::SetVAT(u32 _group0, u32 _group1, u32 _group2)
{
VAT vat;

View File

@ -97,7 +97,6 @@ public:
int SetupRunVertices(int vtx_attr_group, int primitive, int const count);
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;

View File

@ -127,14 +127,6 @@ 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);

View File

@ -17,7 +17,6 @@ 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);

View File

@ -85,7 +85,6 @@
<ClCompile Include="VideoBackendBase.cpp" />
<ClCompile Include="VideoConfig.cpp" />
<ClCompile Include="VideoState.cpp" />
<ClCompile Include="DLCache_x64.cpp" />
<ClCompile Include="TextureDecoder_x64.cpp" />
<ClCompile Include="XFMemory.cpp" />
<ClCompile Include="XFStructs.cpp" />
@ -99,7 +98,6 @@
<ClInclude Include="CPMemory.h" />
<ClInclude Include="DataReader.h" />
<ClInclude Include="Debugger.h" />
<ClInclude Include="DLCache.h" />
<ClInclude Include="DriverDetails.h" />
<ClInclude Include="EmuWindow.h" />
<ClInclude Include="Fifo.h" />

View File

@ -120,9 +120,6 @@
<ClCompile Include="VideoState.cpp">
<Filter>Util</Filter>
</ClCompile>
<ClCompile Include="DLCache_x64.cpp">
<Filter>Vertex Loading</Filter>
</ClCompile>
<ClCompile Include="VertexLoader.cpp">
<Filter>Vertex Loading</Filter>
</ClCompile>
@ -253,9 +250,6 @@
<ClInclude Include="DataReader.h">
<Filter>Vertex Loading</Filter>
</ClInclude>
<ClInclude Include="DLCache.h">
<Filter>Vertex Loading</Filter>
</ClInclude>
<ClInclude Include="VertexLoader.h">
<Filter>Vertex Loading</Filter>
</ClInclude>

View File

@ -90,7 +90,6 @@ void VideoConfig::Load(const char *ini_file)
iniFile.Get("Enhancements", "Enable3dVision", &b3DVision, false);
iniFile.Get("Hacks", "EFBAccessEnable", &bEFBAccessEnable, true);
iniFile.Get("Hacks", "DlistCachingEnable", &bDlistCachingEnable,false);
iniFile.Get("Hacks", "EFBCopyEnable", &bEFBCopyEnable, true);
iniFile.Get("Hacks", "EFBToTextureEnable", &bCopyEFBToTexture, true);
iniFile.Get("Hacks", "EFBScaledCopy", &bCopyEFBScaled, true);
@ -189,7 +188,6 @@ void VideoConfig::GameIniLoad()
CHECK_SETTING("Video_Enhancements", "Enable3dVision", b3DVision);
CHECK_SETTING("Video_Hacks", "EFBAccessEnable", bEFBAccessEnable);
CHECK_SETTING("Video_Hacks", "DlistCachingEnable", bDlistCachingEnable);
CHECK_SETTING("Video_Hacks", "EFBCopyEnable", bEFBCopyEnable);
CHECK_SETTING("Video_Hacks", "EFBToTextureEnable", bCopyEFBToTexture);
CHECK_SETTING("Video_Hacks", "EFBScaledCopy", bCopyEFBScaled);
@ -269,7 +267,6 @@ void VideoConfig::Save(const char *ini_file)
iniFile.Set("Enhancements", "Enable3dVision", b3DVision);
iniFile.Set("Hacks", "EFBAccessEnable", bEFBAccessEnable);
iniFile.Set("Hacks", "DlistCachingEnable", bDlistCachingEnable);
iniFile.Set("Hacks", "EFBCopyEnable", bEFBCopyEnable);
iniFile.Set("Hacks", "EFBToTextureEnable", bCopyEFBToTexture);
iniFile.Set("Hacks", "EFBScaledCopy", bCopyEFBScaled);

View File

@ -105,7 +105,6 @@ struct VideoConfig
// Hacks
bool bEFBAccessEnable;
bool bDlistCachingEnable;
bool bPerfQueriesEnable;
bool bEFBCopyEnable;