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:
parent
72cc6431e5
commit
010a0d481a
|
@ -91,7 +91,6 @@ public final class UserPreferences
|
||||||
editor.putString("externalFrameBuffer", "Real");
|
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("disableDestinationAlpha", getConfig("gfx_opengl.ini", "Settings", "DstAlphaPass", "False").equals("True"));
|
||||||
editor.putBoolean("fastDepthCalculation", getConfig("gfx_opengl.ini", "Settings", "FastDepthCalc", "True").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", "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", "DstAlphaPass", disableDstAlphaPass ? "True" : "False");
|
||||||
NativeLibrary.SetConfig("gfx_opengl.ini", "Settings", "FastDepthCalc", useFastDepthCalc ? "True" : "False");
|
NativeLibrary.SetConfig("gfx_opengl.ini", "Settings", "FastDepthCalc", useFastDepthCalc ? "True" : "False");
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,6 @@ wxString use_ffv1_desc = wxTRANSLATE("Encode frame dumps using the FFV1 codec.\n
|
||||||
#endif
|
#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 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 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 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 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.");
|
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
|
// - other hacks
|
||||||
{
|
{
|
||||||
wxGridSizer* const szr_other = new wxGridSizer(2, 5, 5);
|
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, _("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, _("OpenMP Texture Decoder"), wxGetTranslation(omp_desc), vconfig.bOMPDecoder));
|
||||||
szr_other->Add(CreateCheckBox(page_hacks, _("Fast Depth Calculation"), wxGetTranslation(fast_depth_calc_desc), vconfig.bFastDepthCalc));
|
szr_other->Add(CreateCheckBox(page_hacks, _("Fast Depth Calculation"), wxGetTranslation(fast_depth_calc_desc), vconfig.bFastDepthCalc));
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
#include "Timer.h"
|
#include "Timer.h"
|
||||||
|
|
||||||
#include "Debugger.h"
|
#include "Debugger.h"
|
||||||
#include "DLCache.h"
|
|
||||||
#include "EmuWindow.h"
|
#include "EmuWindow.h"
|
||||||
#include "Fifo.h"
|
#include "Fifo.h"
|
||||||
#include "OnScreenDisplay.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);
|
GFX_DEBUGGER_PAUSE_AT(NEXT_FRAME, true);
|
||||||
|
|
||||||
DLCache::ProgressiveCleanup();
|
|
||||||
TextureCache::Cleanup();
|
TextureCache::Cleanup();
|
||||||
|
|
||||||
// Enable configuration changes
|
// Enable configuration changes
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
#include "Host.h"
|
#include "Host.h"
|
||||||
|
|
||||||
#include "Debugger/DebuggerPanel.h"
|
#include "Debugger/DebuggerPanel.h"
|
||||||
#include "DLCache.h"
|
|
||||||
#include "EmuWindow.h"
|
#include "EmuWindow.h"
|
||||||
#include "IndexGenerator.h"
|
#include "IndexGenerator.h"
|
||||||
#include "FileUtil.h"
|
#include "FileUtil.h"
|
||||||
|
@ -201,7 +200,6 @@ void VideoBackend::Video_Prepare()
|
||||||
PixelShaderManager::Init();
|
PixelShaderManager::Init();
|
||||||
CommandProcessor::Init();
|
CommandProcessor::Init();
|
||||||
PixelEngine::Init();
|
PixelEngine::Init();
|
||||||
DLCache::Init();
|
|
||||||
|
|
||||||
// Tell the host that the window is ready
|
// Tell the host that the window is ready
|
||||||
Host_Message(WM_USER_CREATE);
|
Host_Message(WM_USER_CREATE);
|
||||||
|
@ -219,7 +217,6 @@ void VideoBackend::Shutdown()
|
||||||
s_swapRequested = FALSE;
|
s_swapRequested = FALSE;
|
||||||
|
|
||||||
// VideoCommon
|
// VideoCommon
|
||||||
DLCache::Shutdown();
|
|
||||||
Fifo_Shutdown();
|
Fifo_Shutdown();
|
||||||
CommandProcessor::Shutdown();
|
CommandProcessor::Shutdown();
|
||||||
PixelShaderManager::Shutdown();
|
PixelShaderManager::Shutdown();
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
#include "TextureCache.h"
|
#include "TextureCache.h"
|
||||||
#include "RasterFont.h"
|
#include "RasterFont.h"
|
||||||
#include "VertexShaderGen.h"
|
#include "VertexShaderGen.h"
|
||||||
#include "DLCache.h"
|
|
||||||
#include "ProgramShaderCache.h"
|
#include "ProgramShaderCache.h"
|
||||||
#include "VertexShaderManager.h"
|
#include "VertexShaderManager.h"
|
||||||
#include "VertexLoaderManager.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.
|
// Clean out old stuff from caches. It's not worth it to clean out the shader caches.
|
||||||
DLCache::ProgressiveCleanup();
|
|
||||||
TextureCache::Cleanup();
|
TextureCache::Cleanup();
|
||||||
|
|
||||||
frameCount++;
|
frameCount++;
|
||||||
|
|
|
@ -76,7 +76,6 @@ Make AA apply instantly during gameplay if possible
|
||||||
#include "TextureConverter.h"
|
#include "TextureConverter.h"
|
||||||
#include "PostProcessing.h"
|
#include "PostProcessing.h"
|
||||||
#include "OnScreenDisplay.h"
|
#include "OnScreenDisplay.h"
|
||||||
#include "DLCache.h"
|
|
||||||
#include "FramebufferManager.h"
|
#include "FramebufferManager.h"
|
||||||
#include "Core.h"
|
#include "Core.h"
|
||||||
#include "Host.h"
|
#include "Host.h"
|
||||||
|
@ -225,9 +224,6 @@ void VideoBackend::Video_Prepare()
|
||||||
GL_REPORT_ERRORD();
|
GL_REPORT_ERRORD();
|
||||||
VertexLoaderManager::Init();
|
VertexLoaderManager::Init();
|
||||||
TextureConverter::Init();
|
TextureConverter::Init();
|
||||||
#ifndef _M_GENERIC
|
|
||||||
DLCache::Init();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Notify the core that the video backend is ready
|
// Notify the core that the video backend is ready
|
||||||
Host_Message(WM_USER_CREATE);
|
Host_Message(WM_USER_CREATE);
|
||||||
|
@ -250,9 +246,6 @@ void VideoBackend::Video_Cleanup() {
|
||||||
s_efbAccessRequested = false;
|
s_efbAccessRequested = false;
|
||||||
s_FifoShuttingDown = false;
|
s_FifoShuttingDown = false;
|
||||||
s_swapRequested = false;
|
s_swapRequested = false;
|
||||||
#ifndef _M_GENERIC
|
|
||||||
DLCache::Shutdown();
|
|
||||||
#endif
|
|
||||||
Fifo_Shutdown();
|
Fifo_Shutdown();
|
||||||
|
|
||||||
// The following calls are NOT Thread Safe
|
// The following calls are NOT Thread Safe
|
||||||
|
|
|
@ -40,11 +40,9 @@ set(SRCS BPFunctions.cpp
|
||||||
set(LIBS core png)
|
set(LIBS core png)
|
||||||
|
|
||||||
if(NOT _M_GENERIC)
|
if(NOT _M_GENERIC)
|
||||||
set(SRCS ${SRCS} TextureDecoder_x64.cpp
|
set(SRCS ${SRCS} TextureDecoder_x64.cpp)
|
||||||
DLCache_x64.cpp)
|
|
||||||
else()
|
else()
|
||||||
set(SRCS ${SRCS} TextureDecoder_Generic.cpp
|
set(SRCS ${SRCS} TextureDecoder_Generic.cpp)
|
||||||
DLCache_Generic.cpp)
|
|
||||||
endif()
|
endif()
|
||||||
if(NOT ${CL} STREQUAL CL-NOTFOUND)
|
if(NOT ${CL} STREQUAL CL-NOTFOUND)
|
||||||
list(APPEND LIBS ${CL})
|
list(APPEND LIBS ${CL})
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
#include "HW/ProcessorInterface.h"
|
#include "HW/ProcessorInterface.h"
|
||||||
#include "HW/GPFifo.h"
|
#include "HW/GPFifo.h"
|
||||||
#include "HW/Memmap.h"
|
#include "HW/Memmap.h"
|
||||||
#include "DLCache.h"
|
|
||||||
#include "HW/SystemTimers.h"
|
#include "HW/SystemTimers.h"
|
||||||
#include "Core.h"
|
#include "Core.h"
|
||||||
|
|
||||||
|
@ -409,7 +408,6 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
{
|
{
|
||||||
ResetVideoBuffer();
|
ResetVideoBuffer();
|
||||||
}
|
}
|
||||||
IncrementCheckContextId();
|
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"Try to write to FIFO_RW_DISTANCE_HI : %04x", _Value);
|
DEBUG_LOG(COMMANDPROCESSOR,"Try to write to FIFO_RW_DISTANCE_HI : %04x", _Value);
|
||||||
break;
|
break;
|
||||||
case FIFO_RW_DISTANCE_LO:
|
case FIFO_RW_DISTANCE_LO:
|
||||||
|
@ -527,7 +525,6 @@ void SetCpStatus(bool isCPUThread)
|
||||||
{
|
{
|
||||||
INFO_LOG(COMMANDPROCESSOR, "Hit breakpoint at %i", fifo.CPReadPointer);
|
INFO_LOG(COMMANDPROCESSOR, "Hit breakpoint at %i", fifo.CPReadPointer);
|
||||||
fifo.bFF_Breakpoint = true;
|
fifo.bFF_Breakpoint = true;
|
||||||
IncrementCheckContextId();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -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
|
|
|
@ -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()
|
|
||||||
{
|
|
||||||
}
|
|
|
@ -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++;
|
|
||||||
}
|
|
|
@ -112,15 +112,6 @@ void InterpretDisplayList(u32 address, u32 size)
|
||||||
g_pVideoData = old_pVideoData;
|
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 FifoCommandRunnable(u32 &command_size)
|
||||||
{
|
{
|
||||||
u32 cycleTime = 0;
|
u32 cycleTime = 0;
|
||||||
|
@ -337,7 +328,7 @@ static void Decode()
|
||||||
{
|
{
|
||||||
u32 address = DataReadU32();
|
u32 address = DataReadU32();
|
||||||
u32 count = DataReadU32();
|
u32 count = DataReadU32();
|
||||||
ExecuteDisplayList(address, count);
|
InterpretDisplayList(address, count);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -38,5 +38,5 @@ extern bool g_bRecordFifoData;
|
||||||
void OpcodeDecoder_Init();
|
void OpcodeDecoder_Init();
|
||||||
void OpcodeDecoder_Shutdown();
|
void OpcodeDecoder_Shutdown();
|
||||||
u32 OpcodeDecoder_Run(bool skipped_frame);
|
u32 OpcodeDecoder_Run(bool skipped_frame);
|
||||||
void ExecuteDisplayList(u32 address, u32 size);
|
void InterpretDisplayList(u32 address, u32 size);
|
||||||
#endif // _OPCODE_DECODING_H
|
#endif // _OPCODE_DECODING_H
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
#include "RenderBase.h"
|
#include "RenderBase.h"
|
||||||
#include "CommandProcessor.h"
|
#include "CommandProcessor.h"
|
||||||
#include "HW/ProcessorInterface.h"
|
#include "HW/ProcessorInterface.h"
|
||||||
#include "DLCache.h"
|
|
||||||
#include "State.h"
|
#include "State.h"
|
||||||
|
|
||||||
namespace PixelEngine
|
namespace PixelEngine
|
||||||
|
@ -380,7 +379,6 @@ void SetToken_OnMainThread(u64 userdata, int cyclesLate)
|
||||||
UpdateInterrupts();
|
UpdateInterrupts();
|
||||||
}
|
}
|
||||||
CommandProcessor::interruptTokenWaiting = false;
|
CommandProcessor::interruptTokenWaiting = false;
|
||||||
IncrementCheckContextId();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetFinish_OnMainThread(u64 userdata, int cyclesLate)
|
void SetFinish_OnMainThread(u64 userdata, int cyclesLate)
|
||||||
|
@ -402,7 +400,6 @@ void SetToken(const u16 _token, const int _bSetTokenAcknowledge)
|
||||||
|
|
||||||
CommandProcessor::interruptTokenWaiting = true;
|
CommandProcessor::interruptTokenWaiting = true;
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
|
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
|
||||||
IncrementCheckContextId();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetFinish
|
// SetFinish
|
||||||
|
@ -412,7 +409,6 @@ void SetFinish()
|
||||||
CommandProcessor::interruptFinishWaiting = true;
|
CommandProcessor::interruptFinishWaiting = true;
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetFinishOnMainThread, 0);
|
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetFinishOnMainThread, 0);
|
||||||
INFO_LOG(PIXELENGINE, "VIDEO Set Finish");
|
INFO_LOG(PIXELENGINE, "VIDEO Set Finish");
|
||||||
IncrementCheckContextId();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//This function is used in CommandProcessor when write CTRL_REGISTER and the new fifo is attached.
|
//This function is used in CommandProcessor when write CTRL_REGISTER and the new fifo is attached.
|
||||||
|
|
|
@ -59,7 +59,6 @@ int Renderer::s_LastEFBScale;
|
||||||
|
|
||||||
bool Renderer::s_skipSwap;
|
bool Renderer::s_skipSwap;
|
||||||
bool Renderer::XFBWrited;
|
bool Renderer::XFBWrited;
|
||||||
bool Renderer::s_EnableDLCachingAfterRecording;
|
|
||||||
|
|
||||||
unsigned int Renderer::prev_efb_format = (unsigned int)-1;
|
unsigned int Renderer::prev_efb_format = (unsigned int)-1;
|
||||||
unsigned int Renderer::efb_scale_numeratorX = 1;
|
unsigned int Renderer::efb_scale_numeratorX = 1;
|
||||||
|
@ -490,19 +489,11 @@ void Renderer::CheckFifoRecording()
|
||||||
{
|
{
|
||||||
if (!wasRecording)
|
if (!wasRecording)
|
||||||
{
|
{
|
||||||
// Disable display list caching because the recorder does not handle it
|
|
||||||
s_EnableDLCachingAfterRecording = g_ActiveConfig.bDlistCachingEnable;
|
|
||||||
g_ActiveConfig.bDlistCachingEnable = false;
|
|
||||||
|
|
||||||
RecordVideoMemory();
|
RecordVideoMemory();
|
||||||
}
|
}
|
||||||
|
|
||||||
FifoRecorder::GetInstance().EndFrame(CommandProcessor::fifo.CPBase, CommandProcessor::fifo.CPEnd);
|
FifoRecorder::GetInstance().EndFrame(CommandProcessor::fifo.CPBase, CommandProcessor::fifo.CPEnd);
|
||||||
}
|
}
|
||||||
else if (wasRecording)
|
|
||||||
{
|
|
||||||
g_ActiveConfig.bDlistCachingEnable = s_EnableDLCachingAfterRecording;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::RecordVideoMemory()
|
void Renderer::RecordVideoMemory()
|
||||||
|
|
|
@ -151,8 +151,6 @@ protected:
|
||||||
static bool s_skipSwap;
|
static bool s_skipSwap;
|
||||||
static bool XFBWrited;
|
static bool XFBWrited;
|
||||||
|
|
||||||
static bool s_EnableDLCachingAfterRecording;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static unsigned int prev_efb_format;
|
static unsigned int prev_efb_format;
|
||||||
static unsigned int efb_scale_numeratorX;
|
static unsigned int efb_scale_numeratorX;
|
||||||
|
|
|
@ -915,17 +915,6 @@ void VertexLoader::ConvertVertices ( int count )
|
||||||
#endif
|
#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)
|
void VertexLoader::SetVAT(u32 _group0, u32 _group1, u32 _group2)
|
||||||
{
|
{
|
||||||
VAT vat;
|
VAT vat;
|
||||||
|
|
|
@ -97,7 +97,6 @@ public:
|
||||||
|
|
||||||
int SetupRunVertices(int vtx_attr_group, int primitive, int const count);
|
int SetupRunVertices(int vtx_attr_group, int primitive, int const count);
|
||||||
void RunVertices(int vtx_attr_group, int primitive, int 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
|
// For debugging / profiling
|
||||||
void AppendToString(std::string *dest) const;
|
void AppendToString(std::string *dest) const;
|
||||||
|
|
|
@ -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);
|
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)
|
int GetVertexSize(int vtx_attr_group)
|
||||||
{
|
{
|
||||||
RefreshLoader(vtx_attr_group);
|
RefreshLoader(vtx_attr_group);
|
||||||
|
|
|
@ -17,7 +17,6 @@ namespace VertexLoaderManager
|
||||||
|
|
||||||
int GetVertexSize(int vtx_attr_group);
|
int GetVertexSize(int vtx_attr_group);
|
||||||
void RunVertices(int vtx_attr_group, int primitive, int 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
|
// For debugging
|
||||||
void AppendListToString(std::string *dest);
|
void AppendListToString(std::string *dest);
|
||||||
|
|
|
@ -85,7 +85,6 @@
|
||||||
<ClCompile Include="VideoBackendBase.cpp" />
|
<ClCompile Include="VideoBackendBase.cpp" />
|
||||||
<ClCompile Include="VideoConfig.cpp" />
|
<ClCompile Include="VideoConfig.cpp" />
|
||||||
<ClCompile Include="VideoState.cpp" />
|
<ClCompile Include="VideoState.cpp" />
|
||||||
<ClCompile Include="DLCache_x64.cpp" />
|
|
||||||
<ClCompile Include="TextureDecoder_x64.cpp" />
|
<ClCompile Include="TextureDecoder_x64.cpp" />
|
||||||
<ClCompile Include="XFMemory.cpp" />
|
<ClCompile Include="XFMemory.cpp" />
|
||||||
<ClCompile Include="XFStructs.cpp" />
|
<ClCompile Include="XFStructs.cpp" />
|
||||||
|
@ -99,7 +98,6 @@
|
||||||
<ClInclude Include="CPMemory.h" />
|
<ClInclude Include="CPMemory.h" />
|
||||||
<ClInclude Include="DataReader.h" />
|
<ClInclude Include="DataReader.h" />
|
||||||
<ClInclude Include="Debugger.h" />
|
<ClInclude Include="Debugger.h" />
|
||||||
<ClInclude Include="DLCache.h" />
|
|
||||||
<ClInclude Include="DriverDetails.h" />
|
<ClInclude Include="DriverDetails.h" />
|
||||||
<ClInclude Include="EmuWindow.h" />
|
<ClInclude Include="EmuWindow.h" />
|
||||||
<ClInclude Include="Fifo.h" />
|
<ClInclude Include="Fifo.h" />
|
||||||
|
|
|
@ -120,9 +120,6 @@
|
||||||
<ClCompile Include="VideoState.cpp">
|
<ClCompile Include="VideoState.cpp">
|
||||||
<Filter>Util</Filter>
|
<Filter>Util</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="DLCache_x64.cpp">
|
|
||||||
<Filter>Vertex Loading</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="VertexLoader.cpp">
|
<ClCompile Include="VertexLoader.cpp">
|
||||||
<Filter>Vertex Loading</Filter>
|
<Filter>Vertex Loading</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -253,9 +250,6 @@
|
||||||
<ClInclude Include="DataReader.h">
|
<ClInclude Include="DataReader.h">
|
||||||
<Filter>Vertex Loading</Filter>
|
<Filter>Vertex Loading</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="DLCache.h">
|
|
||||||
<Filter>Vertex Loading</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="VertexLoader.h">
|
<ClInclude Include="VertexLoader.h">
|
||||||
<Filter>Vertex Loading</Filter>
|
<Filter>Vertex Loading</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
|
@ -90,7 +90,6 @@ void VideoConfig::Load(const char *ini_file)
|
||||||
iniFile.Get("Enhancements", "Enable3dVision", &b3DVision, false);
|
iniFile.Get("Enhancements", "Enable3dVision", &b3DVision, false);
|
||||||
|
|
||||||
iniFile.Get("Hacks", "EFBAccessEnable", &bEFBAccessEnable, true);
|
iniFile.Get("Hacks", "EFBAccessEnable", &bEFBAccessEnable, true);
|
||||||
iniFile.Get("Hacks", "DlistCachingEnable", &bDlistCachingEnable,false);
|
|
||||||
iniFile.Get("Hacks", "EFBCopyEnable", &bEFBCopyEnable, true);
|
iniFile.Get("Hacks", "EFBCopyEnable", &bEFBCopyEnable, true);
|
||||||
iniFile.Get("Hacks", "EFBToTextureEnable", &bCopyEFBToTexture, true);
|
iniFile.Get("Hacks", "EFBToTextureEnable", &bCopyEFBToTexture, true);
|
||||||
iniFile.Get("Hacks", "EFBScaledCopy", &bCopyEFBScaled, true);
|
iniFile.Get("Hacks", "EFBScaledCopy", &bCopyEFBScaled, true);
|
||||||
|
@ -189,7 +188,6 @@ void VideoConfig::GameIniLoad()
|
||||||
CHECK_SETTING("Video_Enhancements", "Enable3dVision", b3DVision);
|
CHECK_SETTING("Video_Enhancements", "Enable3dVision", b3DVision);
|
||||||
|
|
||||||
CHECK_SETTING("Video_Hacks", "EFBAccessEnable", bEFBAccessEnable);
|
CHECK_SETTING("Video_Hacks", "EFBAccessEnable", bEFBAccessEnable);
|
||||||
CHECK_SETTING("Video_Hacks", "DlistCachingEnable", bDlistCachingEnable);
|
|
||||||
CHECK_SETTING("Video_Hacks", "EFBCopyEnable", bEFBCopyEnable);
|
CHECK_SETTING("Video_Hacks", "EFBCopyEnable", bEFBCopyEnable);
|
||||||
CHECK_SETTING("Video_Hacks", "EFBToTextureEnable", bCopyEFBToTexture);
|
CHECK_SETTING("Video_Hacks", "EFBToTextureEnable", bCopyEFBToTexture);
|
||||||
CHECK_SETTING("Video_Hacks", "EFBScaledCopy", bCopyEFBScaled);
|
CHECK_SETTING("Video_Hacks", "EFBScaledCopy", bCopyEFBScaled);
|
||||||
|
@ -269,7 +267,6 @@ void VideoConfig::Save(const char *ini_file)
|
||||||
iniFile.Set("Enhancements", "Enable3dVision", b3DVision);
|
iniFile.Set("Enhancements", "Enable3dVision", b3DVision);
|
||||||
|
|
||||||
iniFile.Set("Hacks", "EFBAccessEnable", bEFBAccessEnable);
|
iniFile.Set("Hacks", "EFBAccessEnable", bEFBAccessEnable);
|
||||||
iniFile.Set("Hacks", "DlistCachingEnable", bDlistCachingEnable);
|
|
||||||
iniFile.Set("Hacks", "EFBCopyEnable", bEFBCopyEnable);
|
iniFile.Set("Hacks", "EFBCopyEnable", bEFBCopyEnable);
|
||||||
iniFile.Set("Hacks", "EFBToTextureEnable", bCopyEFBToTexture);
|
iniFile.Set("Hacks", "EFBToTextureEnable", bCopyEFBToTexture);
|
||||||
iniFile.Set("Hacks", "EFBScaledCopy", bCopyEFBScaled);
|
iniFile.Set("Hacks", "EFBScaledCopy", bCopyEFBScaled);
|
||||||
|
|
|
@ -105,7 +105,6 @@ struct VideoConfig
|
||||||
|
|
||||||
// Hacks
|
// Hacks
|
||||||
bool bEFBAccessEnable;
|
bool bEFBAccessEnable;
|
||||||
bool bDlistCachingEnable;
|
|
||||||
bool bPerfQueriesEnable;
|
bool bPerfQueriesEnable;
|
||||||
|
|
||||||
bool bEFBCopyEnable;
|
bool bEFBCopyEnable;
|
||||||
|
|
Loading…
Reference in New Issue