https://bugs.winehq.org/show_bug.cgi?id=47974
Bug ID: 47974 Summary: X Rebirth - wined3d GL_INVALID_OPERATION dimensions must be identical with current filtering modes Product: Wine Version: 4.18 Hardware: x86-64 OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: -unknown Assignee: wine-bugs@winehq.org Reporter: consolelogger@rhyta.com Distribution: ---
Created attachment 65475 --> https://bugs.winehq.org/attachment.cgi?id=65475 console log for x rebirth
Ubuntu 19.10 - wine-mono-4.9.3.msi
X Rebirth crashes on startup. Console log is attached.
I am happy to provide more details and do tests when asked to.
https://bugs.winehq.org/show_bug.cgi?id=47974
Louis Lenders xerox.xerox2000x@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |xerox.xerox2000x@gmail.com
--- Comment #1 from Louis Lenders xerox.xerox2000x@gmail.com --- Maybe winetricks d3dx9_** might help? Could you try? Fill in correct number for the ** (running with WINEDEBUG=+loaddll will tell you what exact d3dx9_** dll is loaded)
https://bugs.winehq.org/show_bug.cgi?id=47974
Paul Gofman gofmanp@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |gofmanp@gmail.com
--- Comment #2 from Paul Gofman gofmanp@gmail.com --- Created attachment 65500 --> https://bugs.winehq.org/attachment.cgi?id=65500 hack
I tested the game (GOG version, installed through GOG Galaxy).
I spotted and had to workaround 3 issues to make the game run, and will describe each one here, while the bug probably needs splitting. I suggest to make this bug about virtual memory issue 2 described below and split off d3dx issues 1, 3 into separate bugs (as those are easier and have a workaround without custom patches). The issue with GL_INVALID_OPERATION (which is currently in bug title) is the forth one and probably worth attention, but seems not to affect the game: I did not notice any glitches after working around the other 3 (tested the start and beginning of the campaign).
1. d3dx9: D3DXCreateCubeTextureFromFileInMemoryEx() fails to create a cube texture. This is because requested usage is D3DUSAGE_RENDERTARGET with default pool. The implementation of the function decides to change the pool to sysmem due to the side reasons, and the texture creation fails which is fatal for the game start. The function is likely have to mind the render target usage flag, doing so in code seem to fix the issue though I did not yet make the unit test. The easiest workaround for now is to use native d3dx9_43 ('winetricks d3dx9_43').
2. After working around p. 1., the game displays some intro movie (can be skipped), and then crashes. The game processes the crashes, so it does not display Wine crash dialog but tries to send crash report instead; it displays the message box complaining about missing INI file. This is accompanied by the following output from game (there are a lot of them for different lua files):
====================================== Error while loading the Lua file: 'ui/addons/ego_movie/movie.lua' for addon 'ego_movie': 'not enough memory' ======================================
This is due to the failures to allocate memory with NtAllocateVirtualMemory(): --- 00a7:Call ntdll.NtAllocateVirtualMemory(ffffffffffffffff,7f4d8e4ceeb8,00000001,7f4d8e4ceec0,00003000,7f4d00000004) ret=00f5fc25 00a7:trace:virtual:NtAllocateVirtualMemory 0xffffffffffffffff (nil) 00020000 3000 00000004 00a7:Ret ntdll.NtAllocateVirtualMemory() retval=c0000017 ret=00f5fc25 00a7:Call KERNEL32.RaiseException(e24c4a04,00000001,00000000,00000000) ret=00f88bce ---
This is called from lua51_64.dll. This would look like a not so unusual VM exhaustion issue, but the game executable is 64bit. Please mind zero_bits parameter for NtAllocateVirtualMemory set to 1. The proper support for such zero_bits parameter was added lately by commit 8a765533d6e19b0b8d51bf1ef7f316d79f9bb968. Without that (or forcefully setting zero_bits to 0) result in successful memory allocation of course, but no surprise the game crashes soon after as it really expects the returned address to fit in 31 bits. The first few same calls to NtAllocateVirtualMemory (same parameters, same return address) succeed, but then it reports out of memory status. Now it may look like we face VM exhaustion in the lower 31 bit, yet my further analysis show that it is not exactly the case.
map_view() (dlls/ntdll/virtual.c) tries to get memory range for non-zero zero_bits parameter in two ways. First it searches for the available memory in reserved areas. All the successful allocations mentioned above hit this path. When there is no memory in reserved areas, it tries to get the correct address with find_free_area(), but this seem to always fail, regardless of actual memory range availability. NULL start address is passed to find_free_area(), without MEM_TOP_DOWN flag. This seem to always fail the search due to this condition in find_free_area() (currently at line 537): 'if (!start || start >= end || (char *)end - (char *)start < size) return NULL;'. 'start' is going to be non NULL here only if we have a view with NULL start address in the tree, but we don't have that, so the search always fails. If we pass 'address_space_start' instead of NULL as base address for find_free_area(), the search succeeds, and in my tests all the allocations start to succeed. Sadly, it is not the end of story, as after find_free_area() succeeds here we hit the next, harder, problem.
Now, when we get memory found through find_free_area(), after certain moment each call to OpenGL causes invalid memory access inside host opengl library. This is likely caused by corruption of the memory areas which native GL library previously allocated using native mmap(). It looks like it has something to do with this code in map_view(): 'if ((ptr = wine_anon_mmap( ptr, view_size, VIRTUAL_GetUnixProt(vprot), ptr ? MAP_FIXED : 0 )) == (void *)-1)...'. ptr is not NULL only for nonzero 'zero_bits', and given the find_free_area() never succeeded before the change I described in the previous paragraph, MAP_FIXED was never actually used here before. The problem seem to be related to the change in MAP_FIXED behaviour starting from Linux 4.17. Now MAP_FIXED does not mind previously mapped areas at the requested location, and clobbers preexisting map range. Starting from Linux 4.17, we are supposed to use MAP_FIXED_NOREPLACE here to do what we want. When I change MAP_FIXED to MAP_FIXED_NOREPLACE here, I am starting to get EEXIST error, which contributes to the guess about GL driver memory corruption. Yet just changing the flag does not solve the allocation issues, as we merely end up being where we started: we still get no memory while actually free areas in the desired range do exist. I am attaching a proof of concent hacky patch which works around the issue and lets me to run the game flawlessly. Yet the patch is nowhere close to even a good workaround yet, as it doesn't care about a load of things, like the correct size of created view, or some mechanism to get the virtual space back if native library unmaps the range. Not mentioning that we need to guess kernel type and version to choose the correct flag; this patch is for Linux kernels 4.17+. The other versions might not need the new flag, but still need to care about marking the VM area as busy and retrying the allocation. The other simplier hack which also lets the game work is like this:
--- a/loader/preloader.c +++ b/loader/preloader.c @@ -118,7 +118,7 @@ static struct wine_preload_info preload_info[] = { (void *)0x7f000000, 0x03000000 }, /* top-down allocations + shared heap + virtual heap */ #else { (void *)0x000000010000, 0x00100000 }, /* DOS area */ - { (void *)0x000000110000, 0x67ef0000 }, /* low memory area */ + { (void *)0x000000110000, 0x77ef0000 }, /* low memory area */ { (void *)0x00007ff00000, 0x000f0000 }, /* shared user data */ { (void *)0x7ffffe000000, 0x01ff0000 }, /* top-down allocations + virtual heap */ #endif
3. d3dx9: The function is using parameter blocks for setting effect parameters which is currently not implemented. This is the first game I encounter which uses this functionality. It does not prevent the game from starting (while of course it has severe graphical glitches). The workaround for now is the same as in p. 1.
https://bugs.winehq.org/show_bug.cgi?id=47974
--- Comment #3 from consolelogger consolelogger@rhyta.com --- Created attachment 65518 --> https://bugs.winehq.org/attachment.cgi?id=65518 console log after winetricks d3dx9_43
Paul Gofman's more extensive dive is probably more insightful, but here is the requested (Louis Lenders) test with winetricks d3dx9_43. We get further. The game company logo clip gets played and then we crash on the spashscreen. The games own crash utility DrDump starts then.
https://bugs.winehq.org/show_bug.cgi?id=47974
--- Comment #4 from Paul Gofman gofmanp@gmail.com --- The memory issue was fixed by 5eca6ffa8b392ac852324a5be3cc88d8e60197a8, so I guess this bug should be closed.
The other issues (Comment #2, pp 1, 3) were also fixed.
https://bugs.winehq.org/show_bug.cgi?id=47974
consolelogger consolelogger@rhyta.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Resolution|--- |FIXED Status|UNCONFIRMED |RESOLVED
--- Comment #5 from consolelogger consolelogger@rhyta.com --- Awesome. Everything just works out of the box now.
https://bugs.winehq.org/show_bug.cgi?id=47974
Gijs Vermeulen gijsvrm@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Fixed by SHA1| |5eca6ffa8b392ac852324a5be3c | |c88d8e60197a8
https://bugs.winehq.org/show_bug.cgi?id=47974
Alexandre Julliard julliard@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |CLOSED
--- Comment #6 from Alexandre Julliard julliard@winehq.org --- Closing bugs fixed in 5.0-rc5.