Merge pull request #1346 from PCSX2/gsdx-cleanup

Gsdx cleanup
This commit is contained in:
Gregory Hainaut 2016-05-06 12:23:54 +02:00
commit c94fecdadb
18 changed files with 390 additions and 423 deletions

View File

@ -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)
@ -202,6 +200,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);

View File

@ -194,6 +194,7 @@ public:
bool IsRBSwapped() {return m_rbswapped;}
void AgePool();
void PurgePool();
virtual void PrintMemoryUsage();
};

View File

@ -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)
{

View File

@ -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)

View File

@ -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)
@ -144,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)
@ -157,7 +158,6 @@ GSTexture* GSDeviceOGL::CreateSurface(int type, int w, int h, bool msaa, int fmt
break;
}
GL_POP();
return t;
}
@ -197,163 +197,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 +372,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 +409,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 +420,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 +553,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 +593,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 +616,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 +633,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 +672,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 +1024,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 +1043,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 +1156,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 +1178,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 +1200,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 +1226,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 +1278,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 +1292,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 +1332,6 @@ void GSDeviceOGL::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* ver
}
EndScene();
GL_POP();
}
void GSDeviceOGL::EndScene()
@ -1576,7 +1546,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)

View File

@ -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,7 +2430,159 @@ bool IsInvokedDynamicCrcHack( GSFrameInfo &fi, int& skip, int region, bool &resu
#endif
bool GSState::IsBadFrame(int& skip, int UserHacks_SkipDraw)
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()
{
GSFrameInfo fi;
@ -2454,193 +2594,30 @@ 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
bool res=false; if(IsInvokedDynamicCrcHack(fi, m_skip, g_crc_region, res, m_crc)){ if( !res ) return false; } else
#endif
if(gsc && !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)
{
// 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;
m_skip = m_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)
if(m_skip > 0)
{
skip--;
m_skip--;
return true;
}

View File

@ -293,8 +293,6 @@ bool GSRenderer::Merge(int field)
}
}
GL_POP();
return true;
}
@ -645,3 +643,8 @@ void GSRenderer::KeyEvent(GSKeyEventData* e)
}
#endif
}
void GSRenderer::PurgePool()
{
m_dev->PurgePool();
}

View File

@ -79,6 +79,8 @@ public:
virtual bool BeginCapture();
virtual void EndCapture();
void PurgePool();
public:
std::mutex m_pGSsetTitle_Crit;

View File

@ -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;
@ -385,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;
}
@ -415,21 +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))
{
GL_POP();
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;
@ -456,11 +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) {
GL_POP();
return;
}
// FIXME: Could be removed on openGL
if(tex_psm.pal > 0)
{
@ -556,14 +549,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;
}
@ -718,8 +709,6 @@ void GSRendererHW::Draw()
m_tc->Read(rt, r);
#endif
GL_POP();
}
// hacks
@ -951,8 +940,6 @@ bool GSRendererHW::OI_BlitFMV(GSTextureCache::Target* _rt, GSTextureCache::Sourc
m_tc->InvalidateVideoMemSubTarget(_rt);
GL_POP();
return false; // skip current draw
}

View File

@ -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;

View File

@ -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();
}

View File

@ -33,6 +33,8 @@ GSState::GSState()
, m_irq(NULL)
, 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)
@ -40,11 +42,11 @@ 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);
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);
@ -1473,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));
@ -2350,6 +2360,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 +2378,7 @@ void GSState::UpdateScissor()
m_ofxy = m_context->scissor.ofxy;
}
void GSState::UpdateVertexKick()
void GSState::UpdateVertexKick()
{
if(m_frameskip) return;

View File

@ -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)
@ -140,19 +153,23 @@ 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;
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 +177,7 @@ protected:
uint64 xy[4];
} m_vertex;
struct
struct
{
uint32* buff;
size_t tail;
@ -173,7 +190,7 @@ protected:
void GrowVertexBuffer();
template<uint32 prim>
template<uint32 prim>
void VertexKick(uint32 skip);
// following functions need m_vt to be initialized
@ -199,7 +216,6 @@ public:
GSDump m_dump;
int m_options;
int m_frameskip;
bool m_crcinited;
bool m_framelimit;
bool m_NTSC_Saturation;
bool m_nativeres;
@ -233,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) {}

View File

@ -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);
@ -1536,7 +1523,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<int>(1 << m_TEX0.TW, bs.x);
int th = std::max<int>(1 << m_TEX0.TH, bs.y);

View File

@ -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)

View File

@ -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;

View File

@ -79,5 +79,6 @@ public:
struct GSDXError {};
struct GSDXRecoverableError : GSDXError {};
struct GSDXErrorOOM : GSDXError {};
extern GSdxApp theApp;

View File

@ -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);