PCSX2 version:
pcsx2-2017.05.08_9b0b32533_master-x86_64-1_git
gcc-7.1.0_multilib-x86_64-1alien
libdrm-compat32-2017.05.04_a2fa2e08_master-x86_64-1_gitcompat32
mesa-compat32-2017.05.06_a3996590b8_master-x86_64-1_gitcompat3
PCSX2 options:
Occurs with a default configuration file.
Plugins used:
GSdx (GCC 7.1.0 SSE2/AVX) 1.1.0 [libGSdx]
GSdx (GCC 7.1.0, SSE2) 1.0.0 [libGSdx-legacy-1.0.0]
Description of the issue:
The OpenGL gsdx no longer works at all and will render nothing, broken images or have severe graphical bugs. The game does not seem to matter too much and the software renderer will still work correctly. Audio from the games also seems to work.
This may be partially or entirely connected to issue https://github.com/PCSX2/pcsx2/issues/1935.

GSDX dump (Guilty Gear X2): http://ks392457.kimsufi.com/orbea/stuff/games/pcsx2/snaps/gsdx_20170509134534_gcc-7.1.0.ggx2.gs.xz
Epileptic flashing in the fmv.
GSDX dump (Tales of the Abyss): http://ks392457.kimsufi.com/orbea/stuff/games/pcsx2/snaps/gsdx_20170509134757_gcc-7.1.0.tota.gs.xz
How to reproduce the issue:
Last known version to work:
pcsx2 compiled with gcc-5.4.0.
PC specifications:
OS: Slackware64-current
CPU: amd fx 6350
GPU: GTX 780 Ti
Here is a verbose build log, some of the warnings which started with gcc-7.1.0 could be relevant.
http://ks392457.kimsufi.com/orbea/stuff/logs/pcsx2_build.log
A non verbose log would be nicer. What is your mesa version or do you use nvidia driver?
What is your patch build ? It seems GS.cpp was hacked.
I am using nouveau with a recent mesa commit, glxinfo reports Mesa 17.2.0-devel (git-a3996590b8).
Here is a non-verbose build log.
https://pastebin.com/5sqzNY9Y
The patch just changes the osd font to something slackware has out of the box. It shouldn't cause this and the osd seems to still work.
diff --git a/plugins/GSdx/GSdx.cpp b/plugins/GSdx/GSdx.cpp
index 6456945fe..85f35a0c6 100644
--- a/plugins/GSdx/GSdx.cpp
+++ b/plugins/GSdx/GSdx.cpp
@@ -316,7 +316,7 @@ void GSdxApp::Init()
#ifdef _WIN32
m_default_configuration["osd_fontname"] = "C:\\Windows\\Fonts\\tahoma.ttf";
#else
- m_default_configuration["osd_fontname"] = "/usr/share/fonts/truetype/freefont/FreeSerif.ttf";
+ m_default_configuration["osd_fontname"] = "/usr/share/fonts/TTF/LiberationSerif-Regular.ttf";
#endif
m_default_configuration["osd_fontsize"] = "48";
m_default_configuration["osd_indicator_enabled"] = "0";
Well most of the warning are harmless.
Hum how do you run PCSX2, do you have some env variable sets?
Actually maybe you could try an egl build. It should avoid some threads issue with Mesa
I just run /usr/bin/PCSX2 from a terminal or keybind.
I built PCSX2 with -DEGL_API=ON and there seems to be no difference. Are there any configuration options I overlooked?
Ok. Fwiw, there are couple of env variable to speed up Mesa. But they are not yet stable (some patches are pending on Mesa's ML). EGL is more stable here. But it isn't your issue.
Anyway, GCC7.1 is way too recent for me. I suggest to use an older version.
Note to myself: disable fabi-version on recent GCC.
That is understandable, but unfortunately my pcsx2.SlackBuild might have issues for others using slackware current now too. Even if I were to downgrade my gcc, I can't expect anyone else to do that just for pcsx2. :)
Also, what is the EGL version requirements for pcsx2?
Yeah, yeah I know. On the other hand, code is working on Clang/MSVC and older GCC so I'm not sure the issue is PCSX2 related. If you're motivated, could you remove this line and test again
=> https://github.com/PCSX2/pcsx2/blob/master/plugins/GSdx/CMakeLists.txt#L39
Also, what is the EGL version requirements for pcsx2?
What do you mean by requirement. A recent Mesa should be enough.
And to be sure GCC optimization didn't break the mess, you could try to
-Og with -O0Note: if EGL got any error it will fallback to GLX.
I tried to remove the line specified (https://github.com/PCSX2/pcsx2/blob/master/plugins/GSdx/CMakeLists.txt#L39) and I built it with -DCMAKE_C_FLAGS='-O0' and -DCMAKE_CXX_FLAGS='-O0'. Both unfortunately made no difference. I also tried to build with clang, but I am not sure the multilib llvm package I have is capable of doing that. I will have to investigate how to accomplish that later.
I was just curious if pcsx2 would use OpenGL ES 2 or 3.
I was just curious if pcsx2 would use OpenGL ES 2 or 3.
I didn't mention OpenGL ES because EGL isn't related to OpenGL ES. It can be used to create an ES context but also a full GL context (and another API).
Oh, I misunderstood. Thanks for the clarification.
So I made two apitraces of the issues.
Guilty Gear X2: http://ks392457.kimsufi.com/orbea/stuff/trace/PCSX2_gcc-7.1.0_ggx2.trace.xz
trace log: https://pastebin.com/nGPv5w72
Prints a lot of:
129: message: application error 57005: ERROR: Update RenderTarget 0x0 bw:10 (0,0 => 640,480)
2218: message: application error 57005: OI_GsMemClear (0,0 => 639,479)
Tales of the Abyss: http://ks392457.kimsufi.com/orbea/stuff/trace/PCSX2_gcc-7.1.0_tota.trace.xz
trace log: https://pastebin.com/meRgFKxa
When replaying the trace it will correctly render the various logos before the fmv while only the first shown in the trace flashes. The fmv also renders normally, but it will print a lot of this:
826: message: application error 57005: ERROR: Source and Target are the same!
Did you try an actual debug build (-DCMAKE_BUILD_TYPE=Debug)? Any optimisation level specified in CMAKE_C_FLAGS and CMAKE_CXX_FLAGS will actually be overridden in the build files, so they won't be applied.
I have been using -DCMAKE_BUILD_TYPE=Devel, I can use Debug instead if that would be preferable?
Yes, it's worth trying to see whether it renders properly. I'm not sure if you tried what gregory suggested earlier:
And to be sure GCC optimization didn't break the mess, you could try to
- edit https://github.com/PCSX2/pcsx2/blob/master/cmake/BuildParameters.cmake#L384
- replace -Og with -O0
- try a debug build
My apologies, I should of done that. Especially given that the GSdx issues are not present when exactly following those instructions!
This prompted for me to reconfirm they still occur with a release build, they do... I then checked if a debug build worked without editing cmake/BuildParameters.cmake, it does! So I conclude the issue is with the devel and release builds...
So you win the thousand build challenge :)
Get GCC7 manual and find the separate flag optimization flag option. You can either
-Og and add -f.... option one by one.-O2 and add -fno-... option one by one.This way we should be able to find which optimization breaks GSdx. Then next step will be to find which file is wrong (my guess is compilation unit of GSTextureCache.cpp) . It will give us the possibility to compare the binary with/without the option to understand what happen.
After many compiles it seems the two optimizations that cause this are -fgcse-lm and -ftree-pre.
$ gcc --help=optimizers
-fgcse Perform global common subexpression elimination.
-fgcse-lm Perform enhanced load motion during global common
subexpression elimination.
-ftree-pre Enable SSA-PRE optimization on trees.
Perform a global common subexpression elimination pass. This pass also performs global
constant and copy propagation.
Note: When compiling a program using computed gotos, a GCC extension, you may get better
run-time performance if you disable the global common subexpression elimination
pass by adding -fno-gcse to the command line.
Enabled at levels -O2, -O3, -Os.
-fgcse-lm
When -fgcse-lm is enabled, global common subexpression elimination attempts to move
loads that are only killed by stores into themselves. This allows a loop containing a
load/store sequence to be changed to a load outside the loop, and a copy/store within
the loop.
Enabled by default when -fgcse is enabled.
-ftree-pre
Perform partial redundancy elimination (PRE) on trees. This flag is enabled by
default at -O2 and -O3.
md5-d317167be8b9511235a99777ede5e76a
cmake \
-DCMAKE_CXX_FLAGS="-O2 -fno-gcse-lm -fno-tree-pre" \
-DCMAKE_BUILD_TYPE=Release
md5-5a96a50746c4406026f64c7f746469a5
$ gcc -v
Reading specs from /usr/lib64/gcc/x86_64-slackware-linux/7.1.0/specs
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-slackware-linux/7.1.0/lto-wrapper
Target: x86_64-slackware-linux
Configured with: ../gcc-7.1.0/configure --prefix=/usr --libdir=/usr/lib64 --mandir=/usr/man --infodir=/usr/info --enable-shared --enable-bootstrap --enable-languages=ada,brig,c,c++,fortran,go,lto,objc --enable-threads=posix --enable-checking=release --enable-objc-gc --with-system-zlib --enable-libstdcxx-dual-abi --with-default-libstdcxx-abi=gcc4-compatible --disable-libunwind-exceptions --enable-__cxa_atexit --enable-libssp --enable-lto --disable-install-libiberty --enable-gnu-indirect-function --with-linker-hash-style=gnu --with-gnu-ld --verbose --with-arch-directory=amd64 --disable-gtktest --disable-werror --enable-multilib --target=x86_64-slackware-linux --build=x86_64-slackware-linux --host=x86_64-slackware-linux
Thread model: posix
gcc version 7.1.0 (GCC)
Could you upload a build with -fno-gcse-lm -fno-tree-pre and a build without them. Better use a Devel target to keep symbol. If I'm very lucky the difference are small enough.
Based on the apitrace and the fact that SW renderer is working, I have 3 potential files
Maybe you could try to limit the scope of the optimization in those files.
set_property(SOURCE GSTextureCache.cpp APPEND PROPERTY CMAKE_CXX_FLAGS -fno-gcse-lm -fno-tree-pre)
...
If we can find a file, it will reduce the scope to find the gcc bad code generation.
Edit: potentially easier to disable widely the optimization and to enable them by file. This way, you will be sure of the impacted file.
I pushed a small Cmake hack to disable the optimization until we find a real fix (or a testcase for gcc)
I'm unfortunately at my time limit to test this for today, I'll have to pick it up tomorrow.
In the mean time here is two devel GSdx.so files, one that should work with -DCMAKE_CXX_FLAGS="fno-gcse-lm -fno-tree-pre" and the other that doesn't which is just the defaults.
Works: http://ks392457.kimsufi.com/orbea/stuff/games/pcsx2/libGSdx_fno-gcse-lm_fno-tree-pre.so
Broken: http://ks392457.kimsufi.com/orbea/stuff/games/pcsx2/libGSdx.so
They are both commit 2dcc85d64c8ac7fb10fb710d79de7eda14ec347b.
Maybe I'm doing this wrong, but could the problem be in a different file?
I built PCSX2 with/
cmake \
-DCMAKE_BUILD_TYPE=Devel
And with this change which successfully avoids the issue.
diff --git a/plugins/GSdx/CMakeLists.txt b/plugins/GSdx/CMakeLists.txt
index 718a81573..79e8ae7cd 100644
--- a/plugins/GSdx/CMakeLists.txt
+++ b/plugins/GSdx/CMakeLists.txt
@@ -5,6 +5,7 @@ if(NOT TOP_CMAKE_WAS_SOURCED)
It is advice to delete all wrongly generated cmake stuff => CMakeFiles & CMakeCache.txt")
endif()
+add_compile_options(-fno-gcse-lm -fno-tree-pre)
# plugin name (no version number to ease future version bump and bisect)
set(Output GSdx)
I then rebuilt it with this patch, but the problem was not reintroduced.
diff --git a/plugins/GSdx/CMakeLists.txt b/plugins/GSdx/CMakeLists.txt
index 718a81573..7d731ba7a 100644
--- a/plugins/GSdx/CMakeLists.txt
+++ b/plugins/GSdx/CMakeLists.txt
@@ -5,6 +5,11 @@ if(NOT TOP_CMAKE_WAS_SOURCED)
It is advice to delete all wrongly generated cmake stuff => CMakeFiles & CMakeCache.txt")
endif()
+add_compile_options(-fno-gcse-lm -fno-tree-pre)
+
+set_property(SOURCE GSLocalMemory.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -fgcse-lm -ftree-pre ")
+set_property(SOURCE GSBlock.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -fgcse-lm -ftree-pre ")
+set_property(SOURCE GSTextureCache.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -fgcse-lm -ftree-pre ")
# plugin name (no version number to ease future version bump and bisect)
set(Output GSdx)
It seems to be applying the correct flags as shown with pcsx2/build/plugins/GSdx$ grep -r -- -fgcse
https://pastebin.com/h8MYsZde
Yes it could be. I was just a stab in the dark.
I guess I can try to find it by the process of elimination... :)
The problem appears to be in plugins/GSdx/GSState.cpp.
https://github.com/PCSX2/pcsx2/blob/master/plugins/GSdx/GSState.cpp
I built PCSX2 like above.
cmake \
-DCMAKE_BUILD_TYPE=Devel
With the following patch which seems to be the minimum requirements to avoid this issue.
diff --git a/plugins/GSdx/CMakeLists.txt b/plugins/GSdx/CMakeLists.txt
index 718a81573..408922844 100644
--- a/plugins/GSdx/CMakeLists.txt
+++ b/plugins/GSdx/CMakeLists.txt
@@ -5,6 +5,7 @@ if(NOT TOP_CMAKE_WAS_SOURCED)
It is advice to delete all wrongly generated cmake stuff => CMakeFiles & CMakeCache.txt")
endif()
+set_property(SOURCE GSState.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -fno-gcse-lm -fno-tree-pre ")
# plugin name (no version number to ease future version bump and bisect)
set(Output GSdx)
I updated the link for the working devel GSdx.so above and it can be downloaded here.
http://ks392457.kimsufi.com/orbea/stuff/games/pcsx2/libGSdx_fno-gcse-lm_fno-tree-pre.so
Oh. It is strange code is shared with sw renderer. Maybe it is linked with the strange uninitialized warning.
Actually the uninitialized warning is correct. It concerns invalid primitive so it isn't our issue.
@orbea Let's try to reduce further the scope of investigation with the help of pragma. At least recompilation will be faster.
I'm not sure how the optimized string must be formated. Hopefully this kind of code will work.
#pragma GCC push_options
#pragma GCC optimize ("-fno-gcse-lm -fno-tree-pre")
void foo()
{
}
#pragma GCC pop_options
I am having trouble with the syntax unfortunately. I tried many variations of the above, but the issue continues to persist. I suspect its because of the two optimization flags instead of just one? So I tried to do #pragma GCC optimize ("O0"), but the it just fails to build instead.
https://pastebin.com/pdNsUAcf
So I looked at bsnes-libretro and bsnes-mercury which conveniently have an unrelated gcc 7 issue with -fstrict-aliasing which results in an infinite loop during compile. There I was able to avoid the issue with this test patch, so the idea does have merit...
diff --git a/sfc/ppu/ppu.cpp b/sfc/ppu/ppu.cpp
index 4ed7389d..1ee3f237 100644
--- a/sfc/ppu/ppu.cpp
+++ b/sfc/ppu/ppu.cpp
@@ -1,5 +1,10 @@
+#pragma GCC push_options
+#pragma GCC optimize ("no-strict-aliasing")
+
#include <sfc/sfc.hpp>
+#pragma GCC pop_options
+
#define PPU_CPP
namespace SuperFamicom {
https://github.com/libretro/bsnes-mercury/issues/47
Here are some links I found helpful when reading about #pragma.
https://stackoverflow.com/questions/2219829/how-to-prevent-gcc-optimizing-some-statements-in-c
https://stackoverflow.com/questions/1867065/how-to-suppress-gcc-warnings-from-library-headers
https://stackoverflow.com/questions/5580140/is-there-a-way-to-tell-gcc-not-to-optimise-a-particular-piece-of-code
The correct syntax looks like this. I will try to narrow it down to specific code next.
#pragma GCC push_options
#pragma GCC optimize ("no-gcse-lm,no-tree-pre")
void foo()
{
}
#pragma GCC pop_options
After many more builds the problem(s) actually appears to be in plugins/GSdx/GS.h.
Here is a test patch that avoids the issues, but its not exact as its likely I will not notice a broken game I am not testing. With this the 5 games I have tested seem to work normally.
diff --git a/plugins/GSdx/GS.h b/plugins/GSdx/GS.h
index db9e41ee8..95f7e8807 100644
--- a/plugins/GSdx/GS.h
+++ b/plugins/GSdx/GS.h
@@ -563,6 +563,9 @@ REG_END2
__forceinline bool IsCd() { return (A == B) && (D == 1);}
REG_END2
+#pragma GCC push_options
+#pragma GCC optimize ("no-tree-pre")
+
REG64_(GIFReg, BITBLTBUF)
uint32 SBP:14;
uint32 _PAD1:2;
@@ -888,6 +891,8 @@ REG64_(GIFReg, TEXA)
uint8 _PAD3[3];
REG_END
+#pragma GCC pop_options
+
REG64_(GIFReg, TEXCLUT)
uint32 CBW:6;
uint32 COU:6;
@@ -907,6 +912,9 @@ REG64_(GIFReg, TRXDIR)
uint32 _PAD2:32;
REG_END
+#pragma GCC push_options
+#pragma GCC optimize ("no-gcse-lm")
+
REG64_(GIFReg, TRXPOS)
uint32 SSAX:11;
uint32 _PAD1:5;
@@ -927,6 +935,8 @@ REG64_(GIFReg, TRXREG)
uint32 _PAD2:20;
REG_END
+#pragma GCC pop_options
+
// GSState::GIFPackedRegHandlerUV and GSState::GIFRegHandlerUV will make sure that the _PAD1/2 bits are set to zero
REG64_(GIFReg, UV)
I have updated the link for the working libgsdx.so.
http://ks392457.kimsufi.com/orbea/stuff/games/pcsx2/libGSdx_fno-gcse-lm_fno-tree-pre.so
@orbea what instruction set did you use ? default ? see2 ?
So your result is quite interesting. If I'm right, the pragma only impact the code inside REG64* object.
https://github.com/PCSX2/pcsx2/blob/master/plugins/GSdx/GS.h#L268
#define REG64(name) \
union name \
{ \
uint64 u64; \
uint32 u32[2]; \
void operator = (const GSVector4i& v) {GSVector4i::storel(this, v);} \
bool operator == (const union name& r) const {return ((GSVector4i)r).eq(*this);} \
bool operator != (const union name& r) const {return !((GSVector4i)r).eq(*this);} \
operator GSVector4i() const {return GSVector4i::loadl(this);} \
struct { \
Indeed I saw various difference for comparisons operator on register functions.
Could you try to replace the == and the !=operators by
bool operator == (const union name& r) const {return r.u64 == u64;} \
bool operator != (const union name& r) const {return r.u64 != u64;} \
Instruction set for GSdx? It should be the default?
GSdx (GCC 7.1.0 SSE2/AVX) 1.1.0 [libGSdx]
Anyways I applied this patch and now all 5 of the test games seem to work normally again. :)
diff --git a/plugins/GSdx/GS.h b/plugins/GSdx/GS.h
index db9e41ee8..5e50e1804 100644
--- a/plugins/GSdx/GS.h
+++ b/plugins/GSdx/GS.h
@@ -265,8 +265,8 @@ union name \
uint64 u64; \
uint32 u32[2]; \
void operator = (const GSVector4i& v) {GSVector4i::storel(this, v);} \
- bool operator == (const union name& r) const {return ((GSVector4i)r).eq(*this);} \
- bool operator != (const union name& r) const {return !((GSVector4i)r).eq(*this);} \
+ bool operator == (const union name& r) const {return r.u64 == u64;} \
+ bool operator != (const union name& r) const {return r.u64 != u64;} \
operator GSVector4i() const {return GSVector4i::loadl(this);} \
struct { \
So SSE2. Do you have the issue on the SSE4 so file ?
And could you attach the build with the above patch. I would like to check the GCC generated code.
Hum looking at the code of the compiler
I don't know the behavior of MSVC but SSE barely helps anyway.
Yes, the SSE4 so file is affected (As is the legacy GSdx), the patch also seems to resolve it for SSE4 just the same. :)
Here is an new devel libGSdx.so with the patch applied.
http://ks392457.kimsufi.com/orbea/stuff/games/pcsx2/libGSdx_new.so
Before
000e88d0 <GSState::GIFRegHandlerTRXPOS(GIFReg const*)>:
push ebp
mov ebp,esp
sub esp,0x18
mov DWORD PTR [ebp-0x8],ebx
mov ebx,DWORD PTR [ebp+0x8]
mov DWORD PTR [ebp-0x4],esi
mov esi,DWORD PTR [ebp+0xc]
movq xmm0,QWORD PTR [ebx+0x5348]
movq mm0,QWORD PTR [esi]
movq2dq xmm1,mm0
pcmpeqd xmm0,xmm1
pmovmskb eax,xmm0
cmp eax,0xffff
je e890b <GSState::GIFRegHandlerTRXPOS(GIFReg const*)+0x3b>
mov DWORD PTR [esp],ebx
call e86c0 <GSState::FlushWrite()>
movq mm0,QWORD PTR [esi]
movq QWORD PTR [ebx+0x5348],mm0
mov ebx,DWORD PTR [ebp-0x8]
mov esi,DWORD PTR [ebp-0x4]
mov esp,ebp
pop ebp
ret
After
000e88d0 <GSState::GIFRegHandlerTRXPOS(GIFReg const*)>:
push ebp
mov ebp,esp
sub esp,0x18
mov DWORD PTR [ebp-0x8],ebx
mov ebx,DWORD PTR [ebp+0x8]
mov DWORD PTR [ebp-0x4],esi
mov esi,DWORD PTR [ebp+0xc]
movq xmm0,QWORD PTR [ebx+0x5348]
movq xmm1,QWORD PTR [esi]
pxor xmm0,xmm1
movd edx,xmm0
psrlq xmm0,0x20
movd eax,xmm0
or eax,edx
je e890b <GSState::GIFRegHandlerTRXPOS(GIFReg const*)+0x3b>
mov DWORD PTR [esp],ebx
call e86c0 <GSState::FlushWrite()>
mov eax,DWORD PTR [esi]
mov edx,DWORD PTR [esi+0x4]
mov DWORD PTR [ebx+0x5348],eax
mov DWORD PTR [ebx+0x534c],edx
mov ebx,DWORD PTR [ebp-0x8]
mov esi,DWORD PTR [ebp-0x4]
mov esp,ebp
pop ebp
ret
The biggest difference is MMX instruction (use in a dumb way). However I think EMMS must be called when leaving MMX code. I'm not 100% sure but there is no reason to use MMX here.
I will try to crease a small testcase so we can open a GCC bug.
Ok I have a small testcase. I will open a gcc bugzilla tomorrow.
Great, its appreciated. :)
The G++ bug report. Hopefully they will confirm it and fix it soon..
Bug confirmed and fixed in upstream ^^
Now remains the complex issue how to handle the buggy GCC7.1 here. I could
I think blacklisting the bad GCC versions is the path of least resistance, a bad instruction remaining somewhere could result in a hard to diagnose issue.
I suggested that gcc be patched with the upstream fix in slackware current, I guess we will see if this happens. Would it be too much to ask for other distros to do the same if they decide to ship GCC7?
I can try to get the patch backported to Fedora. Ubuntu users can easily install multiple different GCC versions if nothing has changed, so I guess blacklisting 7.1 is OK.
I would say Debian rather than Ubuntu. Anyway it is much better to allow multiple versions to coexist so you can fallback to a working version.
Its patched in Slackware-current now. :)
Mon May 22 20:58:20 UTC 2017
d/gcc-7.1.0-i586-2.txz: Rebuilt.
Fixed regression where MMX opcodes are generated without EMMS.
Most helpful comment
The G++ bug report. Hopefully they will confirm it and fix it soon..