ok, here goes a really experimental commit:

replace efb to ram implementation by a hybrid approach.
explanation:
when copying from efb to texture, instead of make a copy to a texture or to the ram, copy the data to both, in hi quality to the texture and in native quality to the ram.
then instead of re-decoding the data from ram (very slow) use the data in the texture.
to improve this even more, test if the cpu has modified the data in the ram copy, if so, update the texture in memory and mark it as dynamic to avoid redundant work in future frames.
having all this implemented this is what is archived:
sms: full quality with scaled efb copies and fully functional goop cleaning :)
ztp: efb to texture speed with full map support.
nsmbw: this is a hard to emulate game, as it make a lot of shading and texture modification in cpu. it only have 35 fps in my system with new efb to ram but is 10 fps faster than normal efb to ram.
this game also show me another unimplemented feature, copy efb to multiple textures at the same time (is used to animate coins and other things in the world).
this is a remaining todo in efb to texture.
a lot of games should improve, so please test and let me know any regresion caused by this commit. 
if everyone likes this the next step is, implement efb to multilpe textures and merge efb to ram and efb to texture.
then port to the other plugins.
enjoy.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5846 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Rodolfo Osvaldo Bogado 2010-07-06 22:27:13 +00:00
parent 464bac82ff
commit 539f63b58b
9 changed files with 383 additions and 200 deletions

View File

@ -93,6 +93,7 @@ void VideoConfig::Load(const char *ini_file)
iniFile.Get("Hacks", "EFBCopyDisable", &bEFBCopyDisable, false); iniFile.Get("Hacks", "EFBCopyDisable", &bEFBCopyDisable, false);
iniFile.Get("Hacks", "EFBCopyDisableHotKey", &bOSDHotKey, 0); iniFile.Get("Hacks", "EFBCopyDisableHotKey", &bOSDHotKey, 0);
iniFile.Get("Hacks", "EFBToTextureEnable", &bCopyEFBToTexture, false); iniFile.Get("Hacks", "EFBToTextureEnable", &bCopyEFBToTexture, false);
iniFile.Get("Hacks", "EFBVerifyTextureModificationsByCPU",&bVerifyTextureModificationsByCPU,false);
iniFile.Get("Hacks", "EFBScaledCopy", &bCopyEFBScaled, true); iniFile.Get("Hacks", "EFBScaledCopy", &bCopyEFBScaled, true);
iniFile.Get("Hacks", "FIFOBPHack", &bFIFOBPhack, false); iniFile.Get("Hacks", "FIFOBPHack", &bFIFOBPhack, false);
iniFile.Get("Hacks", "ProjectionHack", &iPhackvalue, 0); iniFile.Get("Hacks", "ProjectionHack", &iPhackvalue, 0);
@ -125,6 +126,8 @@ void VideoConfig::GameIniLoad(const char *ini_file)
iniFile.Get("Video", "EFBCopyDisableHotKey", &bOSDHotKey); iniFile.Get("Video", "EFBCopyDisableHotKey", &bOSDHotKey);
if (iniFile.Exists("Video", "EFBToTextureEnable")) if (iniFile.Exists("Video", "EFBToTextureEnable"))
iniFile.Get("Video", "EFBToTextureEnable", &bCopyEFBToTexture); iniFile.Get("Video", "EFBToTextureEnable", &bCopyEFBToTexture);
if (iniFile.Exists("Video", "EFBVerifyTextureModificationsByCPU"))
iniFile.Get("Video", "EFBVerifyTextureModificationsByCPU", &bVerifyTextureModificationsByCPU);
if (iniFile.Exists("Video", "EFBScaledCopy")) if (iniFile.Exists("Video", "EFBScaledCopy"))
iniFile.Get("Video", "EFBScaledCopy", &bCopyEFBScaled); iniFile.Get("Video", "EFBScaledCopy", &bCopyEFBScaled);
if (iniFile.Exists("Video", "SafeTextureCache")) if (iniFile.Exists("Video", "SafeTextureCache"))
@ -200,6 +203,7 @@ void VideoConfig::Save(const char *ini_file)
iniFile.Set("Hacks", "EFBCopyDisable", bEFBCopyDisable); iniFile.Set("Hacks", "EFBCopyDisable", bEFBCopyDisable);
iniFile.Set("Hacks", "EFBCopyDisableHotKey", bOSDHotKey); iniFile.Set("Hacks", "EFBCopyDisableHotKey", bOSDHotKey);
iniFile.Set("Hacks", "EFBToTextureEnable", bCopyEFBToTexture); iniFile.Set("Hacks", "EFBToTextureEnable", bCopyEFBToTexture);
iniFile.Set("Hacks", "EFBVerifyTextureModificationsByCPU", bVerifyTextureModificationsByCPU);
iniFile.Set("Hacks", "EFBScaledCopy", bCopyEFBScaled); iniFile.Set("Hacks", "EFBScaledCopy", bCopyEFBScaled);
iniFile.Set("Hacks", "FIFOBPHack", bFIFOBPhack); iniFile.Set("Hacks", "FIFOBPHack", bFIFOBPhack);
iniFile.Set("Hacks", "ProjectionHack", iPhackvalue); iniFile.Set("Hacks", "ProjectionHack", iPhackvalue);

