Windows: Setup tu_override_uncached_as_cache_coherent inside of dlls

To not have this environment variable accidently be enabled on arm64
native Wine games, we need to set it from inside of FEX.

Requires the FEX dlls to set them directly rather than launch scripts.
This commit is contained in:
Ryan Houdek committed 2026-05-08 13:39:51 -07:00
1 parent e517f3259c
commit b7bfbc3fcd
6 files changed
+48

No files matched your search

+3
View File
@@ -28,6 +28,7 @@ $end_info$
#include <FEXCore/Utils/SignalScopeGuards.h>
#include "Windows/Common/Allocator.h"
#include "Windows/Common/EnvironmentVariablesHandling.h"
#include "Common/CallRetStack.h"
#include "Common/JITGuardPage.h"
#include "Common/Config.h"
@@ -595,6 +596,8 @@ NTSTATUS ProcessInit() {
const bool IsWine = !!GetProcAddress(NtDll, "wine_get_version");
OvercommitTracker.emplace(IsWine);
FEX::Windows::SetupEnvironmentVariableValues(NtDll);
FEX::Windows::Allocator::SetupHooks(NtDll);
{
+1
View File
@@ -9,6 +9,7 @@ target_include_directories(CommonWindowsRuntime PRIVATE "${CMAKE_SOURCE_DIR}/Sou
add_library(CommonWindows STATIC
Allocator.cpp
CPUFeatures.cpp
EnvironmentVariablesHandling.cpp
SHMStats.cpp
InvalidationTracker.cpp
ImageTracker.cpp
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: MIT
#include <libloaderapi.h>
#include <stdlib.h>
#include <winternl.h>
#include <wine/unixlib.h>
namespace FEX::Windows {
void SetupEnvironmentVariableValues(HMODULE NtDll) {
auto Sym = GetProcAddress(NtDll, "__wine_set_unix_env");
// On an ARM system we are expecting uncached memory to have marked overhead due to atomic memory usage.
// If `tu_override_uncached_as_cache_coherent` isn't already controlled by the user, then set it here.
// This lets the `turnip` mesa driver allocate uncached memory types as cached coherent instead if the hardware supports it.
//
// The only downside for this approach is that the GPU /may/ need to snoop CPU cachelines which could add some additional load
// on to the GPU side, but is unlikely to matter due to x86 emulation using excessive load-acquire/store-release semantic memory operations.
//
// Other UMA ARM platforms will run in to the same problem, with their own workarounds:
// - NVIDIA Tegra/Spark: Their proprietary driver always maps uncached as cached-coherent.
// - Windows Snapdragon: Same as Tegra
// - Asahi,Mali,PowerVR,Exynos,etc: Unknown behaviour
//
// This `__wine_set_unix_env` path may also not be long-term viable.
// Make sure to communicate with the Wine/Proton people if this interface is expected to change!
// A /possible/ workaround for Proton would be to set the environment variable in the launch script.
// - That would have the downside that arm64 native Windows applications would get workaround set, which isn't strictly necessary.
if (Sym && getenv("tu_override_uncached_as_cache_coherent") == nullptr) {
auto WineSetEnv = reinterpret_cast<decltype(__wine_set_unix_env)>(Sym);
WineSetEnv("tu_override_uncached_as_cache_coherent", "true");
}
}
} // namespace FEX::Windows
@@ -0,0 +1,7 @@
// SPDX-License-Identifier: MIT
#pragma once
#include <winternl.h>
namespace FEX::Windows {
void SetupEnvironmentVariableValues(HMODULE NtDll);
}
+3
View File
@@ -29,6 +29,7 @@ $end_info$
#include <FEXCore/Utils/SignalScopeGuards.h>
#include "Windows/Common/Allocator.h"
#include "Windows/Common/EnvironmentVariablesHandling.h"
#include "Common/CallRetStack.h"
#include "Common/JITGuardPage.h"
#include "Common/Config.h"
@@ -563,6 +564,8 @@ void BTCpuProcessInit() {
WineUnixCall = *reinterpret_cast<decltype(WineUnixCall)*>(Sym);
}
FEX::Windows::SetupEnvironmentVariableValues(NtDll);
// wow64.dll will only initialise the cross-process queue if this is set
GetTLS().Wow64Info().CpuFlags = WOW64_CPUFLAGS_SOFTWARE;
+2
View File
@@ -11,6 +11,8 @@ extern "C" {
typedef UINT64 unixlib_handle_t;
extern NTSTATUS(WINAPI* __wine_set_unix_env)(const char*, const char*);
extern NTSTATUS(WINAPI* __wine_unix_call_dispatcher)(unixlib_handle_t, unsigned int, void*);
static inline NTSTATUS __wine_unix_call(unixlib_handle_t handle, unsigned int code, void* args) {