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:
parent
464bac82ff
commit
539f63b58b
|
@ -93,6 +93,7 @@ void VideoConfig::Load(const char *ini_file)
|
|||
iniFile.Get("Hacks", "EFBCopyDisable", &bEFBCopyDisable, false);
|
||||
iniFile.Get("Hacks", "EFBCopyDisableHotKey", &bOSDHotKey, 0);
|
||||
iniFile.Get("Hacks", "EFBToTextureEnable", &bCopyEFBToTexture, false);
|
||||
iniFile.Get("Hacks", "EFBVerifyTextureModificationsByCPU",&bVerifyTextureModificationsByCPU,false);
|
||||
iniFile.Get("Hacks", "EFBScaledCopy", &bCopyEFBScaled, true);
|
||||
iniFile.Get("Hacks", "FIFOBPHack", &bFIFOBPhack, false);
|
||||
iniFile.Get("Hacks", "ProjectionHack", &iPhackvalue, 0);
|
||||
|
@ -125,6 +126,8 @@ void VideoConfig::GameIniLoad(const char *ini_file)
|
|||
iniFile.Get("Video", "EFBCopyDisableHotKey", &bOSDHotKey);
|
||||
if (iniFile.Exists("Video", "EFBToTextureEnable"))
|
||||
iniFile.Get("Video", "EFBToTextureEnable", &bCopyEFBToTexture);
|
||||
if (iniFile.Exists("Video", "EFBVerifyTextureModificationsByCPU"))
|
||||
iniFile.Get("Video", "EFBVerifyTextureModificationsByCPU", &bVerifyTextureModificationsByCPU);
|
||||
if (iniFile.Exists("Video", "EFBScaledCopy"))
|
||||
iniFile.Get("Video", "EFBScaledCopy", &bCopyEFBScaled);
|
||||
if (iniFile.Exists("Video", "SafeTextureCache"))
|
||||
|
@ -200,6 +203,7 @@ void VideoConfig::Save(const char *ini_file)
|
|||
iniFile.Set("Hacks", "EFBCopyDisable", bEFBCopyDisable);
|
||||
iniFile.Set("Hacks", "EFBCopyDisableHotKey", bOSDHotKey);
|
||||
iniFile.Set("Hacks", "EFBToTextureEnable", bCopyEFBToTexture);
|
||||
iniFile.Set("Hacks", "EFBVerifyTextureModificationsByCPU", bVerifyTextureModificationsByCPU);
|
||||
iniFile.Set("Hacks", "EFBScaledCopy", bCopyEFBScaled);
|
||||
iniFile.Set("Hacks", "FIFOBPHack", bFIFOBPhack);
|
||||
iniFile.Set("Hacks", "ProjectionHack", iPhackvalue);
|
||||
|
|
|
@ -116,6 +116,7 @@ struct VideoConfig
|
|||
bool bOSDHotKey;
|
||||
bool bHack;
|
||||
bool bCopyEFBToTexture;
|
||||
bool bVerifyTextureModificationsByCPU;
|
||||
bool bCopyEFBScaled;
|
||||
bool bSafeTextureCache;
|
||||
int iSafeTextureCache_ColorSamples;
|
||||
|
|
|
@ -82,17 +82,7 @@ void CopyEFB(const BPCmd &bp, const EFBRectangle &rc, const u32 &address, const
|
|||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
//ToRam
|
||||
TextureConverter::EncodeToRam(address, fromZBuffer, isIntensityFmt, copyfmt, scaleByHalf, rc);
|
||||
}
|
||||
TextureCache::CopyRenderTargetToTexture(address, fromZBuffer, isIntensityFmt, copyfmt, scaleByHalf, rc);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@ BEGIN_EVENT_TABLE(GFXConfigDialogDX,wxDialog)
|
|||
EVT_CHECKBOX(ID_OVERLAYFPS, GFXConfigDialogDX::AdvancedSettingsChanged)
|
||||
EVT_CHECKBOX(ID_ENABLEEFBCOPY, GFXConfigDialogDX::AdvancedSettingsChanged)
|
||||
EVT_RADIOBUTTON(ID_EFBTORAM, GFXConfigDialogDX::AdvancedSettingsChanged)
|
||||
EVT_CHECKBOX(ID_VERIFYTEXTUREMODIFICATIONS, GFXConfigDialogDX::AdvancedSettingsChanged)
|
||||
EVT_RADIOBUTTON(ID_EFBTOTEX, GFXConfigDialogDX::AdvancedSettingsChanged)
|
||||
EVT_CHECKBOX(ID_ENABLEHOTKEY, GFXConfigDialogDX::AdvancedSettingsChanged)
|
||||
EVT_CHECKBOX(ID_WIREFRAME, GFXConfigDialogDX::AdvancedSettingsChanged)
|
||||
|
@ -138,7 +139,7 @@ void GFXConfigDialogDX::InitializeGUIValues()
|
|||
|
||||
m_CopyEFB->SetValue(!g_Config.bEFBCopyDisable);
|
||||
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_WireFrame->SetValue(g_Config.bWireFrame);
|
||||
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_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_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_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 );
|
||||
|
@ -332,11 +334,12 @@ void GFXConfigDialogDX::CreateGUIControls()
|
|||
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_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_EnableRealXFB, wxGBPosition( 4, 1 ), wxGBSpan( 1, 1 ), wxEXPAND|wxLEFT, 20 );
|
||||
sSettings->Add( m_EnableXFB, wxGBPosition( 4, 0 ), wxGBSpan( 1, 1 ), wxALL, 5 );
|
||||
sSettings->Add( m_UseNativeMips, wxGBPosition( 5, 0 ), wxGBSpan( 1, 1 ), wxALL, 5 );
|
||||
sSettings->Add( m_EnableRealXFB, wxGBPosition( 5, 1 ), wxGBSpan( 1, 1 ), wxEXPAND|wxLEFT, 20 );
|
||||
sSettings->Add( m_EnableXFB, 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 );
|
||||
sAdvanced->Add( sbSettings, 0, wxEXPAND|wxALL, 5 );
|
||||
|
||||
|
@ -463,6 +466,8 @@ void GFXConfigDialogDX::AdvancedSettingsChanged(wxCommandEvent& event)
|
|||
break;
|
||||
case ID_EFBTORAM:
|
||||
g_Config.bCopyEFBToTexture = false;
|
||||
case ID_VERIFYTEXTUREMODIFICATIONS:
|
||||
g_Config.bVerifyTextureModificationsByCPU = m_VerifyTextureModification->IsChecked();
|
||||
break;
|
||||
case ID_EFBTOTEX:
|
||||
g_Config.bCopyEFBToTexture = true;
|
||||
|
@ -527,6 +532,7 @@ void GFXConfigDialogDX::UpdateGUI()
|
|||
|
||||
// Disable the Copy to options when EFBCopy is disabled
|
||||
m_Radio_CopyEFBToRAM->Enable(!g_Config.bEFBCopyDisable);
|
||||
m_VerifyTextureModification->Enable(!g_Config.bEFBCopyDisable && !g_Config.bCopyEFBToTexture);
|
||||
m_Radio_CopyEFBToGL->Enable(!g_Config.bEFBCopyDisable);
|
||||
|
||||
// Disable/Enable Safe Texture Cache options
|
||||
|
|
|
@ -112,6 +112,7 @@ class GFXConfigDialogDX : public wxDialog
|
|||
wxCheckBox *m_OverlayFPS;
|
||||
wxCheckBox *m_CopyEFB;
|
||||
wxRadioButton *m_Radio_CopyEFBToRAM;
|
||||
wxCheckBox *m_VerifyTextureModification;
|
||||
wxRadioButton *m_Radio_CopyEFBToGL;
|
||||
wxCheckBox *m_EnableHotkeys;
|
||||
wxCheckBox *m_WireFrame;
|
||||
|
@ -149,6 +150,7 @@ class GFXConfigDialogDX : public wxDialog
|
|||
ID_OVERLAYFPS,
|
||||
ID_ENABLEEFBCOPY,
|
||||
ID_EFBTORAM,
|
||||
ID_VERIFYTEXTUREMODIFICATIONS,
|
||||
ID_EFBTOTEX,
|
||||
ID_ENABLEHOTKEY,
|
||||
ID_WIREFRAME,
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "TextureDecoder.h"
|
||||
#include "TextureCache.h"
|
||||
#include "HiresTextures.h"
|
||||
#include "TextureConverter.h"
|
||||
|
||||
#include "debugger/debugger.h"
|
||||
|
||||
|
@ -83,24 +84,58 @@ void TextureCache::InvalidateRange(u32 start_address, u32 size)
|
|||
TexCache::iterator iter = textures.begin();
|
||||
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);
|
||||
textures.erase(iter++);
|
||||
}
|
||||
else {
|
||||
++iter;
|
||||
if(rangePosition<0)
|
||||
{
|
||||
++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)
|
||||
return false;
|
||||
return -1;
|
||||
if (addr >= range_address + range_size)
|
||||
return false;
|
||||
return true;
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TextureCache::Shutdown()
|
||||
|
@ -152,6 +187,7 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width,
|
|||
u32 texID = address;
|
||||
u64 texHash;
|
||||
u32 FullFormat = tex_format;
|
||||
bool TextureIsDinamic = false;
|
||||
if ((tex_format == GX_TF_C4) || (tex_format == GX_TF_C8) || (tex_format == GX_TF_C14X2))
|
||||
u32 FullFormat = (tex_format | (tlutfmt << 16));
|
||||
|
||||
|
@ -186,9 +222,29 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width,
|
|||
TCacheEntry &entry = iter->second;
|
||||
|
||||
if (!g_ActiveConfig.bSafeTextureCache)
|
||||
hash_value = ((u32 *)ptr)[0];
|
||||
{
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
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,
|
||||
// instead of destroying it and having to create a new one.
|
||||
// Might speed up movie playback very, very slightly.
|
||||
|
||||
if (width == entry.w && height==entry.h && FullFormat == entry.fmt/* && entry.MipLevels < maxlevel*/)
|
||||
TextureIsDinamic = true;
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -214,6 +273,7 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width,
|
|||
|
||||
// Make an entry in the table
|
||||
TCacheEntry& entry = textures[texID];
|
||||
entry.isDinamic = TextureIsDinamic;
|
||||
PC_TexFormat pcfmt = PC_TEX_FMT_NONE;
|
||||
|
||||
if (g_ActiveConfig.bHiresTextures)
|
||||
|
@ -319,6 +379,8 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width,
|
|||
entry.frameCount = frameCount;
|
||||
entry.w = width;
|
||||
entry.h = height;
|
||||
entry.Scaledw = width;
|
||||
entry.Scaledh = height;
|
||||
entry.fmt = FullFormat;
|
||||
|
||||
if (g_ActiveConfig.bDumpTextures)
|
||||
|
@ -371,14 +433,17 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, boo
|
|||
int Scaledtex_w = (g_ActiveConfig.bCopyEFBScaled)?((int)(xScale * SuperSampleCompensation * tex_w)):tex_w;
|
||||
int Scaledtex_h = (g_ActiveConfig.bCopyEFBScaled)?((int)(yScale * SuperSampleCompensation * tex_h)):tex_h;
|
||||
|
||||
TexCache::iterator iter;
|
||||
TexCache::iterator iter;
|
||||
LPDIRECT3DTEXTURE9 tex = NULL;
|
||||
iter = textures.find(address);
|
||||
bool TextureIsDinamic = false;
|
||||
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;
|
||||
TextureIsDinamic = iter->second.isDinamic;
|
||||
iter->second.frameCount = frameCount;
|
||||
}
|
||||
else
|
||||
|
@ -390,11 +455,16 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, boo
|
|||
textures.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
if(TextureIsDinamic)
|
||||
{
|
||||
Scaledtex_w = tex_w;
|
||||
Scaledtex_h = tex_h;
|
||||
}
|
||||
if(!tex)
|
||||
{
|
||||
TCacheEntry entry;
|
||||
entry.isRenderTarget = true;
|
||||
entry.addr = address;
|
||||
entry.isRenderTarget = !TextureIsDinamic;
|
||||
entry.hash = 0;
|
||||
entry.frameCount = frameCount;
|
||||
entry.w = tex_w;
|
||||
|
@ -403,187 +473,226 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, boo
|
|||
entry.Scaledh = Scaledtex_h;
|
||||
entry.fmt = copyfmt;
|
||||
entry.isNonPow2 = true;
|
||||
entry.isDinamic = false;
|
||||
D3D::dev->CreateTexture(Scaledtex_w, Scaledtex_h, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &entry.texture, 0);
|
||||
textures[address] = entry;
|
||||
tex = entry.texture;
|
||||
}
|
||||
|
||||
|
||||
float colmat[16]= {0.0f};
|
||||
float fConstAdd[4] = {0.0f};
|
||||
|
||||
if (bFromZBuffer)
|
||||
{
|
||||
switch(copyfmt)
|
||||
{
|
||||
case 0: // Z4
|
||||
case 1: // Z8
|
||||
colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1.0f;
|
||||
break;
|
||||
case 3: // Z16 //?
|
||||
colmat[1] = colmat[5] = colmat[9] = colmat[12] = 1.0f;
|
||||
case 11: // Z16 (reverse order)
|
||||
colmat[0] = colmat[4] = colmat[8] = colmat[13] = 1.0f;
|
||||
break;
|
||||
case 6: // Z24X8
|
||||
colmat[0] = colmat[5] = colmat[10] = 1.0f;
|
||||
break;
|
||||
case 9: // Z8M
|
||||
colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1.0f;
|
||||
break;
|
||||
case 10: // Z8L
|
||||
colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1.0f;
|
||||
break;
|
||||
case 12: // Z16L
|
||||
colmat[2] = colmat[6] = colmat[10] = colmat[13] = 1.0f;
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "Unknown copy zbuf format: 0x%x", copyfmt);
|
||||
colmat[2] = colmat[5] = colmat[8] = 1.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (bIsIntensityFmt)
|
||||
{
|
||||
fConstAdd[0] = fConstAdd[1] = fConstAdd[2] = 16.0f/255.0f;
|
||||
switch (copyfmt)
|
||||
{
|
||||
case 0: // I4
|
||||
case 1: // I8
|
||||
case 2: // IA4
|
||||
case 3: // IA8
|
||||
// TODO - verify these coefficients
|
||||
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[8] = 0.257f; colmat[9] = 0.504f; colmat[10] = 0.098f;
|
||||
|
||||
if (copyfmt < 2)
|
||||
{
|
||||
fConstAdd[3] = 16.0f / 255.0f;
|
||||
colmat[12] = 0.257f; colmat[13] = 0.504f; colmat[14] = 0.098f;
|
||||
}
|
||||
else// alpha
|
||||
colmat[15] = 1;
|
||||
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "Unknown copy intensity format: 0x%x", copyfmt);
|
||||
colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (copyfmt)
|
||||
{
|
||||
case 0: // R4
|
||||
case 8: // R8
|
||||
colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1;
|
||||
break;
|
||||
case 2: // RA4
|
||||
case 3: // RA8
|
||||
colmat[0] = colmat[4] = colmat[8] = colmat[15] = 1;
|
||||
break;
|
||||
|
||||
case 7: // A8
|
||||
colmat[3] = colmat[7] = colmat[11] = colmat[15] = 1;
|
||||
break;
|
||||
case 9: // G8
|
||||
colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1;
|
||||
break;
|
||||
case 10: // B8
|
||||
colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1;
|
||||
break;
|
||||
case 11: // RG8
|
||||
colmat[0] = colmat[4] = colmat[8] = colmat[13] = 1;
|
||||
break;
|
||||
case 12: // GB8
|
||||
colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1;
|
||||
break;
|
||||
|
||||
case 4: // RGB565
|
||||
colmat[0] = colmat[5] = colmat[10] = 1;
|
||||
fConstAdd[3] = 1; // set alpha to 1
|
||||
break;
|
||||
case 5: // RGB5A3
|
||||
case 6: // RGBA8
|
||||
colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "Unknown copy color format: 0x%x", copyfmt);
|
||||
colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1;
|
||||
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;
|
||||
tex->GetSurfaceLevel(0,&Rendersurf);
|
||||
D3D::dev->SetDepthStencilSurface(NULL);
|
||||
D3D::dev->SetRenderTarget(0, Rendersurf);
|
||||
|
||||
D3DVIEWPORT9 vp;
|
||||
|
||||
// Stretch picture with increased internal resolution
|
||||
vp.X = 0;
|
||||
vp.Y = 0;
|
||||
vp.Width = Scaledtex_w;
|
||||
vp.Height = Scaledtex_h;
|
||||
vp.MinZ = 0.0f;
|
||||
vp.MaxZ = 1.0f;
|
||||
D3D::dev->SetViewport(&vp);
|
||||
RECT destrect;
|
||||
destrect.bottom = Scaledtex_h;
|
||||
destrect.left = 0;
|
||||
destrect.right = Scaledtex_w;
|
||||
destrect.top = 0;
|
||||
|
||||
|
||||
PixelShaderManager::SetColorMatrix(colmat, fConstAdd); // set transformation
|
||||
TargetRectangle targetSource = Renderer::ConvertEFBRectangle(source_rect);
|
||||
RECT sourcerect;
|
||||
sourcerect.bottom = targetSource.bottom;
|
||||
sourcerect.left = targetSource.left;
|
||||
sourcerect.right = targetSource.right;
|
||||
sourcerect.top = targetSource.top;
|
||||
|
||||
|
||||
if(bFromZBuffer)
|
||||
if(!TextureIsDinamic || g_ActiveConfig.bCopyEFBToTexture)
|
||||
{
|
||||
if(bScaleByHalf || g_ActiveConfig.iMultisampleMode)
|
||||
|
||||
float colmat[16]= {0.0f};
|
||||
float fConstAdd[4] = {0.0f};
|
||||
|
||||
if (bFromZBuffer)
|
||||
{
|
||||
switch(copyfmt)
|
||||
{
|
||||
case 0: // Z4
|
||||
case 1: // Z8
|
||||
colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1.0f;
|
||||
break;
|
||||
case 3: // Z16 //?
|
||||
colmat[1] = colmat[5] = colmat[9] = colmat[12] = 1.0f;
|
||||
case 11: // Z16 (reverse order)
|
||||
colmat[0] = colmat[4] = colmat[8] = colmat[13] = 1.0f;
|
||||
break;
|
||||
case 6: // Z24X8
|
||||
colmat[0] = colmat[5] = colmat[10] = 1.0f;
|
||||
break;
|
||||
case 9: // Z8M
|
||||
colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1.0f;
|
||||
break;
|
||||
case 10: // Z8L
|
||||
colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1.0f;
|
||||
break;
|
||||
case 12: // Z16L
|
||||
colmat[2] = colmat[6] = colmat[10] = colmat[13] = 1.0f;
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "Unknown copy zbuf format: 0x%x", copyfmt);
|
||||
colmat[2] = colmat[5] = colmat[8] = 1.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (bIsIntensityFmt)
|
||||
{
|
||||
fConstAdd[0] = fConstAdd[1] = fConstAdd[2] = 16.0f/255.0f;
|
||||
switch (copyfmt)
|
||||
{
|
||||
case 0: // I4
|
||||
case 1: // I8
|
||||
case 2: // IA4
|
||||
case 3: // IA8
|
||||
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[8] = 0.257f; colmat[9] = 0.504f; colmat[10] = 0.098f;
|
||||
|
||||
if (copyfmt < 2)
|
||||
{
|
||||
fConstAdd[3] = 16.0f / 255.0f;
|
||||
colmat[12] = 0.257f; colmat[13] = 0.504f; colmat[14] = 0.098f;
|
||||
}
|
||||
else// alpha
|
||||
colmat[15] = 1;
|
||||
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "Unknown copy intensity format: 0x%x", copyfmt);
|
||||
colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (copyfmt)
|
||||
{
|
||||
case 0: // R4
|
||||
case 8: // R8
|
||||
colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1;
|
||||
break;
|
||||
case 2: // RA4
|
||||
case 3: // RA8
|
||||
colmat[0] = colmat[4] = colmat[8] = colmat[15] = 1;
|
||||
break;
|
||||
|
||||
case 7: // A8
|
||||
colmat[3] = colmat[7] = colmat[11] = colmat[15] = 1;
|
||||
break;
|
||||
case 9: // G8
|
||||
colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1;
|
||||
break;
|
||||
case 10: // B8
|
||||
colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1;
|
||||
break;
|
||||
case 11: // RG8
|
||||
colmat[0] = colmat[4] = colmat[8] = colmat[13] = 1;
|
||||
break;
|
||||
case 12: // GB8
|
||||
colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1;
|
||||
break;
|
||||
|
||||
case 4: // RGB565
|
||||
colmat[0] = colmat[5] = colmat[10] = 1;
|
||||
fConstAdd[3] = 1; // set alpha to 1
|
||||
break;
|
||||
case 5: // RGB5A3
|
||||
case 6: // RGBA8
|
||||
colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "Unknown copy color format: 0x%x", copyfmt);
|
||||
colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LPDIRECT3DSURFACE9 Rendersurf = NULL;
|
||||
tex->GetSurfaceLevel(0,&Rendersurf);
|
||||
D3D::dev->SetDepthStencilSurface(NULL);
|
||||
D3D::dev->SetRenderTarget(0, Rendersurf);
|
||||
|
||||
D3DVIEWPORT9 vp;
|
||||
|
||||
// Stretch picture with increased internal resolution
|
||||
vp.X = 0;
|
||||
vp.Y = 0;
|
||||
vp.Width = Scaledtex_w;
|
||||
vp.Height = Scaledtex_h;
|
||||
vp.MinZ = 0.0f;
|
||||
vp.MaxZ = 1.0f;
|
||||
D3D::dev->SetViewport(&vp);
|
||||
RECT destrect;
|
||||
destrect.bottom = Scaledtex_h;
|
||||
destrect.left = 0;
|
||||
destrect.right = Scaledtex_w;
|
||||
destrect.top = 0;
|
||||
|
||||
|
||||
PixelShaderManager::SetColorMatrix(colmat, fConstAdd); // set transformation
|
||||
TargetRectangle targetSource = Renderer::ConvertEFBRectangle(source_rect);
|
||||
RECT sourcerect;
|
||||
sourcerect.bottom = targetSource.bottom;
|
||||
sourcerect.left = targetSource.left;
|
||||
sourcerect.right = targetSource.right;
|
||||
sourcerect.top = targetSource.top;
|
||||
|
||||
|
||||
if(bFromZBuffer)
|
||||
{
|
||||
if(bScaleByHalf || g_ActiveConfig.iMultisampleMode)
|
||||
{
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
}
|
||||
|
||||
|
||||
D3DFORMAT bformat = FBManager.GetEFBDepthRTSurfaceFormat();
|
||||
int SSAAMode = g_ActiveConfig.iMultisampleMode;
|
||||
D3D::drawShadedTexQuad(
|
||||
read_texture,
|
||||
&sourcerect,
|
||||
Renderer::GetFullTargetWidth() ,
|
||||
Renderer::GetFullTargetHeight(),
|
||||
Scaledtex_w,
|
||||
Scaledtex_h,
|
||||
((bformat != FOURCC_RAWZ && bformat != D3DFMT_D24X8) && bFromZBuffer)? PixelShaderCache::GetDepthMatrixProgram(SSAAMode): PixelShaderCache::GetColorMatrixProgram(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
|
||||
{
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
|
||||
textures[address].hash = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
}
|
||||
|
||||
|
||||
D3DFORMAT bformat = FBManager.GetEFBDepthRTSurfaceFormat();
|
||||
int SSAAMode = g_ActiveConfig.iMultisampleMode;
|
||||
D3D::drawShadedTexQuad(
|
||||
read_texture,
|
||||
&sourcerect,
|
||||
Renderer::GetFullTargetWidth() ,
|
||||
Renderer::GetFullTargetHeight(),
|
||||
Scaledtex_w,
|
||||
Scaledtex_h,
|
||||
((bformat != FOURCC_RAWZ && bformat != D3DFMT_D24X8) && bFromZBuffer)? PixelShaderCache::GetDepthMatrixProgram(SSAAMode): PixelShaderCache::GetColorMatrixProgram(SSAAMode),
|
||||
VertexShaderCache::GetSimpleVertexShader(SSAAMode));
|
||||
|
||||
|
||||
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
||||
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->SetDepthStencilSurface(FBManager.GetEFBDepthRTSurface());
|
||||
Renderer::RestoreAPIState();
|
||||
Rendersurf->Release();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ public:
|
|||
float scaleX, scaleY; // Hires texutres need this
|
||||
|
||||
bool isRenderTarget;
|
||||
bool isDinamic;// mofified from cpu
|
||||
bool isNonPow2;
|
||||
|
||||
TCacheEntry()
|
||||
|
@ -66,7 +67,7 @@ public:
|
|||
Scaledh = 0;
|
||||
}
|
||||
void Destroy(bool shutdown);
|
||||
bool IntersectsMemoryRange(u32 range_address, u32 range_size);
|
||||
int IntersectsMemoryRange(u32 range_address, u32 range_size);
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -82,6 +83,7 @@ public:
|
|||
static void Shutdown();
|
||||
static void Invalidate(bool shutdown);
|
||||
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 void CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle &source_rect);
|
||||
};
|
||||
|
|
|
@ -197,8 +197,7 @@ void Shutdown()
|
|||
void EncodeToRamUsingShader(LPDIRECT3DPIXELSHADER9 shader, LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc,
|
||||
u8* destAddr, int dstWidth, int dstHeight, int readStride, bool toTexture, bool linearFilter)
|
||||
{
|
||||
HRESULT hr;
|
||||
Renderer::ResetAPIState();
|
||||
HRESULT hr;
|
||||
u32 index =0;
|
||||
while(index < WorkingBuffers && (TrnBuffers[index].Width != dstWidth || TrnBuffers[index].Height != dstHeight))
|
||||
index++;
|
||||
|
@ -271,10 +270,7 @@ void EncodeToRamUsingShader(LPDIRECT3DPIXELSHADER9 shader, LPDIRECT3DTEXTURE9 sr
|
|||
|
||||
|
||||
// Draw...
|
||||
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::drawShadedTexQuad(srcTexture,&SrcRect,1,1,dstWidth,dstHeight,shader,VertexShaderCache::GetSimpleVertexShader(0));
|
||||
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
||||
// .. and then readback the results.
|
||||
// TODO: make this less slow.
|
||||
|
@ -347,7 +343,7 @@ void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyf
|
|||
|
||||
// Invalidate any existing texture covering this memory range.
|
||||
// TODO - don't delete the texture if it already exists, just replace the contents.
|
||||
TextureCache::InvalidateRange(address, size_in_bytes);
|
||||
TextureCache::InvalidateRange(address, size_in_bytes);
|
||||
|
||||
u16 blkW = TexDecoder_GetBlockWidthInTexels(format) - 1;
|
||||
u16 blkH = TexDecoder_GetBlockHeightInTexels(format) - 1;
|
||||
|
@ -385,10 +381,76 @@ void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyf
|
|||
if ((format & 0x0f) == 6)
|
||||
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);
|
||||
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)
|
||||
{
|
||||
TextureConversionShader::SetShaderParameters(
|
||||
|
@ -400,7 +462,11 @@ void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourc
|
|||
1.0f,
|
||||
(float)Renderer::GetFullTargetWidth(),
|
||||
(float)Renderer::GetFullTargetHeight());
|
||||
Renderer::ResetAPIState();
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -40,6 +40,9 @@ void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourc
|
|||
|
||||
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_
|
||||
|
|
Loading…
Reference in New Issue