View File

@ -116,6 +116,7 @@ struct VideoConfig
bool bOSDHotKey; bool bOSDHotKey;
bool bHack; bool bHack;
bool bCopyEFBToTexture; bool bCopyEFBToTexture;
bool bVerifyTextureModificationsByCPU;
bool bCopyEFBScaled; bool bCopyEFBScaled;
bool bSafeTextureCache; bool bSafeTextureCache;
int iSafeTextureCache_ColorSamples; int iSafeTextureCache_ColorSamples;

View File

@ -82,18 +82,8 @@ void CopyEFB(const BPCmd &bp, const EFBRectangle &rc, const u32 &address, const
{ {
if (!g_ActiveConfig.bEFBCopyDisable) if (!g_ActiveConfig.bEFBCopyDisable)
{ {
//uncomment this to see the efb to ram work in progress
if (g_ActiveConfig.bCopyEFBToTexture)
{
// To D3D Texture
TextureCache::CopyRenderTargetToTexture(address, fromZBuffer, isIntensityFmt, copyfmt, scaleByHalf, rc); TextureCache::CopyRenderTargetToTexture(address, fromZBuffer, isIntensityFmt, copyfmt, scaleByHalf, rc);
} }
else
{
//ToRam
TextureConverter::EncodeToRam(address, fromZBuffer, isIntensityFmt, copyfmt, scaleByHalf, rc);
}
}
} }
void ClearScreen(const BPCmd &bp, const EFBRectangle &rc) void ClearScreen(const BPCmd &bp, const EFBRectangle &rc)

View File

@ -60,6 +60,7 @@ BEGIN_EVENT_TABLE(GFXConfigDialogDX,wxDialog)
EVT_CHECKBOX(ID_OVERLAYFPS, GFXConfigDialogDX::AdvancedSettingsChanged) EVT_CHECKBOX(ID_OVERLAYFPS, GFXConfigDialogDX::AdvancedSettingsChanged)
EVT_CHECKBOX(ID_ENABLEEFBCOPY, GFXConfigDialogDX::AdvancedSettingsChanged) EVT_CHECKBOX(ID_ENABLEEFBCOPY, GFXConfigDialogDX::AdvancedSettingsChanged)
EVT_RADIOBUTTON(ID_EFBTORAM, GFXConfigDialogDX::AdvancedSettingsChanged) EVT_RADIOBUTTON(ID_EFBTORAM, GFXConfigDialogDX::AdvancedSettingsChanged)
EVT_CHECKBOX(ID_VERIFYTEXTUREMODIFICATIONS, GFXConfigDialogDX::AdvancedSettingsChanged)
EVT_RADIOBUTTON(ID_EFBTOTEX, GFXConfigDialogDX::AdvancedSettingsChanged) EVT_RADIOBUTTON(ID_EFBTOTEX, GFXConfigDialogDX::AdvancedSettingsChanged)
EVT_CHECKBOX(ID_ENABLEHOTKEY, GFXConfigDialogDX::AdvancedSettingsChanged) EVT_CHECKBOX(ID_ENABLEHOTKEY, GFXConfigDialogDX::AdvancedSettingsChanged)
EVT_CHECKBOX(ID_WIREFRAME, GFXConfigDialogDX::AdvancedSettingsChanged) EVT_CHECKBOX(ID_WIREFRAME, GFXConfigDialogDX::AdvancedSettingsChanged)
@ -138,7 +139,7 @@ void GFXConfigDialogDX::InitializeGUIValues()
m_CopyEFB->SetValue(!g_Config.bEFBCopyDisable); m_CopyEFB->SetValue(!g_Config.bEFBCopyDisable);
g_Config.bCopyEFBToTexture ? m_Radio_CopyEFBToGL->SetValue(true) : m_Radio_CopyEFBToRAM->SetValue(true); g_Config.bCopyEFBToTexture ? m_Radio_CopyEFBToGL->SetValue(true) : m_Radio_CopyEFBToRAM->SetValue(true);
m_VerifyTextureModification->SetValue(g_Config.bVerifyTextureModificationsByCPU);
m_EnableHotkeys->SetValue(g_Config.bOSDHotKey); m_EnableHotkeys->SetValue(g_Config.bOSDHotKey);
m_WireFrame->SetValue(g_Config.bWireFrame); m_WireFrame->SetValue(g_Config.bWireFrame);
m_EnableXFB->SetValue(g_Config.bUseXFB); m_EnableXFB->SetValue(g_Config.bUseXFB);
@ -300,6 +301,7 @@ void GFXConfigDialogDX::CreateGUIControls()
m_CopyEFB = new wxCheckBox( m_PageAdvanced, ID_ENABLEEFBCOPY, wxT("Enable EFB Copy"), wxDefaultPosition, wxDefaultSize, 0 ); m_CopyEFB = new wxCheckBox( m_PageAdvanced, ID_ENABLEEFBCOPY, wxT("Enable EFB Copy"), wxDefaultPosition, wxDefaultSize, 0 );
m_EnableHotkeys = new wxCheckBox( m_PageAdvanced, ID_ENABLEHOTKEY, wxT("Enable Hotkey"), wxDefaultPosition, wxDefaultSize, 0 ); m_EnableHotkeys = new wxCheckBox( m_PageAdvanced, ID_ENABLEHOTKEY, wxT("Enable Hotkey"), wxDefaultPosition, wxDefaultSize, 0 );
m_Radio_CopyEFBToRAM = new wxRadioButton( m_PageAdvanced, ID_EFBTORAM, wxT("To RAM (accuracy)"), wxDefaultPosition, wxDefaultSize, 0 ); m_Radio_CopyEFBToRAM = new wxRadioButton( m_PageAdvanced, ID_EFBTORAM, wxT("To RAM (accuracy)"), wxDefaultPosition, wxDefaultSize, 0 );
m_VerifyTextureModification = new wxCheckBox( m_PageAdvanced, ID_VERIFYTEXTUREMODIFICATIONS, wxT("Check for textures modified by the cpu"), wxDefaultPosition, wxDefaultSize, 0 );
m_Radio_CopyEFBToGL = new wxRadioButton( m_PageAdvanced, ID_EFBTOTEX, wxT("To Texture (performance, resolution)"), wxDefaultPosition, wxDefaultSize, 0 ); m_Radio_CopyEFBToGL = new wxRadioButton( m_PageAdvanced, ID_EFBTOTEX, wxT("To Texture (performance, resolution)"), wxDefaultPosition, wxDefaultSize, 0 );
m_WireFrame = new wxCheckBox( m_PageAdvanced, ID_WIREFRAME, wxT("Enable Wireframe"), wxDefaultPosition, wxDefaultSize, 0 ); m_WireFrame = new wxCheckBox( m_PageAdvanced, ID_WIREFRAME, wxT("Enable Wireframe"), wxDefaultPosition, wxDefaultSize, 0 );
m_EnableRealXFB = new wxCheckBox( m_PageAdvanced, ID_ENABLEREALXFB, wxT("Enable Real XFB"), wxDefaultPosition, wxDefaultSize, 0 ); m_EnableRealXFB = new wxCheckBox( m_PageAdvanced, ID_ENABLEREALXFB, wxT("Enable Real XFB"), wxDefaultPosition, wxDefaultSize, 0 );
@ -332,11 +334,12 @@ void GFXConfigDialogDX::CreateGUIControls()
sSettings->Add( m_CopyEFB, wxGBPosition( 1, 0 ), wxGBSpan( 1, 1 ), wxALL, 5 ); sSettings->Add( m_CopyEFB, wxGBPosition( 1, 0 ), wxGBSpan( 1, 1 ), wxALL, 5 );
sSettings->Add( m_EnableHotkeys, wxGBPosition( 1, 1 ), wxGBSpan( 1, 1 ), wxEXPAND|wxLEFT, 20 ); sSettings->Add( m_EnableHotkeys, wxGBPosition( 1, 1 ), wxGBSpan( 1, 1 ), wxEXPAND|wxLEFT, 20 );
sSettings->Add( m_Radio_CopyEFBToRAM, wxGBPosition( 2, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxLEFT, 10 ); sSettings->Add( m_Radio_CopyEFBToRAM, wxGBPosition( 2, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxLEFT, 10 );
sSettings->Add( m_Radio_CopyEFBToGL, wxGBPosition( 3, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxLEFT|wxTOP, 10 ); sSettings->Add( m_VerifyTextureModification, wxGBPosition( 3, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxLEFT|wxTOP, 10 );
sSettings->Add( m_Radio_CopyEFBToGL, wxGBPosition( 4, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxLEFT|wxTOP, 10 );
sSettings->Add( m_WireFrame, wxGBPosition( 2, 1 ), wxGBSpan( 1, 1 ), wxEXPAND|wxLEFT, 20 ); sSettings->Add( m_WireFrame, wxGBPosition( 2, 1 ), wxGBSpan( 1, 1 ), wxEXPAND|wxLEFT, 20 );
sSettings->Add( m_EnableRealXFB, wxGBPosition( 4, 1 ), wxGBSpan( 1, 1 ), wxEXPAND|wxLEFT, 20 ); sSettings->Add( m_EnableRealXFB, wxGBPosition( 5, 1 ), wxGBSpan( 1, 1 ), wxEXPAND|wxLEFT, 20 );
sSettings->Add( m_EnableXFB, wxGBPosition( 4, 0 ), wxGBSpan( 1, 1 ), wxALL, 5 ); sSettings->Add( m_EnableXFB, wxGBPosition( 5, 0 ), wxGBSpan( 1, 1 ), wxALL, 5 );
sSettings->Add( m_UseNativeMips, wxGBPosition( 5, 0 ), wxGBSpan( 1, 1 ), wxALL, 5 ); sSettings->Add( m_UseNativeMips, wxGBPosition( 6, 0 ), wxGBSpan( 1, 1 ), wxALL, 5 );
sbSettings->Add( sSettings, 0, wxEXPAND, 5 ); sbSettings->Add( sSettings, 0, wxEXPAND, 5 );
sAdvanced->Add( sbSettings, 0, wxEXPAND|wxALL, 5 ); sAdvanced->Add( sbSettings, 0, wxEXPAND|wxALL, 5 );
@ -463,6 +466,8 @@ void GFXConfigDialogDX::AdvancedSettingsChanged(wxCommandEvent& event)
break; break;
case ID_EFBTORAM: case ID_EFBTORAM:
g_Config.bCopyEFBToTexture = false; g_Config.bCopyEFBToTexture = false;
case ID_VERIFYTEXTUREMODIFICATIONS:
g_Config.bVerifyTextureModificationsByCPU = m_VerifyTextureModification->IsChecked();
break; break;
case ID_EFBTOTEX: case ID_EFBTOTEX:
g_Config.bCopyEFBToTexture = true; g_Config.bCopyEFBToTexture = true;
@ -527,6 +532,7 @@ void GFXConfigDialogDX::UpdateGUI()
// Disable the Copy to options when EFBCopy is disabled // Disable the Copy to options when EFBCopy is disabled
m_Radio_CopyEFBToRAM->Enable(!g_Config.bEFBCopyDisable); m_Radio_CopyEFBToRAM->Enable(!g_Config.bEFBCopyDisable);
m_VerifyTextureModification->Enable(!g_Config.bEFBCopyDisable && !g_Config.bCopyEFBToTexture);
m_Radio_CopyEFBToGL->Enable(!g_Config.bEFBCopyDisable); m_Radio_CopyEFBToGL->Enable(!g_Config.bEFBCopyDisable);
// Disable/Enable Safe Texture Cache options // Disable/Enable Safe Texture Cache options

View File

@ -112,6 +112,7 @@ class GFXConfigDialogDX : public wxDialog
wxCheckBox *m_OverlayFPS; wxCheckBox *m_OverlayFPS;
wxCheckBox *m_CopyEFB; wxCheckBox *m_CopyEFB;
wxRadioButton *m_Radio_CopyEFBToRAM; wxRadioButton *m_Radio_CopyEFBToRAM;
wxCheckBox *m_VerifyTextureModification;
wxRadioButton *m_Radio_CopyEFBToGL; wxRadioButton *m_Radio_CopyEFBToGL;
wxCheckBox *m_EnableHotkeys; wxCheckBox *m_EnableHotkeys;
wxCheckBox *m_WireFrame; wxCheckBox *m_WireFrame;
@ -149,6 +150,7 @@ class GFXConfigDialogDX : public wxDialog
ID_OVERLAYFPS, ID_OVERLAYFPS,
ID_ENABLEEFBCOPY, ID_ENABLEEFBCOPY,
ID_EFBTORAM, ID_EFBTORAM,
ID_VERIFYTEXTUREMODIFICATIONS,
ID_EFBTOTEX, ID_EFBTOTEX,
ID_ENABLEHOTKEY, ID_ENABLEHOTKEY,
ID_WIREFRAME, ID_WIREFRAME,

View File

@ -39,6 +39,7 @@
#include "TextureDecoder.h" #include "TextureDecoder.h"
#include "TextureCache.h" #include "TextureCache.h"
#include "HiresTextures.h" #include "HiresTextures.h"
#include "TextureConverter.h"
#include "debugger/debugger.h" #include "debugger/debugger.h"
@ -83,24 +84,58 @@ void TextureCache::InvalidateRange(u32 start_address, u32 size)
TexCache::iterator iter = textures.begin(); TexCache::iterator iter = textures.begin();
while (iter != textures.end()) while (iter != textures.end())
{ {
if (iter->second.IntersectsMemoryRange(start_address, size)) int rangePosition = iter->second.IntersectsMemoryRange(start_address, size);
if (rangePosition == 0)
{ {
iter->second.Destroy(false); iter->second.Destroy(false);
textures.erase(iter++); textures.erase(iter++);
} }
else { else {
if(rangePosition<0)
{
++iter; ++iter;
} }
else
{
break;
}
}
} }
} }
bool TextureCache::TCacheEntry::IntersectsMemoryRange(u32 range_address, u32 range_size) void TextureCache::MakeRangeDynamic(u32 start_address, u32 size)
{
TexCache::iterator iter = textures.begin();
while (iter != textures.end())
{
int rangePosition = iter->second.IntersectsMemoryRange(start_address, size);
if ( rangePosition == 0)
{
if(iter->second.addr != start_address)
{
if(!iter->second.isRenderTarget)
{
iter->second.isDinamic = true;
}
iter->second.hash = 0;
}
}
else
{
if(rangePosition > 0)
break;
}
++iter;
}
}
int TextureCache::TCacheEntry::IntersectsMemoryRange(u32 range_address, u32 range_size)
{ {
if (addr + size_in_bytes < range_address) if (addr + size_in_bytes < range_address)
return false; return -1;
if (addr >= range_address + range_size) if (addr >= range_address + range_size)
return false; return 1;
return true; return 0;
} }
void TextureCache::Shutdown() void TextureCache::Shutdown()
@ -152,6 +187,7 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width,
u32 texID = address; u32 texID = address;
u64 texHash; u64 texHash;
u32 FullFormat = tex_format; u32 FullFormat = tex_format;
bool TextureIsDinamic = false;
if ((tex_format == GX_TF_C4) || (tex_format == GX_TF_C8) || (tex_format == GX_TF_C14X2)) if ((tex_format == GX_TF_C4) || (tex_format == GX_TF_C8) || (tex_format == GX_TF_C14X2))
u32 FullFormat = (tex_format | (tlutfmt << 16)); u32 FullFormat = (tex_format | (tlutfmt << 16));
@ -186,9 +222,29 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width,
TCacheEntry &entry = iter->second; TCacheEntry &entry = iter->second;
if (!g_ActiveConfig.bSafeTextureCache) if (!g_ActiveConfig.bSafeTextureCache)
{
if(entry.isRenderTarget)
{
if(!g_ActiveConfig.bCopyEFBToTexture && g_ActiveConfig.bVerifyTextureModificationsByCPU)
{
hash_value = TexDecoder_GetHash64(ptr,TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples);
}
else
{
hash_value = 0;
}
}
else
{
hash_value = ((u32 *)ptr)[0]; hash_value = ((u32 *)ptr)[0];
}
}
if (entry.isRenderTarget || ((address == entry.addr) && (hash_value == entry.hash) && FullFormat == entry.fmt/* && entry.MipLevels == maxlevel*/))
if ((entry.isRenderTarget && hash_value == entry.hash && address == entry.addr)
|| ((address == entry.addr)
&& (hash_value == entry.hash)
&& FullFormat == entry.fmt/* && entry.MipLevels == maxlevel*/))
{ {
entry.frameCount = frameCount; entry.frameCount = frameCount;
D3D::SetTexture(stage, entry.texture); D3D::SetTexture(stage, entry.texture);
@ -199,8 +255,11 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width,
// Let's reload the new texture data into the same texture, // Let's reload the new texture data into the same texture,
// instead of destroying it and having to create a new one. // instead of destroying it and having to create a new one.
// Might speed up movie playback very, very slightly. // Might speed up movie playback very, very slightly.
TextureIsDinamic = true;
if (width == entry.w && height==entry.h && FullFormat == entry.fmt/* && entry.MipLevels < maxlevel*/) if (!entry.isRenderTarget &&
((!entry.isDinamic && width == entry.w && height==entry.h && FullFormat == entry.fmt /* && entry.MipLevels < maxlevel*/)
|| (entry.isDinamic && entry.w == width && entry.h == height)))
{ {
skip_texture_create = true; skip_texture_create = true;
} }
@ -214,6 +273,7 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width,
// Make an entry in the table // Make an entry in the table
TCacheEntry& entry = textures[texID]; TCacheEntry& entry = textures[texID];
entry.isDinamic = TextureIsDinamic;
PC_TexFormat pcfmt = PC_TEX_FMT_NONE; PC_TexFormat pcfmt = PC_TEX_FMT_NONE;
if (g_ActiveConfig.bHiresTextures) if (g_ActiveConfig.bHiresTextures)
@ -319,6 +379,8 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width,
entry.frameCount = frameCount; entry.frameCount = frameCount;
entry.w = width; entry.w = width;
entry.h = height; entry.h = height;
entry.Scaledw = width;
entry.Scaledh = height;
entry.fmt = FullFormat; entry.fmt = FullFormat;
if (g_ActiveConfig.bDumpTextures) if (g_ActiveConfig.bDumpTextures)
@ -374,11 +436,14 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, boo
TexCache::iterator iter; TexCache::iterator iter;
LPDIRECT3DTEXTURE9 tex = NULL; LPDIRECT3DTEXTURE9 tex = NULL;
iter = textures.find(address); iter = textures.find(address);
bool TextureIsDinamic = false;
if (iter != textures.end()) if (iter != textures.end())
{ {
if (iter->second.isRenderTarget && iter->second.Scaledw == Scaledtex_w && iter->second.Scaledh == Scaledtex_h) if ((iter->second.isRenderTarget && iter->second.Scaledw == Scaledtex_w && iter->second.Scaledh == Scaledtex_h)
|| (iter->second.isDinamic && iter->second.w == tex_w && iter->second.h == tex_h))
{ {
tex = iter->second.texture; tex = iter->second.texture;
TextureIsDinamic = iter->second.isDinamic;
iter->second.frameCount = frameCount; iter->second.frameCount = frameCount;
} }
else else
@ -390,11 +455,16 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, boo
textures.erase(iter); textures.erase(iter);
} }
} }
if(TextureIsDinamic)
{
Scaledtex_w = tex_w;
Scaledtex_h = tex_h;
}
if(!tex) if(!tex)
{ {
TCacheEntry entry; TCacheEntry entry;
entry.isRenderTarget = true; entry.addr = address;
entry.isRenderTarget = !TextureIsDinamic;
entry.hash = 0; entry.hash = 0;
entry.frameCount = frameCount; entry.frameCount = frameCount;
entry.w = tex_w; entry.w = tex_w;
@ -403,11 +473,20 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, boo
entry.Scaledh = Scaledtex_h; entry.Scaledh = Scaledtex_h;
entry.fmt = copyfmt; entry.fmt = copyfmt;
entry.isNonPow2 = true; entry.isNonPow2 = true;
entry.isDinamic = false;
D3D::dev->CreateTexture(Scaledtex_w, Scaledtex_h, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &entry.texture, 0); D3D::dev->CreateTexture(Scaledtex_w, Scaledtex_h, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &entry.texture, 0);
textures[address] = entry; textures[address] = entry;
tex = entry.texture; tex = entry.texture;
} }
// Make sure to resolve anything we need to read from.
LPDIRECT3DTEXTURE9 read_texture = bFromZBuffer ? FBManager.GetEFBDepthTexture(source_rect) : FBManager.GetEFBColorTexture(source_rect);
// We have to run a pixel shader, for color conversion.
Renderer::ResetAPIState(); // reset any game specific settings
if(!TextureIsDinamic || g_ActiveConfig.bCopyEFBToTexture)
{
float colmat[16]= {0.0f}; float colmat[16]= {0.0f};
float fConstAdd[4] = {0.0f}; float fConstAdd[4] = {0.0f};
@ -452,7 +531,6 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, boo
case 1: // I8 case 1: // I8
case 2: // IA4 case 2: // IA4
case 3: // IA8 case 3: // IA8
// TODO - verify these coefficients
colmat[0] = 0.257f; colmat[1] = 0.504f; colmat[2] = 0.098f; colmat[0] = 0.257f; colmat[1] = 0.504f; colmat[2] = 0.098f;
colmat[4] = 0.257f; colmat[5] = 0.504f; colmat[6] = 0.098f; colmat[4] = 0.257f; colmat[5] = 0.504f; colmat[6] = 0.098f;
colmat[8] = 0.257f; colmat[9] = 0.504f; colmat[10] = 0.098f; colmat[8] = 0.257f; colmat[9] = 0.504f; colmat[10] = 0.098f;
@ -516,11 +594,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, boo
break; break;
} }
} }
// Make sure to resolve anything we need to read from.
LPDIRECT3DTEXTURE9 read_texture = bFromZBuffer ? FBManager.GetEFBDepthTexture(source_rect) : FBManager.GetEFBColorTexture(source_rect);
// We have to run a pixel shader, for color conversion.
Renderer::ResetAPIState(); // reset any game specific settings
LPDIRECT3DSURFACE9 Rendersurf = NULL; LPDIRECT3DSURFACE9 Rendersurf = NULL;
tex->GetSurfaceLevel(0,&Rendersurf); tex->GetSurfaceLevel(0,&Rendersurf);
D3D::dev->SetDepthStencilSurface(NULL); D3D::dev->SetDepthStencilSurface(NULL);
@ -583,7 +657,42 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, boo
Scaledtex_h, Scaledtex_h,
((bformat != FOURCC_RAWZ && bformat != D3DFMT_D24X8) && bFromZBuffer)? PixelShaderCache::GetDepthMatrixProgram(SSAAMode): PixelShaderCache::GetColorMatrixProgram(SSAAMode), ((bformat != FOURCC_RAWZ && bformat != D3DFMT_D24X8) && bFromZBuffer)? PixelShaderCache::GetDepthMatrixProgram(SSAAMode): PixelShaderCache::GetColorMatrixProgram(SSAAMode),
VertexShaderCache::GetSimpleVertexShader(SSAAMode)); VertexShaderCache::GetSimpleVertexShader(SSAAMode));
Rendersurf->Release();
}
if(!g_ActiveConfig.bCopyEFBToTexture)
{
TextureConverter::EncodeToRamFromTexture(
address,
read_texture,
Renderer::GetFullTargetWidth(),
Renderer::GetFullTargetHeight(),
xScale,
yScale,
(float)((Renderer::GetFullTargetWidth() - Renderer::GetTargetWidth()) / 2),
(float)((Renderer::GetFullTargetHeight() - Renderer::GetTargetHeight()) / 2) ,
bFromZBuffer,
bIsIntensityFmt,
copyfmt,
bScaleByHalf,
source_rect);
u8 *ptr = g_VideoInitialize.pGetMemoryPointer(address);
int bsw = TexDecoder_GetBlockWidthInTexels(copyfmt) - 1;
int bsh = TexDecoder_GetBlockHeightInTexels(copyfmt) - 1;
int expandedWidth = (tex_w + bsw) & (~bsw);
int expandedHeight = (tex_h + bsh) & (~bsh);
u32 textureSize = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, copyfmt);
MakeRangeDynamic(address,textureSize);
if(g_ActiveConfig.bVerifyTextureModificationsByCPU)
{
textures[address].hash = TexDecoder_GetHash64(ptr,textureSize,g_ActiveConfig.iSafeTextureCache_ColorSamples);
}
else
{
textures[address].hash = 0;
}
}
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER); D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER); D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER);
@ -591,6 +700,6 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, boo
D3D::dev->SetRenderTarget(0, FBManager.GetEFBColorRTSurface()); D3D::dev->SetRenderTarget(0, FBManager.GetEFBColorRTSurface());
D3D::dev->SetDepthStencilSurface(FBManager.GetEFBDepthRTSurface()); D3D::dev->SetDepthStencilSurface(FBManager.GetEFBDepthRTSurface());
Renderer::RestoreAPIState(); Renderer::RestoreAPIState();
Rendersurf->Release();
} }

