diff --git a/Source/Core/VideoCommon/Src/VideoConfig.cpp b/Source/Core/VideoCommon/Src/VideoConfig.cpp index e3051c6e91..a2cacffc10 100644 --- a/Source/Core/VideoCommon/Src/VideoConfig.cpp +++ b/Source/Core/VideoCommon/Src/VideoConfig.cpp @@ -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); diff --git a/Source/Core/VideoCommon/Src/VideoConfig.h b/Source/Core/VideoCommon/Src/VideoConfig.h index 7f5e45f8bf..1e9db7b5a2 100644 --- a/Source/Core/VideoCommon/Src/VideoConfig.h +++ b/Source/Core/VideoCommon/Src/VideoConfig.h @@ -116,6 +116,7 @@ struct VideoConfig bool bOSDHotKey; bool bHack; bool bCopyEFBToTexture; + bool bVerifyTextureModificationsByCPU; bool bCopyEFBScaled; bool bSafeTextureCache; int iSafeTextureCache_ColorSamples; diff --git a/Source/Plugins/Plugin_VideoDX9/Src/BPFunctions.cpp b/Source/Plugins/Plugin_VideoDX9/Src/BPFunctions.cpp index 9667d8b018..c06cc5497a 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/BPFunctions.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/BPFunctions.cpp @@ -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); } } diff --git a/Source/Plugins/Plugin_VideoDX9/Src/DlgSettings.cpp b/Source/Plugins/Plugin_VideoDX9/Src/DlgSettings.cpp index 9c3a26420b..6c751f1ad6 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/DlgSettings.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/DlgSettings.cpp @@ -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 diff --git a/Source/Plugins/Plugin_VideoDX9/Src/DlgSettings.h b/Source/Plugins/Plugin_VideoDX9/Src/DlgSettings.h index dba28f09bf..185a0edfec 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/DlgSettings.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/DlgSettings.h @@ -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, diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp index 63e0e995e3..c095114b54 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp @@ -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(); + } diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.h b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.h index 29c21a1ee7..3986a9723f 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.h @@ -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); }; diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.cpp index 2990cda47c..de45fe79f1 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.cpp @@ -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(); } diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.h b/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.h index 516892574a..09c9de3f46 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.h @@ -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_