From 8424eeb4ee8f9bc6ce8e9fff7caaebb2a5a19c7b Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Thu, 5 May 2016 15:32:21 +0200 Subject: [PATCH 1/7] gsdx tc: small hint for the compiler --- plugins/GSdx/GSTextureCache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/GSdx/GSTextureCache.cpp b/plugins/GSdx/GSTextureCache.cpp index 7447a7e765..4099028506 100644 --- a/plugins/GSdx/GSTextureCache.cpp +++ b/plugins/GSdx/GSTextureCache.cpp @@ -1536,7 +1536,7 @@ void GSTextureCache::Source::Update(const GSVector4i& rect) return; } - GSVector2i bs = GSLocalMemory::m_psm[m_TEX0.PSM].bs; + const GSVector2i& bs = GSLocalMemory::m_psm[m_TEX0.PSM].bs; int tw = std::max(1 << m_TEX0.TW, bs.x); int th = std::max(1 << m_TEX0.TH, bs.y); From 7b0427e86e2e7e35e313bcf6cf5b5325825a73b6 Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Thu, 5 May 2016 15:46:21 +0200 Subject: [PATCH 2/7] gsdx hack: use psm lookup + remove now useless log --- plugins/GSdx/GSHwHack.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/plugins/GSdx/GSHwHack.cpp b/plugins/GSdx/GSHwHack.cpp index b2fa15ecdb..05a00c9c45 100644 --- a/plugins/GSdx/GSHwHack.cpp +++ b/plugins/GSdx/GSHwHack.cpp @@ -2623,20 +2623,13 @@ bool GSState::IsBadFrame(int& skip, int UserHacks_SkipDraw) if(fi.TME) { // depth textures (bully, mgs3s1 intro, Front Mission 5) - if( (fi.TPSM == PSM_PSMZ32 || fi.TPSM == PSM_PSMZ24 || fi.TPSM == PSM_PSMZ16 || fi.TPSM == PSM_PSMZ16S) || - // General, often problematic post processing - (GSUtil::HasSharedBits(fi.FBP, fi.FPSM, fi.TBP0, fi.TPSM)) ) + // General, often problematic post processing + if (GSLocalMemory::m_psm[fi.TPSM].depth || GSUtil::HasSharedBits(fi.FBP, fi.FPSM, fi.TBP0, fi.TPSM)) { skip = UserHacks_SkipDraw; } } } -#ifdef ENABLE_OGL_DEBUG - else if (fi.TME) { - if(fi.TPSM == PSM_PSMZ32 || fi.TPSM == PSM_PSMZ24 || fi.TPSM == PSM_PSMZ16 || fi.TPSM == PSM_PSMZ16S) - GL_INS("!!! Depth Texture 0x%x!!!", fi.TPSM); - } -#endif if(skip > 0) { From 21d1bd48ec3607b03ec1f18534c01355965bd4b6 Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Thu, 5 May 2016 16:03:48 +0200 Subject: [PATCH 3/7] gsdx hack: move the CRC setup into a separate function In order to reduce a bit the overhead of IsBadFrame called each draw calls --- plugins/GSdx/GSHwHack.cpp | 322 ++++++++++++++++++-------------------- plugins/GSdx/GSState.cpp | 5 +- plugins/GSdx/GSState.h | 24 ++- 3 files changed, 175 insertions(+), 176 deletions(-) diff --git a/plugins/GSdx/GSHwHack.cpp b/plugins/GSdx/GSHwHack.cpp index 05a00c9c45..cef3a96387 100644 --- a/plugins/GSdx/GSHwHack.cpp +++ b/plugins/GSdx/GSHwHack.cpp @@ -29,18 +29,6 @@ int s_crc_hack_level = 3; #define Aggresive (s_crc_hack_level > 3) #define Dx_only (s_crc_hack_level > 2) -struct GSFrameInfo -{ - uint32 FBP; - uint32 FPSM; - uint32 FBMSK; - uint32 TBP0; - uint32 TPSM; - uint32 TZTST; - bool TME; -}; - -typedef bool (*GetSkipCount)(const GSFrameInfo& fi, int& skip); CRC::Region g_crc_region = CRC::NoRegion; //////////////////////////////////////////////////////////////////////////////// @@ -2442,6 +2430,158 @@ bool IsInvokedDynamicCrcHack( GSFrameInfo &fi, int& skip, int region, bool &resu #endif +void GSState::SetupCrcHack() +{ + GetSkipCount lut[CRC::TitleCount]; + + s_crc_hack_level = theApp.GetConfig("crc_hack_level", 3); + + memset(lut, 0, sizeof(lut)); + + if (s_crc_hack_level > 1) { + lut[CRC::AceCombat4] = GSC_AceCombat4; + lut[CRC::AlpineRacer3] = GSC_AlpineRacer3; + lut[CRC::BlackHawkDown] = GSC_BlackHawkDown; + lut[CRC::BleachBladeBattlers] = GSC_BleachBladeBattlers; + lut[CRC::BurnoutDominator] = GSC_Burnout; + lut[CRC::BurnoutRevenge] = GSC_Burnout; + lut[CRC::BurnoutTakedown] = GSC_Burnout; + lut[CRC::CaptainTsubasa] = GSC_CaptainTsubasa; + lut[CRC::CrashBandicootWoC] = GSC_CrashBandicootWoC; + lut[CRC::DBZBT2] = GSC_DBZBT2; + lut[CRC::DBZBT3] = GSC_DBZBT3; + lut[CRC::DevilMayCry3] = GSC_DevilMayCry3; + lut[CRC::EternalPoison] = GSC_EternalPoison; + lut[CRC::EvangelionJo] = GSC_EvangelionJo; + lut[CRC::FFVIIDoC] = GSC_FFVIIDoC; + lut[CRC::FightingBeautyWulong] = GSC_FightingBeautyWulong; + lut[CRC::FinalFightStreetwise] = GSC_FinalFightStreetwise; + lut[CRC::FrontMission5] = GSC_FrontMission5; + lut[CRC::Genji] = GSC_Genji; + lut[CRC::GetaWayBlackMonday] = GSC_GetaWay; + lut[CRC::GetaWay] = GSC_GetaWay; + lut[CRC::GiTS] = GSC_GiTS; + lut[CRC::GodHand] = GSC_GodHand; + lut[CRC::GTASanAndreas] = GSC_GTASanAndreas; + lut[CRC::HauntingGround] = GSC_HauntingGround; + lut[CRC::HeavyMetalThunder] = GSC_HeavyMetalThunder; + lut[CRC::HummerBadlands] = GSC_HummerBadlands; + lut[CRC::IkkiTousen] = GSC_IkkiTousen; + lut[CRC::KnightsOfTheTemple2] = GSC_KnightsOfTheTemple2; + lut[CRC::Kunoichi] = GSC_Kunoichi; + lut[CRC::LordOfTheRingsThirdAge] = GSC_LordOfTheRingsThirdAge; + lut[CRC::Manhunt2] = GSC_Manhunt2; + lut[CRC::MidnightClub3] = GSC_MidnightClub3; + lut[CRC::NanoBreaker] = GSC_NanoBreaker; + lut[CRC::NarutimateAccel] = GSC_NarutimateAccel; + lut[CRC::Naruto] = GSC_Naruto; + lut[CRC::Oneechanbara2Special] = GSC_Oneechanbara2Special; + lut[CRC::Onimusha3] = GSC_Onimusha3; + lut[CRC::RedDeadRevolver] = GSC_RedDeadRevolver; + lut[CRC::ResidentEvil4] = GSC_ResidentEvil4; + lut[CRC::SacredBlaze] = GSC_SacredBlaze; + lut[CRC::SakuraTaisen] = GSC_SakuraTaisen; + lut[CRC::SakuraWarsSoLongMyLove] = GSC_SakuraWarsSoLongMyLove; + lut[CRC::SengokuBasara] = GSC_SengokuBasara; + lut[CRC::ShadowofRome] = GSC_ShadowofRome; + lut[CRC::ShinOnimusha] = GSC_ShinOnimusha; + lut[CRC::Simple2000Vol114] = GSC_Simple2000Vol114; + lut[CRC::SoulCalibur2] = GSC_SoulCalibur2; + lut[CRC::SoulCalibur3] = GSC_SoulCalibur3; + lut[CRC::Spartan] = GSC_Spartan; + lut[CRC::StarWarsForceUnleashed] = GSC_StarWarsForceUnleashed; + lut[CRC::SteambotChronicles] = GSC_SteambotChronicles; + lut[CRC::TalesOfAbyss] = GSC_TalesOfAbyss; + lut[CRC::TalesOfLegendia] = GSC_TalesOfLegendia; + lut[CRC::TalesofSymphonia] = GSC_TalesofSymphonia; + lut[CRC::Tekken5] = GSC_Tekken5; + lut[CRC::TimeSplitters2] = GSC_TimeSplitters2; + lut[CRC::TombRaiderAnniversary] = GSC_TombRaider; + lut[CRC::TombRaiderLegend] = GSC_TombRaiderLegend; + lut[CRC::TombRaiderUnderworld] = GSC_TombRaiderUnderWorld; + lut[CRC::UltramanFightingEvolution] = GSC_UltramanFightingEvolution; + lut[CRC::UrbanReign] = GSC_UrbanReign; + lut[CRC::WildArms4] = GSC_WildArms4; + lut[CRC::WildArms5] = GSC_WildArms5; + lut[CRC::Yakuza2] = GSC_Yakuza2; + lut[CRC::Yakuza] = GSC_Yakuza; + lut[CRC::ZettaiZetsumeiToshi2] = GSC_ZettaiZetsumeiToshi2; + // Only Aggresive + lut[CRC::FFX2] = GSC_FFX2; + lut[CRC::FFX] = GSC_FFX; + lut[CRC::FFXII] = GSC_FFXII; + lut[CRC::SMTDDS1] = GSC_SMTNocturneDDS<0x203BA820>; + lut[CRC::SMTDDS2] = GSC_SMTNocturneDDS<0x20435BF0>; + lut[CRC::SMTNocturne] = GSC_SMTNocturneDDS<0x2054E870>; + lut[CRC::SoTC] = GSC_SoTC; + lut[CRC::SSX3] = GSC_SSX3; + } + + // Hack that were fixed on openGL + if (Dx_only) { + // Depth + lut[CRC::Bully] = GSC_Bully; + lut[CRC::BullyCC] = GSC_BullyCC; + lut[CRC::GodOfWar2] = GSC_GodOfWar2; + lut[CRC::ICO] = GSC_ICO; + lut[CRC::LordOfTheRingsTwoTowers] = GSC_LordOfTheRingsTwoTowers; + lut[CRC::Okami] = GSC_Okami; + lut[CRC::SimpsonsGame] = GSC_SimpsonsGame; + lut[CRC::SuikodenTactics] = GSC_SuikodenTactics; + lut[CRC::XE3] = GSC_XE3; + + // Not tested but must be fixed with texture shuffle + lut[CRC::BigMuthaTruckers] = GSC_BigMuthaTruckers; + lut[CRC::DemonStone] = GSC_DemonStone; + lut[CRC::CrashNburn] = GSC_CrashNburn; // seem to be a basic depth effect + lut[CRC::LegoBatman] = GSC_LegoBatman; + lut[CRC::OnePieceGrandAdventure] = GSC_OnePieceGrandAdventure; + lut[CRC::OnePieceGrandBattle] = GSC_OnePieceGrandBattle; + lut[CRC::SFEX3] = GSC_SFEX3; + lut[CRC::SpyroEternalNight] = GSC_SpyroEternalNight; + lut[CRC::SpyroNewBeginning] = GSC_SpyroNewBeginning; + lut[CRC::SonicUnleashed] = GSC_SonicUnleashed; + lut[CRC::TenchuFS] = GSC_Tenchu; + lut[CRC::TenchuWoH] = GSC_Tenchu; + + // Those games might requires accurate fbmask + lut[CRC::Sly2] = GSC_Sly2; + lut[CRC::Sly3] = GSC_Sly3; + + // Those games require accurate_colclip (perf) + lut[CRC::CastlevaniaCoD] = GSC_Castlevania; + lut[CRC::CastlevaniaLoI] = GSC_Castlevania; + lut[CRC::GodOfWar] = GSC_GodOfWar; + + // Those games emulate a stencil buffer with the alpha channel of the RT (Slow) + lut[CRC::RadiataStories] = GSC_RadiataStories; + lut[CRC::StarOcean3] = GSC_StarOcean3; + lut[CRC::ValkyrieProfile2] = GSC_ValkyrieProfile2; + + // Deprecated hack could be removed (Cutie) + lut[CRC::Grandia3] = GSC_Grandia3; + + // At least a part of the CRC is fixed with texture shuffle. + // The status of post-processing effect is unknown + lut[CRC::Black] = GSC_Black; + + // Channel Effect + lut[CRC::DeathByDegreesTekkenNinaWilliams] = GSC_DeathByDegreesTekkenNinaWilliams; + lut[CRC::GT3] = GSC_GT3; + lut[CRC::GT4] = GSC_GT4; + lut[CRC::GTConcept] = GSC_GTConcept; + lut[CRC::JamesBondEverythingOrNothing] = GSC_JamesBondEverythingOrNothing; + lut[CRC::MetalGearSolid3] = GSC_MetalGearSolid3; // + accurate blending + lut[CRC::SkyGunner] = GSC_SkyGunner; + lut[CRC::StarWarsBattlefront2] = GSC_StarWarsBattlefront2; + lut[CRC::StarWarsBattlefront] = GSC_StarWarsBattlefront; + lut[CRC::TouristTrophy] = GSC_TouristTrophy; + } + + m_gsc = lut[m_game.title]; + g_crc_region = m_game.region; +} + bool GSState::IsBadFrame(int& skip, int UserHacks_SkipDraw) { GSFrameInfo fi; @@ -2454,166 +2594,10 @@ bool GSState::IsBadFrame(int& skip, int UserHacks_SkipDraw) fi.TPSM = m_context->TEX0.PSM; fi.TZTST = m_context->TEST.ZTST; - static GetSkipCount map[CRC::TitleCount]; - - if (!m_crcinited) - { - m_crcinited = true; - - s_crc_hack_level = theApp.GetConfig("crc_hack_level", 3); - - memset(map, 0, sizeof(map)); - - if (s_crc_hack_level > 1) { - map[CRC::AceCombat4] = GSC_AceCombat4; - map[CRC::AlpineRacer3] = GSC_AlpineRacer3; - map[CRC::BlackHawkDown] = GSC_BlackHawkDown; - map[CRC::BleachBladeBattlers] = GSC_BleachBladeBattlers; - map[CRC::BurnoutDominator] = GSC_Burnout; - map[CRC::BurnoutRevenge] = GSC_Burnout; - map[CRC::BurnoutTakedown] = GSC_Burnout; - map[CRC::CaptainTsubasa] = GSC_CaptainTsubasa; - map[CRC::CrashBandicootWoC] = GSC_CrashBandicootWoC; - map[CRC::DBZBT2] = GSC_DBZBT2; - map[CRC::DBZBT3] = GSC_DBZBT3; - map[CRC::DevilMayCry3] = GSC_DevilMayCry3; - map[CRC::EternalPoison] = GSC_EternalPoison; - map[CRC::EvangelionJo] = GSC_EvangelionJo; - map[CRC::FFVIIDoC] = GSC_FFVIIDoC; - map[CRC::FightingBeautyWulong] = GSC_FightingBeautyWulong; - map[CRC::FinalFightStreetwise] = GSC_FinalFightStreetwise; - map[CRC::FrontMission5] = GSC_FrontMission5; - map[CRC::Genji] = GSC_Genji; - map[CRC::GetaWayBlackMonday] = GSC_GetaWay; - map[CRC::GetaWay] = GSC_GetaWay; - map[CRC::GiTS] = GSC_GiTS; - map[CRC::GodHand] = GSC_GodHand; - map[CRC::GTASanAndreas] = GSC_GTASanAndreas; - map[CRC::HauntingGround] = GSC_HauntingGround; - map[CRC::HeavyMetalThunder] = GSC_HeavyMetalThunder; - map[CRC::HummerBadlands] = GSC_HummerBadlands; - map[CRC::IkkiTousen] = GSC_IkkiTousen; - map[CRC::KnightsOfTheTemple2] = GSC_KnightsOfTheTemple2; - map[CRC::Kunoichi] = GSC_Kunoichi; - map[CRC::LordOfTheRingsThirdAge] = GSC_LordOfTheRingsThirdAge; - map[CRC::Manhunt2] = GSC_Manhunt2; - map[CRC::MidnightClub3] = GSC_MidnightClub3; - map[CRC::NanoBreaker] = GSC_NanoBreaker; - map[CRC::NarutimateAccel] = GSC_NarutimateAccel; - map[CRC::Naruto] = GSC_Naruto; - map[CRC::Oneechanbara2Special] = GSC_Oneechanbara2Special; - map[CRC::Onimusha3] = GSC_Onimusha3; - map[CRC::RedDeadRevolver] = GSC_RedDeadRevolver; - map[CRC::ResidentEvil4] = GSC_ResidentEvil4; - map[CRC::SacredBlaze] = GSC_SacredBlaze; - map[CRC::SakuraTaisen] = GSC_SakuraTaisen; - map[CRC::SakuraWarsSoLongMyLove] = GSC_SakuraWarsSoLongMyLove; - map[CRC::SengokuBasara] = GSC_SengokuBasara; - map[CRC::ShadowofRome] = GSC_ShadowofRome; - map[CRC::ShinOnimusha] = GSC_ShinOnimusha; - map[CRC::Simple2000Vol114] = GSC_Simple2000Vol114; - map[CRC::SoulCalibur2] = GSC_SoulCalibur2; - map[CRC::SoulCalibur3] = GSC_SoulCalibur3; - map[CRC::Spartan] = GSC_Spartan; - map[CRC::StarWarsForceUnleashed] = GSC_StarWarsForceUnleashed; - map[CRC::SteambotChronicles] = GSC_SteambotChronicles; - map[CRC::TalesOfAbyss] = GSC_TalesOfAbyss; - map[CRC::TalesOfLegendia] = GSC_TalesOfLegendia; - map[CRC::TalesofSymphonia] = GSC_TalesofSymphonia; - map[CRC::Tekken5] = GSC_Tekken5; - map[CRC::TimeSplitters2] = GSC_TimeSplitters2; - map[CRC::TombRaiderAnniversary] = GSC_TombRaider; - map[CRC::TombRaiderLegend] = GSC_TombRaiderLegend; - map[CRC::TombRaiderUnderworld] = GSC_TombRaiderUnderWorld; - map[CRC::UltramanFightingEvolution] = GSC_UltramanFightingEvolution; - map[CRC::UrbanReign] = GSC_UrbanReign; - map[CRC::WildArms4] = GSC_WildArms4; - map[CRC::WildArms5] = GSC_WildArms5; - map[CRC::Yakuza2] = GSC_Yakuza2; - map[CRC::Yakuza] = GSC_Yakuza; - map[CRC::ZettaiZetsumeiToshi2] = GSC_ZettaiZetsumeiToshi2; - // Only Aggresive - map[CRC::FFX2] = GSC_FFX2; - map[CRC::FFX] = GSC_FFX; - map[CRC::FFXII] = GSC_FFXII; - map[CRC::SMTDDS1] = GSC_SMTNocturneDDS<0x203BA820>; - map[CRC::SMTDDS2] = GSC_SMTNocturneDDS<0x20435BF0>; - map[CRC::SMTNocturne] = GSC_SMTNocturneDDS<0x2054E870>; - map[CRC::SoTC] = GSC_SoTC; - map[CRC::SSX3] = GSC_SSX3; - } - - // Hack that were fixed on openGL - if (Dx_only) { - // Depth - map[CRC::Bully] = GSC_Bully; - map[CRC::BullyCC] = GSC_BullyCC; - map[CRC::GodOfWar2] = GSC_GodOfWar2; - map[CRC::ICO] = GSC_ICO; - map[CRC::LordOfTheRingsTwoTowers] = GSC_LordOfTheRingsTwoTowers; - map[CRC::Okami] = GSC_Okami; - map[CRC::SimpsonsGame] = GSC_SimpsonsGame; - map[CRC::SuikodenTactics] = GSC_SuikodenTactics; - map[CRC::XE3] = GSC_XE3; - - // Not tested but must be fixed with texture shuffle - map[CRC::BigMuthaTruckers] = GSC_BigMuthaTruckers; - map[CRC::DemonStone] = GSC_DemonStone; - map[CRC::CrashNburn] = GSC_CrashNburn; // seem to be a basic depth effect - map[CRC::LegoBatman] = GSC_LegoBatman; - map[CRC::OnePieceGrandAdventure] = GSC_OnePieceGrandAdventure; - map[CRC::OnePieceGrandBattle] = GSC_OnePieceGrandBattle; - map[CRC::SFEX3] = GSC_SFEX3; - map[CRC::SpyroEternalNight] = GSC_SpyroEternalNight; - map[CRC::SpyroNewBeginning] = GSC_SpyroNewBeginning; - map[CRC::SonicUnleashed] = GSC_SonicUnleashed; - map[CRC::TenchuFS] = GSC_Tenchu; - map[CRC::TenchuWoH] = GSC_Tenchu; - - // Those games might requires accurate fbmask - map[CRC::Sly2] = GSC_Sly2; - map[CRC::Sly3] = GSC_Sly3; - - // Those games require accurate_colclip (perf) - map[CRC::CastlevaniaCoD] = GSC_Castlevania; - map[CRC::CastlevaniaLoI] = GSC_Castlevania; - map[CRC::GodOfWar] = GSC_GodOfWar; - - // Those games emulate a stencil buffer with the alpha channel of the RT (Slow) - map[CRC::RadiataStories] = GSC_RadiataStories; - map[CRC::StarOcean3] = GSC_StarOcean3; - map[CRC::ValkyrieProfile2] = GSC_ValkyrieProfile2; - - // Deprecated hack could be removed (Cutie) - map[CRC::Grandia3] = GSC_Grandia3; - - // At least a part of the CRC is fixed with texture shuffle. - // The status of post-processing effect is unknown - map[CRC::Black] = GSC_Black; - - // Channel Effect - map[CRC::DeathByDegreesTekkenNinaWilliams] = GSC_DeathByDegreesTekkenNinaWilliams; - map[CRC::GT3] = GSC_GT3; - map[CRC::GT4] = GSC_GT4; - map[CRC::GTConcept] = GSC_GTConcept; - map[CRC::JamesBondEverythingOrNothing] = GSC_JamesBondEverythingOrNothing; - map[CRC::MetalGearSolid3] = GSC_MetalGearSolid3; // + accurate blending - map[CRC::SkyGunner] = GSC_SkyGunner; - map[CRC::StarWarsBattlefront2] = GSC_StarWarsBattlefront2; - map[CRC::StarWarsBattlefront] = GSC_StarWarsBattlefront; - map[CRC::TouristTrophy] = GSC_TouristTrophy; - } - } - - // TODO: just set gsc in SetGameCRC once - - GetSkipCount gsc = map[m_game.title]; - g_crc_region = m_game.region; - #ifdef ENABLE_DYNAMIC_CRC_HACK bool res=false; if(IsInvokedDynamicCrcHack(fi, skip, g_crc_region, res, m_crc)){ if( !res ) return false; } else #endif - if(gsc && !gsc(fi, skip)) + if(m_gsc && !m_gsc(fi, skip)) { return false; } diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index 63ac007ff0..c7f5daabf6 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -33,6 +33,7 @@ GSState::GSState() , m_irq(NULL) , m_path3hack(0) , m_init_read_fifo_supported(false) + , m_gsc(NULL) , m_q(1.0f) , m_texflush(true) , m_vt(this) @@ -40,7 +41,6 @@ GSState::GSState() , m_crc(0) , m_options(0) , m_frameskip(0) - , m_crcinited(false) { m_nativeres = theApp.GetConfig("upscale_multiplier",1) == 1; m_mipmap = !!theApp.GetConfig("mipmap", 1); @@ -2350,6 +2350,7 @@ void GSState::SetGameCRC(uint32 crc, int options) m_crc = crc; m_options = options; m_game = CRC::Lookup(m_crc_hack_level ? crc : 0); + SetupCrcHack(); } // @@ -2367,7 +2368,7 @@ void GSState::UpdateScissor() m_ofxy = m_context->scissor.ofxy; } -void GSState::UpdateVertexKick() +void GSState::UpdateVertexKick() { if(m_frameskip) return; diff --git a/plugins/GSdx/GSState.h b/plugins/GSdx/GSState.h index efd34f7c19..c91eea3ae4 100644 --- a/plugins/GSdx/GSState.h +++ b/plugins/GSdx/GSState.h @@ -35,6 +35,19 @@ #include "GSAlignedClass.h" #include "GSDump.h" +struct GSFrameInfo +{ + uint32 FBP; + uint32 FPSM; + uint32 FBMSK; + uint32 TBP0; + uint32 TPSM; + uint32 TZTST; + bool TME; +}; + +typedef bool (*GetSkipCount)(const GSFrameInfo& fi, int& skip); + class GSState : public GSAlignedClass<32> { // RESTRICT prevents multiple loads of the same part of the register when accessing its bitfields (the compiler is happy to know that memory writes in-between will not go there) @@ -141,18 +154,20 @@ class GSState : public GSAlignedClass<32> protected: bool IsBadFrame(int& skip, int UserHacks_SkipDraw); + void SetupCrcHack(); int UserHacks_WildHack; bool isPackedUV_HackFlag; int m_crc_hack_level; + GetSkipCount m_gsc; GSVertex m_v; float m_q; GSVector4i m_scissor; GSVector4i m_ofxy; bool m_texflush; - - struct + + struct { GSVertex* buff; size_t head, tail, next, maxcount; // head: first vertex, tail: last vertex + 1, next: last indexed + 1 @@ -160,7 +175,7 @@ protected: uint64 xy[4]; } m_vertex; - struct + struct { uint32* buff; size_t tail; @@ -173,7 +188,7 @@ protected: void GrowVertexBuffer(); - template + template void VertexKick(uint32 skip); // following functions need m_vt to be initialized @@ -199,7 +214,6 @@ public: GSDump m_dump; int m_options; int m_frameskip; - bool m_crcinited; bool m_framelimit; bool m_NTSC_Saturation; bool m_nativeres; From c8dddfed06222b8fbec6a15bb3b7d115fb899840 Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Thu, 5 May 2016 16:22:14 +0200 Subject: [PATCH 4/7] gsdx hack: move m_skip and m_userhacks_skipdraw to GSState level Avoid to push argument to call IsBadFrame --- plugins/GSdx/GSHwHack.cpp | 14 +++++++------- plugins/GSdx/GSRendererHW.cpp | 4 +--- plugins/GSdx/GSRendererHW.h | 2 -- plugins/GSdx/GSState.cpp | 2 ++ plugins/GSdx/GSState.h | 4 +++- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/plugins/GSdx/GSHwHack.cpp b/plugins/GSdx/GSHwHack.cpp index cef3a96387..42870564e9 100644 --- a/plugins/GSdx/GSHwHack.cpp +++ b/plugins/GSdx/GSHwHack.cpp @@ -2582,7 +2582,7 @@ void GSState::SetupCrcHack() g_crc_region = m_game.region; } -bool GSState::IsBadFrame(int& skip, int UserHacks_SkipDraw) +bool GSState::IsBadFrame() { GSFrameInfo fi; @@ -2595,14 +2595,14 @@ bool GSState::IsBadFrame(int& skip, int UserHacks_SkipDraw) fi.TZTST = m_context->TEST.ZTST; #ifdef ENABLE_DYNAMIC_CRC_HACK - bool res=false; if(IsInvokedDynamicCrcHack(fi, skip, g_crc_region, res, m_crc)){ if( !res ) return false; } else + bool res=false; if(IsInvokedDynamicCrcHack(fi, m_skip, g_crc_region, res, m_crc)){ if( !res ) return false; } else #endif - if(m_gsc && !m_gsc(fi, skip)) + if(m_gsc && !m_gsc(fi, m_skip)) { return false; } - if(skip == 0 && (UserHacks_SkipDraw > 0) ) + if(m_skip == 0 && (m_userhacks_skipdraw > 0) ) { if(fi.TME) { @@ -2610,14 +2610,14 @@ bool GSState::IsBadFrame(int& skip, int UserHacks_SkipDraw) // General, often problematic post processing if (GSLocalMemory::m_psm[fi.TPSM].depth || GSUtil::HasSharedBits(fi.FBP, fi.FPSM, fi.TBP0, fi.TPSM)) { - skip = UserHacks_SkipDraw; + m_skip = m_userhacks_skipdraw; } } } - if(skip > 0) + if(m_skip > 0) { - skip--; + m_skip--; return true; } diff --git a/plugins/GSdx/GSRendererHW.cpp b/plugins/GSdx/GSRendererHW.cpp index 76b72683fb..453bbba238 100644 --- a/plugins/GSdx/GSRendererHW.cpp +++ b/plugins/GSdx/GSRendererHW.cpp @@ -25,7 +25,6 @@ GSRendererHW::GSRendererHW(GSTextureCache* tc) : m_width(1280) , m_height(1024) - , m_skip(0) , m_reset(false) , m_upscale_multiplier(1) , m_tc(tc) @@ -33,7 +32,6 @@ GSRendererHW::GSRendererHW(GSTextureCache* tc) , m_double_downscale(false) { m_upscale_multiplier = theApp.GetConfig("upscale_multiplier", 1); - m_userhacks_skipdraw = !!theApp.GetConfig("UserHacks", 0) ? theApp.GetConfig("UserHacks_SkipDraw", 0) : 0; m_userhacks_align_sprite_X = !!theApp.GetConfig("UserHacks_align_sprite_X", 0) && !!theApp.GetConfig("UserHacks", 0); m_userhacks_round_sprite_offset = !!theApp.GetConfig("UserHacks", 0) ? theApp.GetConfig("UserHacks_round_sprite_offset", 0) : 0; m_userhacks_disable_gs_mem_clear = theApp.GetConfig("UserHacks_DisableGsMemClear", 0) && theApp.GetConfig("UserHacks", 0); @@ -353,7 +351,7 @@ void GSRendererHW::RoundSpriteOffset() void GSRendererHW::Draw() { - if(m_dev->IsLost() || GSRenderer::IsBadFrame(m_skip, m_userhacks_skipdraw)) { + if(m_dev->IsLost() || IsBadFrame()) { GL_INS("Warning skipping a draw call (%d)", s_n); s_n += 3; // Keep it sync with SW renderer return; diff --git a/plugins/GSdx/GSRendererHW.h b/plugins/GSdx/GSRendererHW.h index 24a0c0e6ab..fa2454c7ba 100644 --- a/plugins/GSdx/GSRendererHW.h +++ b/plugins/GSdx/GSRendererHW.h @@ -32,10 +32,8 @@ class GSRendererHW : public GSRenderer private: int m_width; int m_height; - int m_skip; bool m_reset; int m_upscale_multiplier; - int m_userhacks_skipdraw; bool m_userhacks_align_sprite_X; bool m_userhacks_disable_gs_mem_clear; diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index c7f5daabf6..64105dd982 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -34,6 +34,7 @@ GSState::GSState() , m_path3hack(0) , m_init_read_fifo_supported(false) , m_gsc(NULL) + , m_skip(0) , m_q(1.0f) , m_texflush(true) , m_vt(this) @@ -45,6 +46,7 @@ GSState::GSState() m_nativeres = theApp.GetConfig("upscale_multiplier",1) == 1; m_mipmap = !!theApp.GetConfig("mipmap", 1); m_NTSC_Saturation = !!theApp.GetConfig("NTSC_Saturation", true); + m_userhacks_skipdraw = !!theApp.GetConfig("UserHacks", 0) ? theApp.GetConfig("UserHacks_SkipDraw", 0) : 0; s_n = 0; s_dump = !!theApp.GetConfig("dump", 0); diff --git a/plugins/GSdx/GSState.h b/plugins/GSdx/GSState.h index c91eea3ae4..05593451c3 100644 --- a/plugins/GSdx/GSState.h +++ b/plugins/GSdx/GSState.h @@ -153,13 +153,15 @@ class GSState : public GSAlignedClass<32> } m_tr; protected: - bool IsBadFrame(int& skip, int UserHacks_SkipDraw); + bool IsBadFrame(); void SetupCrcHack(); int UserHacks_WildHack; bool isPackedUV_HackFlag; int m_crc_hack_level; GetSkipCount m_gsc; + int m_skip; + int m_userhacks_skipdraw; GSVertex m_v; float m_q; From 37c7fa7663625292ae1ac218442c63a0dccbefcb Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Thu, 5 May 2016 16:43:02 +0200 Subject: [PATCH 5/7] gsdx: add draw exception (OOM and Recoverable) The exception will free the unused (but allocated) texture aka the emergency break ;) Recoverable could be useful for unsupported draw call --- plugins/GSdx/GSDevice.cpp | 11 +++++++++++ plugins/GSdx/GSDevice.h | 1 + plugins/GSdx/GSRenderer.cpp | 5 +++++ plugins/GSdx/GSRenderer.h | 2 ++ plugins/GSdx/GSState.cpp | 10 +++++++++- plugins/GSdx/GSState.h | 1 + plugins/GSdx/GSdx.h | 1 + 7 files changed, 30 insertions(+), 1 deletion(-) diff --git a/plugins/GSdx/GSDevice.cpp b/plugins/GSdx/GSDevice.cpp index c88a242a04..94c2066fab 100644 --- a/plugins/GSdx/GSDevice.cpp +++ b/plugins/GSdx/GSDevice.cpp @@ -202,6 +202,17 @@ void GSDevice::AgePool() } } +void GSDevice::PurgePool() +{ + // OOM emergency. Let's free this useless pool + while(m_pool.size() > 0) + { + delete m_pool.back(); + + m_pool.pop_back(); + } +} + GSTexture* GSDevice::CreateRenderTarget(int w, int h, bool msaa, int format) { return FetchSurface(GSTexture::RenderTarget, w, h, msaa, format); diff --git a/plugins/GSdx/GSDevice.h b/plugins/GSdx/GSDevice.h index 186d88b751..974cdbfda4 100644 --- a/plugins/GSdx/GSDevice.h +++ b/plugins/GSdx/GSDevice.h @@ -194,6 +194,7 @@ public: bool IsRBSwapped() {return m_rbswapped;} void AgePool(); + void PurgePool(); virtual void PrintMemoryUsage(); }; diff --git a/plugins/GSdx/GSRenderer.cpp b/plugins/GSdx/GSRenderer.cpp index 5e3d1d3007..11323a1edd 100644 --- a/plugins/GSdx/GSRenderer.cpp +++ b/plugins/GSdx/GSRenderer.cpp @@ -645,3 +645,8 @@ void GSRenderer::KeyEvent(GSKeyEventData* e) } #endif } + +void GSRenderer::PurgePool() +{ + m_dev->PurgePool(); +} diff --git a/plugins/GSdx/GSRenderer.h b/plugins/GSdx/GSRenderer.h index 671f014802..78309b2d40 100644 --- a/plugins/GSdx/GSRenderer.h +++ b/plugins/GSdx/GSRenderer.h @@ -79,6 +79,8 @@ public: virtual bool BeginCapture(); virtual void EndCapture(); + void PurgePool(); + public: std::mutex m_pGSsetTitle_Crit; diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index 64105dd982..bdc80a04d0 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -1475,7 +1475,15 @@ void GSState::FlushPrim() m_vt.Update(m_vertex.buff, m_index.buff, m_index.tail, GSUtil::GetPrimClass(PRIM->PRIM)); - Draw(); + try { + Draw(); + } catch (GSDXRecoverableError&) { + // could be an unsupported draw call + } catch (GSDXErrorOOM&) { + // Texture Out Of Memory + PurgePool(); + fprintf(stderr, "GSDX OUT OF MEMORY\n"); + } m_perfmon.Put(GSPerfMon::Draw, 1); m_perfmon.Put(GSPerfMon::Prim, m_index.tail / GSUtil::GetVertexCount(PRIM->PRIM)); diff --git a/plugins/GSdx/GSState.h b/plugins/GSdx/GSState.h index 05593451c3..ffe74645d6 100644 --- a/plugins/GSdx/GSState.h +++ b/plugins/GSdx/GSState.h @@ -249,6 +249,7 @@ public: virtual void FlushPrim(); virtual void FlushWrite(); virtual void Draw() = 0; + virtual void PurgePool() = 0; virtual void InvalidateVideoMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r) {} virtual void InvalidateLocalMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r, bool clut = false) {} diff --git a/plugins/GSdx/GSdx.h b/plugins/GSdx/GSdx.h index 5ea4201c4c..6ddaf2cb9e 100644 --- a/plugins/GSdx/GSdx.h +++ b/plugins/GSdx/GSdx.h @@ -79,5 +79,6 @@ public: struct GSDXError {}; struct GSDXRecoverableError : GSDXError {}; +struct GSDXErrorOOM : GSDXError {}; extern GSdxApp theApp; From d58b71688b239ecb5cf30cfe243192eb509b2883 Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Thu, 5 May 2016 17:42:22 +0200 Subject: [PATCH 6/7] gsdx debug: auto GL_POP Nicer and exception safe V2: miss definition of vs/ps --- plugins/GSdx/GSDevice.cpp | 2 - plugins/GSdx/GSDeviceOGL.cpp | 294 +++++++++++++---------------- plugins/GSdx/GSRenderer.cpp | 2 - plugins/GSdx/GSRendererHW.cpp | 9 - plugins/GSdx/GSRendererOGL.cpp | 12 +- plugins/GSdx/GSTextureCacheOGL.cpp | 2 - plugins/GSdx/GSTextureOGL.cpp | 4 +- plugins/GSdx/stdafx.h | 10 +- 8 files changed, 142 insertions(+), 193 deletions(-) diff --git a/plugins/GSdx/GSDevice.cpp b/plugins/GSdx/GSDevice.cpp index 94c2066fab..e93cd210c3 100644 --- a/plugins/GSdx/GSDevice.cpp +++ b/plugins/GSdx/GSDevice.cpp @@ -121,8 +121,6 @@ void GSDevice::Present(const GSVector4i& r, int shader) } Flip(); - - GL_POP(); } void GSDevice::Present(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, int shader) diff --git a/plugins/GSdx/GSDeviceOGL.cpp b/plugins/GSdx/GSDeviceOGL.cpp index c0eef66ee5..23ffca7c06 100644 --- a/plugins/GSdx/GSDeviceOGL.cpp +++ b/plugins/GSdx/GSDeviceOGL.cpp @@ -133,8 +133,6 @@ GSDeviceOGL::~GSDeviceOGL() // Must be done after the destruction of all shader/program objects delete m_shader; m_shader = NULL; - - GL_POP(); } GSTexture* GSDeviceOGL::CreateSurface(int type, int w, int h, bool msaa, int fmt) @@ -157,7 +155,6 @@ GSTexture* GSDeviceOGL::CreateSurface(int type, int w, int h, bool msaa, int fmt break; } - GL_POP(); return t; } @@ -197,163 +194,165 @@ bool GSDeviceOGL::Create(GSWnd* wnd) // **************************************************************** // Various object // **************************************************************** - GL_PUSH("GSDeviceOGL::Various"); + { + GL_PUSH("GSDeviceOGL::Various"); - m_shader = new GSShaderOGL(!!theApp.GetConfig("debug_glsl_shader", 0)); + m_shader = new GSShaderOGL(!!theApp.GetConfig("debug_glsl_shader", 0)); - glGenFramebuffers(1, &m_fbo); - // Always write to the first buffer - OMSetFBO(m_fbo); - GLenum target[1] = {GL_COLOR_ATTACHMENT0}; - glDrawBuffers(1, target); - OMSetFBO(0); + glGenFramebuffers(1, &m_fbo); + // Always write to the first buffer + OMSetFBO(m_fbo); + GLenum target[1] = {GL_COLOR_ATTACHMENT0}; + glDrawBuffers(1, target); + OMSetFBO(0); - glGenFramebuffers(1, &m_fbo_read); - // Always read from the first buffer - glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read); - glReadBuffer(GL_COLOR_ATTACHMENT0); - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - - GL_POP(); + glGenFramebuffers(1, &m_fbo_read); + // Always read from the first buffer + glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + } // **************************************************************** // Vertex buffer state // **************************************************************** - GL_PUSH("GSDeviceOGL::Vertex Buffer"); - - ASSERT(sizeof(GSVertexPT1) == sizeof(GSVertex)); - GSInputLayoutOGL il_convert[] = { - {2 , GL_FLOAT , GL_FALSE , sizeof(GSVertexPT1) , (const GLvoid*)(0) } , - {2 , GL_FLOAT , GL_FALSE , sizeof(GSVertexPT1) , (const GLvoid*)(16) } , - {4 , GL_UNSIGNED_BYTE , GL_FALSE , sizeof(GSVertex) , (const GLvoid*)(8) } , - {1 , GL_FLOAT , GL_FALSE , sizeof(GSVertex) , (const GLvoid*)(12) } , - {2 , GL_UNSIGNED_SHORT , GL_FALSE , sizeof(GSVertex) , (const GLvoid*)(16) } , - {1 , GL_UNSIGNED_INT , GL_FALSE , sizeof(GSVertex) , (const GLvoid*)(20) } , - {2 , GL_UNSIGNED_SHORT , GL_FALSE , sizeof(GSVertex) , (const GLvoid*)(24) } , - {4 , GL_UNSIGNED_BYTE , GL_TRUE , sizeof(GSVertex) , (const GLvoid*)(28) } , // Only 1 byte is useful but hardware unit only support 4B - }; - m_va = new GSVertexBufferStateOGL(il_convert, countof(il_convert)); + GL_PUSH("GSDeviceOGL::Vertex Buffer"); + + ASSERT(sizeof(GSVertexPT1) == sizeof(GSVertex)); + GSInputLayoutOGL il_convert[] = + { + {2 , GL_FLOAT , GL_FALSE , sizeof(GSVertexPT1) , (const GLvoid*)(0) } , + {2 , GL_FLOAT , GL_FALSE , sizeof(GSVertexPT1) , (const GLvoid*)(16) } , + {4 , GL_UNSIGNED_BYTE , GL_FALSE , sizeof(GSVertex) , (const GLvoid*)(8) } , + {1 , GL_FLOAT , GL_FALSE , sizeof(GSVertex) , (const GLvoid*)(12) } , + {2 , GL_UNSIGNED_SHORT , GL_FALSE , sizeof(GSVertex) , (const GLvoid*)(16) } , + {1 , GL_UNSIGNED_INT , GL_FALSE , sizeof(GSVertex) , (const GLvoid*)(20) } , + {2 , GL_UNSIGNED_SHORT , GL_FALSE , sizeof(GSVertex) , (const GLvoid*)(24) } , + {4 , GL_UNSIGNED_BYTE , GL_TRUE , sizeof(GSVertex) , (const GLvoid*)(28) } , // Only 1 byte is useful but hardware unit only support 4B + }; + m_va = new GSVertexBufferStateOGL(il_convert, countof(il_convert)); + } - GL_POP(); // **************************************************************** // Pre Generate the different sampler object // **************************************************************** - GL_PUSH("GSDeviceOGL::Sampler"); + { + GL_PUSH("GSDeviceOGL::Sampler"); - for (uint32 key = 0; key < countof(m_ps_ss); key++) { - m_ps_ss[key] = CreateSampler(PSSamplerSelector(key)); + for (uint32 key = 0; key < countof(m_ps_ss); key++) { + m_ps_ss[key] = CreateSampler(PSSamplerSelector(key)); + } } - GL_POP(); - // **************************************************************** // convert // **************************************************************** - GL_PUSH("GSDeviceOGL::Convert"); - - m_convert.cb = new GSUniformBufferOGL(g_convert_index, sizeof(ConvertConstantBuffer)); - // Upload once and forget about it - ConvertConstantBuffer cb; - cb.ScalingFactor = GSVector4i(theApp.GetConfig("upscale_multiplier", 1)); - m_convert.cb->upload(&cb); - - GLuint vs = m_shader->Compile("convert.glsl", "vs_main", GL_VERTEX_SHADER, convert_glsl); + GLuint vs = 0; GLuint ps = 0; + { + GL_PUSH("GSDeviceOGL::Convert"); - m_convert.vs = vs; - for(size_t i = 0; i < countof(m_convert.ps); i++) { - ps = m_shader->Compile("convert.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, convert_glsl); - m_convert.ps[i] = m_shader->LinkPipeline(vs, 0, ps); + m_convert.cb = new GSUniformBufferOGL(g_convert_index, sizeof(ConvertConstantBuffer)); + // Upload once and forget about it + ConvertConstantBuffer cb; + cb.ScalingFactor = GSVector4i(theApp.GetConfig("upscale_multiplier", 1)); + m_convert.cb->upload(&cb); + + vs = m_shader->Compile("convert.glsl", "vs_main", GL_VERTEX_SHADER, convert_glsl); + + m_convert.vs = vs; + for(size_t i = 0; i < countof(m_convert.ps); i++) { + ps = m_shader->Compile("convert.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, convert_glsl); + m_convert.ps[i] = m_shader->LinkPipeline(vs, 0, ps); + } + + PSSamplerSelector point; + m_convert.pt = GetSamplerID(point); + + PSSamplerSelector bilinear; + bilinear.ltf = true; + m_convert.ln = GetSamplerID(bilinear); + + m_convert.dss = new GSDepthStencilOGL(); + m_convert.dss_write = new GSDepthStencilOGL(); + m_convert.dss_write->EnableDepth(); + m_convert.dss_write->SetDepth(GL_ALWAYS, true); } - PSSamplerSelector point; - m_convert.pt = GetSamplerID(point); - - PSSamplerSelector bilinear; - bilinear.ltf = true; - m_convert.ln = GetSamplerID(bilinear); - - m_convert.dss = new GSDepthStencilOGL(); - m_convert.dss_write = new GSDepthStencilOGL(); - m_convert.dss_write->EnableDepth(); - m_convert.dss_write->SetDepth(GL_ALWAYS, true); - - GL_POP(); - // **************************************************************** // merge // **************************************************************** - GL_PUSH("GSDeviceOGL::Merge"); + { + GL_PUSH("GSDeviceOGL::Merge"); - m_merge_obj.cb = new GSUniformBufferOGL(g_merge_cb_index, sizeof(MergeConstantBuffer)); + m_merge_obj.cb = new GSUniformBufferOGL(g_merge_cb_index, sizeof(MergeConstantBuffer)); - for(size_t i = 0; i < countof(m_merge_obj.ps); i++) { - ps = m_shader->Compile("merge.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, merge_glsl); - m_merge_obj.ps[i] = m_shader->LinkPipeline(vs, 0, ps); + for(size_t i = 0; i < countof(m_merge_obj.ps); i++) { + ps = m_shader->Compile("merge.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, merge_glsl); + m_merge_obj.ps[i] = m_shader->LinkPipeline(vs, 0, ps); + } } - GL_POP(); - // **************************************************************** // interlace // **************************************************************** - GL_PUSH("GSDeviceOGL::Interlace"); + { + GL_PUSH("GSDeviceOGL::Interlace"); - m_interlace.cb = new GSUniformBufferOGL(g_interlace_cb_index, sizeof(InterlaceConstantBuffer)); + m_interlace.cb = new GSUniformBufferOGL(g_interlace_cb_index, sizeof(InterlaceConstantBuffer)); - for(size_t i = 0; i < countof(m_interlace.ps); i++) { - ps = m_shader->Compile("interlace.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, interlace_glsl); - m_interlace.ps[i] = m_shader->LinkPipeline(vs, 0, ps); + for(size_t i = 0; i < countof(m_interlace.ps); i++) { + ps = m_shader->Compile("interlace.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, interlace_glsl); + m_interlace.ps[i] = m_shader->LinkPipeline(vs, 0, ps); + } } - GL_POP(); - // **************************************************************** // Shade boost // **************************************************************** - GL_PUSH("GSDeviceOGL::Shadeboost"); + { + GL_PUSH("GSDeviceOGL::Shadeboost"); - int ShadeBoost_Contrast = theApp.GetConfig("ShadeBoost_Contrast", 50); - int ShadeBoost_Brightness = theApp.GetConfig("ShadeBoost_Brightness", 50); - int ShadeBoost_Saturation = theApp.GetConfig("ShadeBoost_Saturation", 50); - std::string shade_macro = format("#define SB_SATURATION %d.0\n", ShadeBoost_Saturation) - + format("#define SB_BRIGHTNESS %d.0\n", ShadeBoost_Brightness) - + format("#define SB_CONTRAST %d.0\n", ShadeBoost_Contrast); + int ShadeBoost_Contrast = theApp.GetConfig("ShadeBoost_Contrast", 50); + int ShadeBoost_Brightness = theApp.GetConfig("ShadeBoost_Brightness", 50); + int ShadeBoost_Saturation = theApp.GetConfig("ShadeBoost_Saturation", 50); + std::string shade_macro = format("#define SB_SATURATION %d.0\n", ShadeBoost_Saturation) + + format("#define SB_BRIGHTNESS %d.0\n", ShadeBoost_Brightness) + + format("#define SB_CONTRAST %d.0\n", ShadeBoost_Contrast); - ps = m_shader->Compile("shadeboost.glsl", "ps_main", GL_FRAGMENT_SHADER, shadeboost_glsl, shade_macro); - m_shadeboost.ps = m_shader->LinkPipeline(vs, 0, ps); - - GL_POP(); + ps = m_shader->Compile("shadeboost.glsl", "ps_main", GL_FRAGMENT_SHADER, shadeboost_glsl, shade_macro); + m_shadeboost.ps = m_shader->LinkPipeline(vs, 0, ps); + } // **************************************************************** // rasterization configuration // **************************************************************** - GL_PUSH("GSDeviceOGL::Rasterization"); + { + GL_PUSH("GSDeviceOGL::Rasterization"); #ifdef ONLY_LINES - glLineWidth(5.0); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glLineWidth(5.0); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); #else - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); #endif - glDisable(GL_CULL_FACE); - glEnable(GL_SCISSOR_TEST); - glDisable(GL_MULTISAMPLE); - glDisable(GL_DITHER); // Honestly I don't know! - - GL_POP(); + glDisable(GL_CULL_FACE); + glEnable(GL_SCISSOR_TEST); + glDisable(GL_MULTISAMPLE); + glDisable(GL_DITHER); // Honestly I don't know! + } // **************************************************************** // DATE // **************************************************************** - GL_PUSH("GSDeviceOGL::Date"); + { + GL_PUSH("GSDeviceOGL::Date"); - m_date.dss = new GSDepthStencilOGL(); - m_date.dss->EnableStencil(); - m_date.dss->SetStencil(GL_ALWAYS, GL_REPLACE); - - GL_POP(); + m_date.dss = new GSDepthStencilOGL(); + m_date.dss->EnableStencil(); + m_date.dss->SetStencil(GL_ALWAYS, GL_REPLACE); + } // **************************************************************** // Use DX coordinate convention @@ -370,28 +369,21 @@ bool GSDeviceOGL::Create(GSWnd* wnd) // **************************************************************** // HW renderer shader // **************************************************************** - GL_PUSH("GSDeviceOGL::CreateTextureFX"); - CreateTextureFX(); - GL_POP(); - // **************************************************************** // Pbo Pool allocation // **************************************************************** - GL_PUSH("GSDeviceOGL::PBO"); + { + GL_PUSH("GSDeviceOGL::PBO"); - // Mesa seems to use it to compute the row length. In our case, we are - // tightly packed so don't bother with this parameter and set it to the - // minimum alignment (1 byte) - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + // Mesa seems to use it to compute the row length. In our case, we are + // tightly packed so don't bother with this parameter and set it to the + // minimum alignment (1 byte) + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - PboPool::Init(); - - GL_POP(); - - // Done ! - GL_POP(); + PboPool::Init(); + } // **************************************************************** // Finish window setup and backbuffer @@ -414,6 +406,8 @@ bool GSDeviceOGL::Create(GSWnd* wnd) void GSDeviceOGL::CreateTextureFX() { + GL_PUSH("GSDeviceOGL::CreateTextureFX"); + m_vs_cb = new GSUniformBufferOGL(g_vs_cb_index, sizeof(VSConstantBuffer)); m_ps_cb = new GSUniformBufferOGL(g_ps_cb_index, sizeof(PSConstantBuffer)); @@ -423,27 +417,27 @@ void GSDeviceOGL::CreateTextureFX() // Pre compile all Geometry & Vertex Shader // It might cost a seconds at startup but it would reduce benchmark pollution - GL_PUSH("Compile GS"); + { + GL_PUSH("Compile GS"); - for (uint32 key = 0; key < countof(m_gs); key++) { - GSSelector sel(key); - if (sel.point == sel.sprite) - m_gs[key] = 0; - else - m_gs[key] = CompileGS(GSSelector(key)); + for (uint32 key = 0; key < countof(m_gs); key++) { + GSSelector sel(key); + if (sel.point == sel.sprite) + m_gs[key] = 0; + else + m_gs[key] = CompileGS(GSSelector(key)); + } } - GL_POP(); + { + GL_PUSH("Compile VS"); - GL_PUSH("Compile VS"); - - for (uint32 key = 0; key < countof(m_vs); key++) { - VSSelector sel(key); - m_vs[key] = CompileVS(sel); + for (uint32 key = 0; key < countof(m_vs); key++) { + VSSelector sel(key); + m_vs[key] = CompileVS(sel); + } } - GL_POP(); - // Enable all bits for stencil operations. Technically 1 bit is // enough but buffer is polluted with noise. Clear will be limited // to the mask. @@ -556,8 +550,6 @@ void GSDeviceOGL::ClearRenderTarget(GSTexture* t, const GSVector4& c) glEnable(GL_SCISSOR_TEST); T->WasCleaned(); - - GL_POP(); } void GSDeviceOGL::ClearRenderTarget(GSTexture* t, uint32 c) @@ -598,8 +590,6 @@ void GSDeviceOGL::ClearRenderTarget_i(GSTexture* t, int32 c) if (GLState::blend) { glEnable(GL_BLEND); } - - GL_POP(); } void GSDeviceOGL::ClearDepth(GSTexture* t, float c) @@ -623,8 +613,6 @@ void GSDeviceOGL::ClearDepth(GSTexture* t, float c) glDepthMask(false); } glEnable(GL_SCISSOR_TEST); - - GL_POP(); } void GSDeviceOGL::ClearStencil(GSTexture* t, uint8 c) @@ -642,8 +630,6 @@ void GSDeviceOGL::ClearStencil(GSTexture* t, uint8 c) GLint color = c; glClearBufferiv(GL_STENCIL, 0, &color); - - GL_POP(); } GLuint GSDeviceOGL::CreateSampler(PSSamplerSelector sel) @@ -683,7 +669,6 @@ GLuint GSDeviceOGL::CreateSampler(bool bilinear, bool tau, bool tav, bool aniso) if (GLLoader::found_GL_EXT_texture_filter_anisotropic && anisotropy && aniso) glSamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)anisotropy); - GL_POP(); return sampler; } @@ -1036,8 +1021,6 @@ void GSDeviceOGL::CopyRectConv(GSTexture* sTex, GSTexture* dTex, const GSVector4 glCopyTextureSubImage2D(did, GL_TEX_LEVEL_0, r.x, r.y, r.x, r.y, r.width(), r.height()); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - - GL_POP(); } // Copy a sub part of a texture into another @@ -1057,8 +1040,6 @@ void GSDeviceOGL::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r did, GL_TEXTURE_2D, 0, 0, 0, 0, r.width(), r.height(), 1); - - GL_POP(); } void GSDeviceOGL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, int shader, bool linear) @@ -1172,8 +1153,6 @@ void GSDeviceOGL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture // ************************************ EndScene(); - - GL_POP(); } void GSDeviceOGL::DoMerge(GSTexture* sTex[2], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, bool slbg, bool mmod, const GSVector4& c) @@ -1196,8 +1175,6 @@ void GSDeviceOGL::DoMerge(GSTexture* sTex[2], GSVector4* sRect, GSTexture* dTex, StretchRect(sTex[0], sRect[0], dTex, dRect[0], m_merge_obj.ps[mmod ? 1 : 0], m_MERGE_BLEND); } - - GL_POP(); } void GSDeviceOGL::DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset) @@ -1220,8 +1197,6 @@ void GSDeviceOGL::DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool m_interlace.cb->upload(&cb); StretchRect(sTex, sRect, dTex, dRect, m_interlace.ps[shader], linear); - - GL_POP(); } void GSDeviceOGL::DoFXAA(GSTexture* sTex, GSTexture* dTex) @@ -1248,8 +1223,6 @@ void GSDeviceOGL::DoFXAA(GSTexture* sTex, GSTexture* dTex) GSVector4 dRect(0, 0, s.x, s.y); StretchRect(sTex, sRect, dTex, dRect, m_fxaa.ps, true); - - GL_POP(); } void GSDeviceOGL::DoExternalFX(GSTexture* sTex, GSTexture* dTex) @@ -1302,8 +1275,6 @@ void GSDeviceOGL::DoExternalFX(GSTexture* sTex, GSTexture* dTex) m_shaderfx.cb->upload(&cb); StretchRect(sTex, sRect, dTex, dRect, m_shaderfx.ps, true); - - GL_POP(); } void GSDeviceOGL::DoShadeBoost(GSTexture* sTex, GSTexture* dTex) @@ -1318,8 +1289,6 @@ void GSDeviceOGL::DoShadeBoost(GSTexture* sTex, GSTexture* dTex) GSVector4 dRect(0, 0, s.x, s.y); StretchRect(sTex, sRect, dTex, dRect, m_shadeboost.ps, true); - - GL_POP(); } void GSDeviceOGL::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vertices, bool datm) @@ -1360,8 +1329,6 @@ void GSDeviceOGL::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* ver } EndScene(); - - GL_POP(); } void GSDeviceOGL::EndScene() @@ -1576,7 +1543,6 @@ void GSDeviceOGL::SetupCB(const VSConstantBuffer* vs_cb, const PSConstantBuffer* if(m_ps_cb_cache.Update(ps_cb)) { m_ps_cb->upload(ps_cb); } - GL_POP(); } void GSDeviceOGL::SetupPipeline(const VSSelector& vsel, const GSSelector& gsel, const PSSelector& psel) diff --git a/plugins/GSdx/GSRenderer.cpp b/plugins/GSdx/GSRenderer.cpp index 11323a1edd..53c7f71014 100644 --- a/plugins/GSdx/GSRenderer.cpp +++ b/plugins/GSdx/GSRenderer.cpp @@ -293,8 +293,6 @@ bool GSRenderer::Merge(int field) } } - GL_POP(); - return true; } diff --git a/plugins/GSdx/GSRendererHW.cpp b/plugins/GSdx/GSRendererHW.cpp index 453bbba238..578cff6532 100644 --- a/plugins/GSdx/GSRendererHW.cpp +++ b/plugins/GSdx/GSRendererHW.cpp @@ -383,7 +383,6 @@ void GSRendererHW::Draw() m_channel_shuffle = draw_sprite_tex && (m_context->TEX0.PSM == PSM_PSMT8) && single_page; if (m_channel_shuffle) { GL_CACHE("Channel shuffle effect detected SKIP"); - GL_POP(); s_n += 3; // Keep it sync with SW renderer return; } @@ -425,7 +424,6 @@ void GSRendererHW::Draw() if(!(rt || no_rt) || !(ds || no_ds)) { - GL_POP(); ASSERT(0); return; } @@ -455,7 +453,6 @@ void GSRendererHW::Draw() tex = tex_psm.depth ? m_tc->LookupDepthSource(context->TEX0, env.TEXA, r) : m_tc->LookupSource(context->TEX0, env.TEXA, r); if(!tex) { - GL_POP(); return; } @@ -554,14 +551,12 @@ void GSRendererHW::Draw() { s_n += 1; // keep counter sync GL_INS("Warning skipping a draw call (%d)", s_n); - GL_POP(); return; } if (!OI_BlitFMV(rt, tex, r)) { s_n += 1; // keep counter sync GL_INS("Warning skipping a draw call (%d)", s_n); - GL_POP(); return; } @@ -716,8 +711,6 @@ void GSRendererHW::Draw() m_tc->Read(rt, r); #endif - - GL_POP(); } // hacks @@ -949,8 +942,6 @@ bool GSRendererHW::OI_BlitFMV(GSTextureCache::Target* _rt, GSTextureCache::Sourc m_tc->InvalidateVideoMemSubTarget(_rt); - GL_POP(); - return false; // skip current draw } diff --git a/plugins/GSdx/GSRendererOGL.cpp b/plugins/GSdx/GSRendererOGL.cpp index 9bdb1a0f58..e0f55d2200 100644 --- a/plugins/GSdx/GSRendererOGL.cpp +++ b/plugins/GSdx/GSRendererOGL.cpp @@ -124,6 +124,8 @@ void GSRendererOGL::EmulateGS() void GSRendererOGL::SetupIA() { + GL_PUSH("IA"); + GSDeviceOGL* dev = (GSDeviceOGL*)m_dev; if (!GLLoader::found_geometry_shader) @@ -615,8 +617,6 @@ void GSRendererOGL::SendDraw(bool require_barrier) glTextureBarrier(); dev->DrawIndexedPrimitive(p, count); } - - GL_POP(); } else { // FIXME: Investigate: a dynamic check to pack as many primitives as possibles // I'm nearly sure GSdx already have this kind of code (maybe we can adapt GSDirtyRect) @@ -630,8 +630,6 @@ void GSRendererOGL::SendDraw(bool require_barrier) glTextureBarrier(); dev->DrawIndexedPrimitive(p, nb_vertex); } - - GL_POP(); } } @@ -1098,9 +1096,7 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour const GSVector4& hacked_scissor = m_channel_shuffle ? GSVector4(0, 0, 1024, 1024) : m_context->scissor.in; GSVector4i scissor = GSVector4i(GSVector4(rtscale).xyxy() * hacked_scissor).rintersect(GSVector4i(rtsize).zwxy()); - GL_PUSH("IA"); SetupIA(); - GL_POP(); dev->OMSetColorMaskState(om_csel); dev->SetupOM(om_dssel); @@ -1134,8 +1130,6 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour // Be sure that first pass is finished ! dev->Barrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); - - GL_POP(); } if (ps_sel.hdr) { @@ -1211,6 +1205,4 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour dev->Recycle(hdr_rt); } - - GL_POP(); } diff --git a/plugins/GSdx/GSTextureCacheOGL.cpp b/plugins/GSdx/GSTextureCacheOGL.cpp index aa8ae4cf3d..f2e066b26c 100644 --- a/plugins/GSdx/GSTextureCacheOGL.cpp +++ b/plugins/GSdx/GSTextureCacheOGL.cpp @@ -125,8 +125,6 @@ void GSTextureCacheOGL::Read(Target* t, const GSVector4i& r) // FIXME invalidate data m_renderer->m_dev->Recycle(offscreen); } - - GL_POP(); } void GSTextureCacheOGL::Read(Source* t, const GSVector4i& r) diff --git a/plugins/GSdx/GSTextureOGL.cpp b/plugins/GSdx/GSTextureOGL.cpp index 234f5192e9..44ba8b4b86 100644 --- a/plugins/GSdx/GSTextureOGL.cpp +++ b/plugins/GSdx/GSTextureOGL.cpp @@ -343,8 +343,6 @@ bool GSTextureOGL::Update(const GSVector4i& r, const void* data, int pitch) PboPool::EndTransfer(); #endif - GL_POP(); - return true; } @@ -379,7 +377,7 @@ bool GSTextureOGL::Map(GSMap& m, const GSVector4i* _r) return true; } else if (m_type == GSTexture::Texture || m_type == GSTexture::RenderTarget) { - GL_PUSH("Upload Texture %d", m_texture_id); // POP is in Unmap + GL_PUSH_("Upload Texture %d", m_texture_id); // POP is in Unmap m_clean = false; diff --git a/plugins/GSdx/stdafx.h b/plugins/GSdx/stdafx.h index 19238bdb5e..0b230c96a8 100644 --- a/plugins/GSdx/stdafx.h +++ b/plugins/GSdx/stdafx.h @@ -435,11 +435,19 @@ extern void vmfree(void* ptr, size_t size); #endif #if defined(ENABLE_OGL_DEBUG) -#define GL_PUSH(...) do glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0xBAD, -1, format(__VA_ARGS__).c_str()); while(0); +struct GLAutoPop { + ~GLAutoPop() { + glPopDebugGroup(); + } +}; + +#define GL_PUSH_(...) do glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0xBAD, -1, format(__VA_ARGS__).c_str()); while(0); +#define GL_PUSH(...) do glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0xBAD, -1, format(__VA_ARGS__).c_str()); while(0); GLAutoPop gl_auto_pop; #define GL_POP() do glPopDebugGroup(); while(0); #define GL_INS(...) GL_INSERT(GL_DEBUG_TYPE_ERROR, 0xDEAD, GL_DEBUG_SEVERITY_MEDIUM, __VA_ARGS__) #define GL_PERF(...) GL_INSERT(GL_DEBUG_TYPE_PERFORMANCE, 0xFEE1, GL_DEBUG_SEVERITY_NOTIFICATION, __VA_ARGS__) #else +#define GL_PUSH_(...) (0); #define GL_PUSH(...) (0); #define GL_POP() (0); #define GL_INS(...) (0); From e890ce989ce94226ca4381a2cdfcd68624418bb3 Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Thu, 5 May 2016 18:01:44 +0200 Subject: [PATCH 7/7] gsdx: throw oom exception + error Texture can't be NULL anymore, so we can remove a couples of check --- plugins/GSdx/GSDevice11.cpp | 3 +++ plugins/GSdx/GSDevice9.cpp | 6 ++++++ plugins/GSdx/GSDeviceOGL.cpp | 3 +++ plugins/GSdx/GSRendererHW.cpp | 24 +++++++++++------------- plugins/GSdx/GSTextureCache.cpp | 23 +++++------------------ 5 files changed, 28 insertions(+), 31 deletions(-) diff --git a/plugins/GSdx/GSDevice11.cpp b/plugins/GSdx/GSDevice11.cpp index a09ff0a351..073c4a8322 100644 --- a/plugins/GSdx/GSDevice11.cpp +++ b/plugins/GSdx/GSDevice11.cpp @@ -523,6 +523,9 @@ GSTexture* GSDevice11::CreateSurface(int type, int w, int h, bool msaa, int form if(SUCCEEDED(hr)) { t = new GSTexture11(texture); + if (t == NULL) { + throw GSDXErrorOOM(); + } switch(type) { diff --git a/plugins/GSdx/GSDevice9.cpp b/plugins/GSdx/GSDevice9.cpp index 4d0a6ad446..13f52b052c 100644 --- a/plugins/GSdx/GSDevice9.cpp +++ b/plugins/GSdx/GSDevice9.cpp @@ -718,11 +718,17 @@ GSTexture* GSDevice9::CreateSurface(int type, int w, int h, bool msaa, int forma if(surface) { t = new GSTexture9(surface); + if (t == NULL) { + throw GSDXErrorOOM(); + } } if(texture) { t = new GSTexture9(texture); + if (t == NULL) { + throw GSDXErrorOOM(); + } } if(t) diff --git a/plugins/GSdx/GSDeviceOGL.cpp b/plugins/GSdx/GSDeviceOGL.cpp index 23ffca7c06..ca241aa74d 100644 --- a/plugins/GSdx/GSDeviceOGL.cpp +++ b/plugins/GSdx/GSDeviceOGL.cpp @@ -142,6 +142,9 @@ GSTexture* GSDeviceOGL::CreateSurface(int type, int w, int h, bool msaa, int fmt // A wrapper to call GSTextureOGL, with the different kind of parameter GSTextureOGL* t = NULL; t = new GSTextureOGL(type, w, h, fmt, m_fbo_read); + if (t == NULL) { + throw GSDXErrorOOM(); + } // NOTE: I'm not sure RenderTarget always need to be cleared. It could be costly for big upscale. switch(type) diff --git a/plugins/GSdx/GSRendererHW.cpp b/plugins/GSdx/GSRendererHW.cpp index 578cff6532..4164e9a774 100644 --- a/plugins/GSdx/GSRendererHW.cpp +++ b/plugins/GSdx/GSRendererHW.cpp @@ -412,20 +412,22 @@ void GSRendererHW::Draw() TEX0.TBW = context->FRAME.FBW; TEX0.PSM = context->FRAME.PSM; - GSTextureCache::Target* rt = no_rt ? NULL : m_tc->LookupTarget(TEX0, m_width, m_height, GSTextureCache::RenderTarget, true); - GSTexture* rt_tex = rt ? rt->m_texture : NULL; + GSTextureCache::Target* rt = NULL; + GSTexture* rt_tex = NULL; + if (!no_rt) { + rt = m_tc->LookupTarget(TEX0, m_width, m_height, GSTextureCache::RenderTarget, true); + rt_tex = rt->m_texture; + } TEX0.TBP0 = context->ZBUF.Block(); TEX0.TBW = context->FRAME.FBW; TEX0.PSM = context->ZBUF.PSM; - GSTextureCache::Target* ds = no_ds ? NULL : m_tc->LookupTarget(TEX0, m_width, m_height, GSTextureCache::DepthStencil, context->DepthWrite()); - GSTexture* ds_tex = ds ? ds->m_texture : NULL; - - if(!(rt || no_rt) || !(ds || no_ds)) - { - ASSERT(0); - return; + GSTextureCache::Target* ds = NULL; + GSTexture* ds_tex = NULL; + if (!no_ds) { + ds = m_tc->LookupTarget(TEX0, m_width, m_height, GSTextureCache::DepthStencil, context->DepthWrite()); + ds_tex = ds->m_texture; } GSTextureCache::Source* tex = NULL; @@ -452,10 +454,6 @@ void GSRendererHW::Draw() tex = tex_psm.depth ? m_tc->LookupDepthSource(context->TEX0, env.TEXA, r) : m_tc->LookupSource(context->TEX0, env.TEXA, r); - if(!tex) { - return; - } - // FIXME: Could be removed on openGL if(tex_psm.pal > 0) { diff --git a/plugins/GSdx/GSTextureCache.cpp b/plugins/GSdx/GSTextureCache.cpp index 4099028506..0cf7df7727 100644 --- a/plugins/GSdx/GSTextureCache.cpp +++ b/plugins/GSdx/GSTextureCache.cpp @@ -87,7 +87,7 @@ void GSTextureCache::RemoveAll() GSTextureCache::Source* GSTextureCache::LookupDepthSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GSVector4i& r, bool palette) { - if (!CanConvertDepth()) return NULL; + if (!CanConvertDepth()) throw GSDXRecoverableError(); const GSLocalMemory::psm_t& psm_s = GSLocalMemory::m_psm[TEX0.PSM]; @@ -332,11 +332,6 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con #endif src = CreateSource(TEX0, TEXA, dst, half_right); - if(src == NULL) - { - return NULL; - } - } else { GL_CACHE("TC: src hit: %d (0x%x, F:0x%x)", src->m_texture ? src->m_texture->GetID() : 0, @@ -432,9 +427,6 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, int dst = CreateTarget(TEX0, w, h, type); - if(dst == NULL) - return NULL; - // In theory new textures contain invalidated data. Still in theory a new target // must contains the content of the GS memory. // In practice, TC will wrongly invalidate some RT. For example due to write on the alpha @@ -594,11 +586,6 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, int dst = CreateTarget(TEX0, w, h, RenderTarget); - if(dst == NULL) - { - return NULL; - } - m_renderer->m_dev->ClearRenderTarget(dst->m_texture, 0); // new frame buffers after reset should be cleared, don't display memory garbage if (m_preload_frame) { @@ -1076,6 +1063,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con { const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[TEX0.PSM]; Source* src = new Source(m_renderer, TEX0, TEXA, m_temp); + if (src == NULL) throw GSDXErrorOOM(); int tw = 1 << TEX0.TW; int th = 1 << TEX0.TH; @@ -1370,9 +1358,8 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con if(src->m_texture == NULL) { - ASSERT(0); delete src; - return NULL; + throw GSDXErrorOOM(); } if(psm.pal > 0) @@ -1388,6 +1375,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con GSTextureCache::Target* GSTextureCache::CreateTarget(const GIFRegTEX0& TEX0, int w, int h, int type) { Target* t = new Target(m_renderer, TEX0, m_temp, CanConvertDepth()); + if (t == NULL) throw GSDXErrorOOM(); // FIXME: initial data should be unswizzled from local mem in Update() if dirty @@ -1406,9 +1394,8 @@ GSTextureCache::Target* GSTextureCache::CreateTarget(const GIFRegTEX0& TEX0, int if(t->m_texture == NULL) { - ASSERT(0); delete t; - return NULL; + throw GSDXErrorOOM(); } m_dst[type].push_front(t);