View File

@ -45,6 +45,7 @@ public:
float scaleX, scaleY; // Hires texutres need this float scaleX, scaleY; // Hires texutres need this
bool isRenderTarget; bool isRenderTarget;
bool isDinamic;// mofified from cpu
bool isNonPow2; bool isNonPow2;
TCacheEntry() TCacheEntry()
@ -66,7 +67,7 @@ public:
Scaledh = 0; Scaledh = 0;
} }
void Destroy(bool shutdown); void Destroy(bool shutdown);
bool IntersectsMemoryRange(u32 range_address, u32 range_size); int IntersectsMemoryRange(u32 range_address, u32 range_size);
}; };
private: private:
@ -82,6 +83,7 @@ public:
static void Shutdown(); static void Shutdown();
static void Invalidate(bool shutdown); static void Invalidate(bool shutdown);
static void InvalidateRange(u32 start_address, u32 size); static void InvalidateRange(u32 start_address, u32 size);
static void MakeRangeDynamic(u32 start_address, u32 size);
static TCacheEntry *Load(int stage, u32 address, int width, int height, int format, int tlutaddr, int tlutfmt,bool UseNativeMips, int maxlevel); static TCacheEntry *Load(int stage, u32 address, int width, int height, int format, int tlutaddr, int tlutfmt,bool UseNativeMips, int maxlevel);
static void CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle &source_rect); static void CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle &source_rect);
}; };

