Compare commits

..

15 Commits

Author SHA1 Message Date
lizzie ec56438ace 2026-09-24 01:05:18
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-24 01:05:18 +00:00
lizzie 727150d446 remove evil hacks: TODO: patch in later pr 2026-09-24 02:49:59 +02:00
lizzie 503573e896 no x11 find 2026-09-24 02:49:59 +02:00
lizzie 1f826f2218 extra portability adjustments 2026-09-24 02:49:59 +02:00
lizzie b100b47a2d let openbsd be fucked then i guess (FOR NOW) 2026-09-24 02:49:59 +02:00
lizzie 27dfa6037a fx 2026-09-24 02:49:59 +02:00
lizzie f527acaf9f qt diffs 2026-09-24 02:49:59 +02:00
lizzie 0cbc36be58 oops stray file 2026-09-24 02:49:59 +02:00
lizzie 11ae6496f3 oh, we were the ones doing it wrong, ok 2026-09-24 02:49:59 +02:00
lizzie c8db621706 correct qt6 instructions 2026-09-24 02:49:59 +02:00
lizzie 0830ca147f ok x11 fine 2026-09-24 02:49:59 +02:00
lizzie 7722ad07c7 nvm not x11::x11 2026-09-24 02:49:59 +02:00
lizzie 5b7cdef141 better x11 2026-09-24 02:49:59 +02:00
lizzie 39ebab267b [dynarmic] fix NetBSD builds on gcc14
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-24 02:49:59 +02:00
PavelBARABANOV cb73a4dcc7 [renderer_vulkan] Skip post-processing on applet layers (#4474)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------
Detect applet layers via the absence of the Recording bit in layer_stack_mask (only AppletId::Application sets it) and skip PostProcessChain creation and application for them.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4474
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: lizzie <lizzie@eden-emu.dev>
2026-09-24 02:48:46 +02:00
13 changed files with 60 additions and 78 deletions
+3 -15
View File
@@ -24,20 +24,8 @@ include(CMakeDependentOption)
include(CTest)
include(CPMUtil)
if (NOT DEFINED ARCHITECTURE)
message(FATAL_ERROR "Architecture didn't make it out of scope, did you delete DetectArchitecture.cmake?")
endif()
# Needed for FFmpeg w/ VAAPI and DRM
if (OPENBSD)
# OpenBSD 7.8 broke libcxx when upgrading, so we must define the PSTL backend manually
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${CMAKE_SYSROOT}/usr/X11R6/include -D_LIBCPP_PSTL_BACKEND_SERIAL=1")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I${CMAKE_SYSROOT}/usr/X11R6/include -D_LIBCPP_PSTL_BACKEND_SERIAL=1")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SYSROOT}/usr/X11R6/lib")
elseif (NETBSD)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${CMAKE_SYSROOT}/usr/X11R7/include -I${CMAKE_SYSROOT}/usr/pkg/include/c++/v1")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I${CMAKE_SYSROOT}/usr/X11R7/include -I${CMAKE_SYSROOT}/usr/pkg/include/c++/v1")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SYSROOT}/usr/X11R7/lib")
if (CXX_GCC AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "14.0")
message(FATAL_ERROR "GCC versions older than 14.0 are not supported. Update your system, or use clang/clang++ instead.")
endif()
# NetBSD: Fun for the whole family!
@@ -618,7 +606,7 @@ if (ENABLE_QT)
# Best practice is to ask for all components at once, so they are from the same version
set(YUZU_QT_COMPONENTS Core Widgets Charts Concurrent Gui)
if (LINUX OR FREEBSD)
if (NOT WIN32 AND NOT APPLE)
list(APPEND YUZU_QT_COMPONENTS DBus)
# yes Qt, we get it
set(QT_NO_PRIVATE_MODULE_WARNING ON)
+4 -6
View File
@@ -147,15 +147,13 @@ System provides a default `g++-10` which doesn't support the current C++ codebas
Make may error out when generating C++ headers of SPIRV shaders, hence it's recommended to use `gmake` over the default system one.
[parallel/spirv-tools](https://iso.us.netbsd.org/pub/pkgsrc/current/pkgsrc/parallel/spirv-tools/index.html) isn't available in binary form and must be built from source.
glslang is not available on NetBSD, to circumvent this simply build glslang by yourself:
If [parallel/spirv-tools](https://iso.us.netbsd.org/pub/pkgsrc/current/pkgsrc/parallel/spirv-tools/index.html) isn't available in binary, build from source:
```sh
pkgin python313
pkgin install python314
git clone --depth=1 https://github.com/KhronosGroup/glslang.git
cd glslang
python3.13 ./update_glslang_sources.py
python3.14 ./update_glslang_sources.py
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -- -j`nproc`
cmake --install build
@@ -163,7 +161,7 @@ cmake --install build
However, pkgsrc is highly recommended, see [getting pkgsrc](https://iso.us.netbsd.org/pub/pkgsrc/current/pkgsrc/doc/pkgsrc.html#getting). You must get `current` not the `2025Q2` version.
`QtCore` on NetBSD is included, but due to misconfigurations(!) we MUST include one of the standard headers that include `bits/c++config.h`, since source_location (required by `QtCore`) isn't properly configured to intake `bits/c++config.h` (none of the experimental library is). This is a bug with NetBSD packaging and not our fault, but alas.
`QtCore` on NetBSD is included, but due to misconfigurations you must include `bits/c++config.h`, since source_location (required by `QtCore`) isn't properly configured to intake `bits/c++config.h` (none of the experimental library is).
## DragonFlyBSD
+1 -1
View File
@@ -213,7 +213,7 @@ First, enable the community repository; [see here](https://wiki.alpinelinux.org/
# Enable the community repository
setup-apkrepos -c
# Install
apk add g++ git cmake make mesa-dev qt6-qtbase-dev qt6-qtbase-private-dev libquazip1-qt6 ffmpeg-dev qt6-charts-dev libusb-dev libtool boost-dev sdl3-dev zstd-dev vulkan-utility-libraries spirv-tools-dev openssl-dev nlohmann-json lz4-dev opus-dev jq patch
apk add g++ git cmake make mesa-dev qt6-qtbase-dev qt6-qtbase-private-dev libquazip1-qt6 ffmpeg-dev qt6-qtcharts-dev libusb-dev boost-dev sdl3-dev zstd-dev vulkan-utility-libraries spirv-tools-dev openssl-dev nlohmann-json lz4-dev opus-dev enet-dev glslang libtool jq patch
```
</details>
+1 -3
View File
@@ -67,9 +67,7 @@
#else
# define CTX_SP (_UC_MACHINE_SP(ucontext))
#endif
#endif
#if defined(ARCHITECTURE_arm64)
#elif defined(ARCHITECTURE_arm64)
# if defined(__APPLE__)
# define CTX_PC (mctx->__ss.__pc)
# define CTX_SP (mctx->__ss.__sp)
+1 -1
View File
@@ -92,7 +92,7 @@ if (ENABLE_OPENGL)
target_compile_definitions(qt_common PUBLIC HAS_OPENGL)
endif()
if (UNIX AND NOT APPLE)
if (UNIX AND NOT APPLE AND NOT NETBSD)
if (DEFINED Qt6Gui_PRIVATE_INCLUDE_DIRS)
target_include_directories(qt_common PRIVATE ${Qt6Gui_PRIVATE_INCLUDE_DIRS})
else()
+8 -15
View File
@@ -121,7 +121,7 @@ void BufferCache<P>::UnmapGPUMemory(size_t as_id, GPUVAddr gpu_addr, size_t size
template <class P>
void BufferCache<P>::WriteMemory(DAddr device_addr, u64 size) {
if (IsRegionGpuModified(device_addr, size)) {
if (memory_tracker.IsRegionGpuModified(device_addr, size)) {
ClearDownload(device_addr, size);
gpu_modified_ranges.Subtract(device_addr, size);
}
@@ -311,8 +311,11 @@ std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainCPUBuffer(
MarkWrittenBuffer(buffer_id, device_addr, size);
break;
case ObtainBufferOperation::DiscardWrite: {
ClearDownload(device_addr, size);
gpu_modified_ranges.Subtract(device_addr, size);
const DAddr device_addr_start = Common::AlignDown(device_addr, 64);
const DAddr device_addr_end = Common::AlignUp(device_addr + size, 64);
const size_t new_size = device_addr_end - device_addr_start;
ClearDownload(device_addr_start, new_size);
gpu_modified_ranges.Subtract(device_addr_start, new_size);
break;
}
default:
@@ -1739,24 +1742,14 @@ bool BufferCache<P>::SynchronizeBuffer(Buffer& buffer, DAddr device_addr, u32 si
u64 total_size_bytes = 0;
u64 largest_copy = 0;
const DAddr buffer_start = buffer.cpu_addr_cached;
const auto add_upload = [&](DAddr start, DAddr end) {
if (start == end) return;
const u64 range_size = end - start;
memory_tracker.ForEachUploadRange(device_addr, size, [&](u64 device_addr_out, u64 range_size) {
upload_copies.push_back(BufferCopy{
.src_offset = total_size_bytes,
.dst_offset = start - buffer_start,
.dst_offset = device_addr_out - buffer_start,
.size = range_size,
});
total_size_bytes += range_size;
largest_copy = (std::max)(largest_copy, range_size);
};
memory_tracker.ForEachUploadRange(device_addr, size, [&](u64 device_addr_out, u64 range_size) {
DAddr upload_start = device_addr_out;
gpu_modified_ranges.ForEachInRange(device_addr_out, range_size, [&](DAddr gpu_start, DAddr gpu_end) {
add_upload(upload_start, gpu_start);
upload_start = gpu_end;
});
add_upload(upload_start, device_addr_out + range_size);
});
if (total_size_bytes == 0) {
return true;
+5 -10
View File
@@ -16,7 +16,7 @@
namespace Tegra {
constexpr u32 MacroRegistersStart = 0xE00;
constexpr u32 ComputeInline = 0x6D;
[[maybe_unused]] constexpr u32 ComputeInline = 0x6D;
DmaPusher::DmaPusher(Core::System& system_, MemoryManager& memory_manager_, Control::ChannelState& channel_state_)
: system{system_}
@@ -73,16 +73,11 @@ bool DmaPusher::Step() {
synced = false;
}
if (header.size > 0 && dma_state.method >= MacroRegistersStart && subchannels[dma_state.subchannel]) {
subchannels[dma_state.subchannel]->current_dirty = memory_manager.IsMemoryDirty(dma_state.dma_get, header.size * sizeof(u32));
}
if (header.size > 0) {
if (subchannels[dma_state.subchannel] && dma_state.method_count) {
const auto engine = subchannel_type[dma_state.subchannel];
const bool kepler_payload = engine == Engines::EngineTypes::KeplerCompute && dma_state.method == ComputeInline && dma_state.non_incrementing;
const bool macro_payload = engine == Engines::EngineTypes::Maxwell3D && dma_state.method >= MacroRegistersStart;
if (kepler_payload || macro_payload) {
const size_t words = std::min<size_t>(dma_state.method_count, header.size);
subchannels[dma_state.subchannel]->current_dirty = memory_manager.IsMemoryDirty(dma_state.dma_get, words * sizeof(u32));
}
}
const bool use_safe = Settings::IsDMALevelDefault() ? Settings::IsGPULevelHigh() : Settings::IsDMALevelSafe();
if (use_safe) {
Tegra::Memory::GpuGuestMemory<Tegra::CommandHeader, Tegra::Memory::GuestMemoryFlags::SafeRead>headers(memory_manager, dma_state.dma_get, header.size, &command_headers);
+4 -11
View File
@@ -49,16 +49,13 @@ void KeplerCompute::CallMethod(Core::System& system, u32 method, u32 method_argu
case KEPLER_COMPUTE_REG_INDEX(exec_upload): {
UploadInfo info{.upload_address = upload_address,
.exec_address = upload_state.ExecTargetAddress(),
.copy_size = upload_state.GetUploadSize(),
.was_dirty = upload_dirty};
.copy_size = upload_state.GetUploadSize()};
uploads.push_back(info);
upload_state.ProcessExec(regs.exec_upload.linear != 0);
break;
}
case KEPLER_COMPUTE_REG_INDEX(data_upload): {
upload_address = current_dma_segment;
upload_dirty = current_dirty;
current_dirty = false;
upload_state.ProcessData(method_argument, is_last_call);
break;
}
@@ -67,11 +64,9 @@ void KeplerCompute::CallMethod(Core::System& system, u32 method, u32 method_argu
for (auto& data : uploads) {
const GPUVAddr offset = data.exec_address - launch_desc_loc;
if (offset / sizeof(u32) == LAUNCH_REG_INDEX(grid_dim_x)) {
const bool source_dirty = memory_manager.IsMemoryDirty(data.upload_address, data.copy_size);
if (data.was_dirty || source_dirty) {
indirect_compute = {data.upload_address};
}
if (offset / sizeof(u32) == LAUNCH_REG_INDEX(grid_dim_x) &&
memory_manager.IsMemoryDirty(data.upload_address, data.copy_size)) {
indirect_compute = {data.upload_address};
}
}
uploads.clear();
@@ -88,8 +83,6 @@ void KeplerCompute::CallMultiMethod(Core::System& system, u32 method, const u32*
switch (method) {
case KEPLER_COMPUTE_REG_INDEX(data_upload):
upload_address = current_dma_segment;
upload_dirty = current_dirty;
current_dirty = false;
upload_state.ProcessData(base_start, amount);
return;
default:
-2
View File
@@ -226,13 +226,11 @@ private:
VideoCore::RasterizerInterface* rasterizer = nullptr;
Upload::State upload_state;
GPUVAddr upload_address;
bool upload_dirty{};
struct UploadInfo {
GPUVAddr upload_address;
GPUVAddr exec_address;
u32 copy_size;
bool was_dirty;
};
std::vector<UploadInfo> uploads;
std::optional<GPUVAddr> indirect_compute{};
@@ -98,7 +98,10 @@ void Layer::ConfigureDraw(const Device& device, PresentPushConstants* out_push_c
RefreshResources(device, framebuffer);
SetAntiAliasPass(device);
#ifdef HAS_RESHADE
SetPostProcessPass(device);
const bool is_applet =
(framebuffer.layer_stack_mask & Service::Nvnflinger::LayerStackBit(
Service::Nvnflinger::LayerStackId::Recording)) == 0;
SetPostProcessPass(device, is_applet);
#endif
// Finish any pending renderpass
@@ -228,7 +231,11 @@ void Layer::SetAntiAliasPass(const Device& device) {
}
#ifdef HAS_RESHADE
void Layer::SetPostProcessPass(const Device& device) {
void Layer::SetPostProcessPass(const Device& device, bool is_applet) {
if (is_applet) {
post_process.reset();
return;
}
const VkExtent2D render_area{
.width = Settings::values.resolution_info.ScaleUp(raw_width),
.height = Settings::values.resolution_info.ScaleUp(raw_height),
@@ -70,7 +70,7 @@ private:
void RefreshResources(const Device& device, const Tegra::FramebufferConfig& framebuffer);
void SetAntiAliasPass(const Device& device);
#ifdef HAS_RESHADE
void SetPostProcessPass(const Device& device);
void SetPostProcessPass(const Device& device, bool is_applet);
#endif
void ReleaseRawImages();
@@ -43,26 +43,32 @@ namespace {
switch (window_type) {
case Core::Frontend::WindowSystemType::Headless:
break;
#ifdef _WIN32
#if defined(VK_USE_PLATFORM_WIN32_KHR)
case Core::Frontend::WindowSystemType::Windows:
extensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
break;
#elif defined(__APPLE__)
#endif
#if defined(VK_USE_PLATFORM_METAL_EXT)
case Core::Frontend::WindowSystemType::Cocoa:
extensions.push_back(VK_EXT_METAL_SURFACE_EXTENSION_NAME);
break;
#elif defined(__ANDROID__)
#endif
#if defined(VK_USE_PLATFORM_ANDROID_KHR)
case Core::Frontend::WindowSystemType::Android:
extensions.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
break;
#elif defined(__HAIKU__)
#endif
#if defined(VK_USE_PLATFORM_XCB_KHR)
case Core::Frontend::WindowSystemType::Xcb:
extensions.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
break;
#else
#endif
#if defined(VK_USE_PLATFORM_XLIB_KHR)
case Core::Frontend::WindowSystemType::X11:
extensions.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
break;
#endif
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
case Core::Frontend::WindowSystemType::Wayland:
extensions.push_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
break;
@@ -8,6 +8,7 @@
#include "core/frontend/emu_window.h"
#include "video_core/vulkan_common/vulkan_surface.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
#include "video_core/vulkan_common/vulkan.h"
namespace Vulkan {
@@ -17,7 +18,7 @@ vk::SurfaceKHR CreateSurface(
[[maybe_unused]] const vk::InstanceDispatch& dld = instance.Dispatch();
VkSurfaceKHR unsafe_surface = VkSurfaceKHR{};
#ifdef _WIN32
#if defined(VK_USE_PLATFORM_WIN32_KHR)
if (window_info.type == Core::Frontend::WindowSystemType::Windows) {
const HWND hWnd = static_cast<HWND>(window_info.render_surface);
const VkWin32SurfaceCreateInfoKHR win32_ci{VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR,
@@ -30,7 +31,8 @@ vk::SurfaceKHR CreateSurface(
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
}
}
#elif defined(__APPLE__)
#endif
#if defined(VK_USE_PLATFORM_METAL_EXT)
if (window_info.type == Core::Frontend::WindowSystemType::Cocoa) {
const VkMetalSurfaceCreateInfoEXT metal_ci = {
.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT,
@@ -45,7 +47,8 @@ vk::SurfaceKHR CreateSurface(
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
}
}
#elif defined(__ANDROID__)
#endif
#if defined(VK_USE_PLATFORM_ANDROID_KHR)
if (window_info.type == Core::Frontend::WindowSystemType::Android) {
const VkAndroidSurfaceCreateInfoKHR android_ci{
VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR, nullptr, 0,
@@ -59,7 +62,8 @@ vk::SurfaceKHR CreateSurface(
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
}
}
#elif defined(__HAIKU__)
#endif
#if defined(VK_USE_PLATFORM_XCB_KHR)
if (window_info.type == Core::Frontend::WindowSystemType::Xcb) {
const VkXcbSurfaceCreateInfoKHR xcb_ci{
.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR,
@@ -76,7 +80,8 @@ vk::SurfaceKHR CreateSurface(
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
}
}
#else
#endif
#if defined(VK_USE_PLATFORM_XLIB_KHR)
if (window_info.type == Core::Frontend::WindowSystemType::X11) {
const VkXlibSurfaceCreateInfoKHR xlib_ci{
VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, nullptr, 0,
@@ -90,6 +95,8 @@ vk::SurfaceKHR CreateSurface(
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
}
}
#endif
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
if (window_info.type == Core::Frontend::WindowSystemType::Wayland) {
const VkWaylandSurfaceCreateInfoKHR wayland_ci{
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR, nullptr, 0,
@@ -105,7 +112,6 @@ vk::SurfaceKHR CreateSurface(
}
}
#endif
if (!unsafe_surface) {
LOG_ERROR(Render_Vulkan, "Presentation not supported on this platform");
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);