View File

@ -198,7 +198,6 @@ void EncodeToRamUsingShader(LPDIRECT3DPIXELSHADER9 shader, LPDIRECT3DTEXTURE9 sr
u8* destAddr, int dstWidth, int dstHeight, int readStride, bool toTexture, bool linearFilter) u8* destAddr, int dstWidth, int dstHeight, int readStride, bool toTexture, bool linearFilter)
{ {
HRESULT hr; HRESULT hr;
Renderer::ResetAPIState();
u32 index =0; u32 index =0;
while(index < WorkingBuffers && (TrnBuffers[index].Width != dstWidth || TrnBuffers[index].Height != dstHeight)) while(index < WorkingBuffers && (TrnBuffers[index].Width != dstWidth || TrnBuffers[index].Height != dstHeight))
index++; index++;
@ -272,9 +271,6 @@ void EncodeToRamUsingShader(LPDIRECT3DPIXELSHADER9 shader, LPDIRECT3DTEXTURE9 sr
// Draw... // Draw...
D3D::drawShadedTexQuad(srcTexture,&SrcRect,1,1,dstWidth,dstHeight,shader,VertexShaderCache::GetSimpleVertexShader(0)); D3D::drawShadedTexQuad(srcTexture,&SrcRect,1,1,dstWidth,dstHeight,shader,VertexShaderCache::GetSimpleVertexShader(0));
hr = D3D::dev->SetRenderTarget(0, FBManager.GetEFBColorRTSurface());
hr = D3D::dev->SetDepthStencilSurface(FBManager.GetEFBDepthRTSurface());
Renderer::RestoreAPIState();
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER); D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
// .. and then readback the results. // .. and then readback the results.
// TODO: make this less slow. // TODO: make this less slow.
@ -385,10 +381,76 @@ void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyf
if ((format & 0x0f) == 6) if ((format & 0x0f) == 6)
cacheBytes = 64; cacheBytes = 64;
int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format);
Renderer::ResetAPIState();
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight,readStride, true, bScaleByHalf > 0);
D3D::dev->SetRenderTarget(0, FBManager.GetEFBColorRTSurface());
D3D::dev->SetDepthStencilSurface(FBManager.GetEFBDepthRTSurface());
Renderer::RestoreAPIState();
}
void EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture,u32 SourceW, u32 SourceH,float MValueX,float MValueY,float Xstride, float Ystride , bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source)
{
u32 format = copyfmt;
if (bFromZBuffer)
{
format |= _GX_TF_ZTF;
if (copyfmt == 11)
format = GX_TF_Z16;
else if (format < GX_TF_Z8 || format > GX_TF_Z24X8)
format |= _GX_TF_CTF;
}
else
if (copyfmt > GX_TF_RGBA8 || (copyfmt < GX_TF_RGB565 && !bIsIntensityFmt))
format |= _GX_TF_CTF;
LPDIRECT3DPIXELSHADER9 texconv_shader = GetOrCreateEncodingShader(format);
if (!texconv_shader)
return;
u8 *dest_ptr = Memory_GetPtr(address);
int width = (source.right - source.left) >> bScaleByHalf;
int height = (source.bottom - source.top) >> bScaleByHalf;
int size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, format);
u16 blkW = TexDecoder_GetBlockWidthInTexels(format) - 1;
u16 blkH = TexDecoder_GetBlockHeightInTexels(format) - 1;
u16 samples = TextureConversionShader::GetEncodedSampleCount(format);
// only copy on cache line boundaries
// extra pixels are copied but not displayed in the resulting texture
s32 expandedWidth = (width + blkW) & (~blkW);
s32 expandedHeight = (height + blkH) & (~blkH);
float sampleStride = bScaleByHalf?2.0f:1.0f;
TextureConversionShader::SetShaderParameters(
(float)expandedWidth,
expandedHeight * MValueY,
source.left * MValueX + Xstride ,
source.top * MValueY + Ystride,
sampleStride * MValueX,
sampleStride * MValueY,
(float)SourceW,
(float)SourceH);
TargetRectangle scaledSource;
scaledSource.top = 0;
scaledSource.bottom = expandedHeight;
scaledSource.left = 0;
scaledSource.right = expandedWidth / samples;
int cacheBytes = 32;
if ((format & 0x0f) == 6)
cacheBytes = 64;
int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format); int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format);
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight,readStride, true, bScaleByHalf > 0); EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight,readStride, true, bScaleByHalf > 0);
} }
void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc,u8* destAddr, int dstWidth, int dstHeight) void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc,u8* destAddr, int dstWidth, int dstHeight)
{ {
TextureConversionShader::SetShaderParameters( TextureConversionShader::SetShaderParameters(
@ -400,7 +462,11 @@ void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourc
1.0f, 1.0f,
(float)Renderer::GetFullTargetWidth(), (float)Renderer::GetFullTargetWidth(),
(float)Renderer::GetFullTargetHeight()); (float)Renderer::GetFullTargetHeight());
Renderer::ResetAPIState();
EncodeToRamUsingShader(s_rgbToYuyvProgram, srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, 0, false, false); EncodeToRamUsingShader(s_rgbToYuyvProgram, srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, 0, false, false);
D3D::dev->SetRenderTarget(0, FBManager.GetEFBColorRTSurface());
D3D::dev->SetDepthStencilSurface(FBManager.GetEFBDepthRTSurface());
Renderer::RestoreAPIState();
} }

View File

@ -40,6 +40,9 @@ void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourc
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, LPDIRECT3DTEXTURE9 destTexture); void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, LPDIRECT3DTEXTURE9 destTexture);
void EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture,u32 SourceW, u32 SourceH,float MValueX,float MValueY,float Xstride, float Ystride , bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
} }
#endif // _TEXTURECONVERTER_H_ #endif // _TEXTURECONVERTER_H_