mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-09-27 03:12:02 +00:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b03d6c58c2 | |||
| 2351265667 | |||
| ad4f210d88 | |||
| 5999302c69 | |||
| 2f896f6b44 | |||
| 6edeaa9b1e | |||
| 2f0c78d2dc | |||
| ec56438ace | |||
| 727150d446 | |||
| 503573e896 | |||
| 1f826f2218 | |||
| b100b47a2d | |||
| 27dfa6037a | |||
| f527acaf9f | |||
| 0cbc36be58 | |||
| 11ae6496f3 | |||
| c8db621706 | |||
| 0830ca147f | |||
| 7722ad07c7 | |||
| 5b7cdef141 | |||
| 39ebab267b |
+8
-18
@@ -24,20 +24,8 @@ include(CMakeDependentOption)
|
|||||||
include(CTest)
|
include(CTest)
|
||||||
include(CPMUtil)
|
include(CPMUtil)
|
||||||
|
|
||||||
if (NOT DEFINED ARCHITECTURE)
|
if (CXX_GCC AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "14.0")
|
||||||
message(FATAL_ERROR "Architecture didn't make it out of scope, did you delete DetectArchitecture.cmake?")
|
message(FATAL_ERROR "GCC versions older than 14.0 are not supported. Update your system, or use clang/clang++ instead.")
|
||||||
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")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# NetBSD: Fun for the whole family!
|
# NetBSD: Fun for the whole family!
|
||||||
@@ -85,7 +73,7 @@ option(ENABLE_WERROR "Enable -Werror diagnostics" ON)
|
|||||||
# Lossless Scaling frame generation. Only Android.
|
# Lossless Scaling frame generation. Only Android.
|
||||||
cmake_dependent_option(ENABLE_LSFG "Enable Lossless Scaling frame generation" ON "ANDROID" OFF)
|
cmake_dependent_option(ENABLE_LSFG "Enable Lossless Scaling frame generation" ON "ANDROID" OFF)
|
||||||
|
|
||||||
option(ENABLE_RESHADE "Enable ReShade FX post-processing effects" ON)
|
cmake_dependent_option(ENABLE_RESHADE "Enable ReShade FX post-processing effects" ON "WIN32 OR ANDROID OR APPLE OR LINUX OR FREEBSD" OFF)
|
||||||
|
|
||||||
# non-linux bundled qt are static
|
# non-linux bundled qt are static
|
||||||
if (YUZU_USE_BUNDLED_QT AND (APPLE OR NOT UNIX))
|
if (YUZU_USE_BUNDLED_QT AND (APPLE OR NOT UNIX))
|
||||||
@@ -276,7 +264,7 @@ cmake_dependent_option(YUZU_USE_BUNDLED_MOLTENVK "Download bundled MoltenVK lib"
|
|||||||
option(YUZU_DISABLE_LLVM "Disable LLVM (useful for CI)" OFF)
|
option(YUZU_DISABLE_LLVM "Disable LLVM (useful for CI)" OFF)
|
||||||
|
|
||||||
set(DEFAULT_YUZU_USE_BUNDLED_OPENSSL OFF)
|
set(DEFAULT_YUZU_USE_BUNDLED_OPENSSL OFF)
|
||||||
if (EXT_DEFAULT OR SOLARIS OR OPENBSD)
|
if (EXT_DEFAULT)
|
||||||
set(DEFAULT_YUZU_USE_BUNDLED_OPENSSL ON)
|
set(DEFAULT_YUZU_USE_BUNDLED_OPENSSL ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -309,10 +297,12 @@ if (YUZU_ROOM)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (UNIX AND NOT (LINUX OR WIN32))
|
if (UNIX AND NOT (LINUX OR WIN32))
|
||||||
if(CXX_APPLE OR CXX_CLANG)
|
if(CXX_APPLE OR (CXX_CLANG AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "20.0"))
|
||||||
# libc++ has stop_token and jthread as experimental
|
# libc++ has stop_token and jthread as experimental
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexperimental-library")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexperimental-library")
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fexperimental-library")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fexperimental-library")
|
||||||
|
elseif(CXX_CLANG)
|
||||||
|
# New clang >=20.0, so do nothing
|
||||||
else()
|
else()
|
||||||
# Uses glibc, mostly?
|
# Uses glibc, mostly?
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_LIBCPP_ENABLE_EXPERIMENTAL=1")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_LIBCPP_ENABLE_EXPERIMENTAL=1")
|
||||||
@@ -618,7 +608,7 @@ if (ENABLE_QT)
|
|||||||
|
|
||||||
# Best practice is to ask for all components at once, so they are from the same version
|
# 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)
|
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)
|
list(APPEND YUZU_QT_COMPONENTS DBus)
|
||||||
# yes Qt, we get it
|
# yes Qt, we get it
|
||||||
set(QT_NO_PRIVATE_MODULE_WARNING ON)
|
set(QT_NO_PRIVATE_MODULE_WARNING ON)
|
||||||
|
|||||||
+11
-17
@@ -65,7 +65,7 @@ export LIBGL_ALWAYS_SOFTWARE=1
|
|||||||
|
|
||||||
## OmniOS
|
## OmniOS
|
||||||
|
|
||||||
Install `developer/gcc14` on OmniOS using pkgsrc.
|
Install `developer/gcc15` on OmniOS using pkgsrc.
|
||||||
|
|
||||||
Since so many dependencies are missing on `OmniOS`, you may wish to use `-DCPMUTIL_FORCE_BUNDLED=ON` and `-DYUZU_USE_BUNDLED_OPENSSL=OFF`.
|
Since so many dependencies are missing on `OmniOS`, you may wish to use `-DCPMUTIL_FORCE_BUNDLED=ON` and `-DYUZU_USE_BUNDLED_OPENSSL=OFF`.
|
||||||
|
|
||||||
@@ -74,21 +74,15 @@ For OmniOS you are required to build glslang yourself:
|
|||||||
sudo pkg install python-313
|
sudo pkg install python-313
|
||||||
git clone --depth=1 https://github.com/KhronosGroup/glslang.git
|
git clone --depth=1 https://github.com/KhronosGroup/glslang.git
|
||||||
cd glslang
|
cd glslang
|
||||||
python3.13 ./update_glslang_sources.py
|
python3 ./update_glslang_sources.py
|
||||||
cmake -B build -DCMAKE_BUILD_TYPE=Release
|
cmake -B build -DCMAKE_BUILD_TYPE=Release
|
||||||
cmake --build build -- -j `nproc`
|
cmake --build build -- -j`nproc`
|
||||||
cmake --install build
|
cmake --install build
|
||||||
```
|
```
|
||||||
|
|
||||||
It may be tempting to specify `-t glslang`, but this will cause installation to fail. So don't.
|
Use `gmake` to properly build all utilities. You require an X11 server, [this guide](https://web.archive.org/web/20260424200928/https://geekblood.wordpress.com/2017/10/26/installing-x11-and-a-desktop-environment-on-omnios/) details how to attain one, the links to pkgsrc on said guide [are better found here](https://pkgsrc.smartos.org/install-on-illumos/).
|
||||||
|
|
||||||
Using `--parallel` on CMake incorrectly passes `dmake ... -jn` instead of `dmake ... -j n`, this is a bug with OmniOS's CMake, it's recommended to not use this option until it's fixed.
|
For Solaris based OSes, `${CMAKE_SYSTEM_PROCESSOR}` isn't properly set on CMake (it's set to i686 on AMD64, must be `amd64`), you may find issues when building OpenSSL from `openssl-cmake`.
|
||||||
|
|
||||||
You may also need to install `gmake` in order to properly build FFmpeg, this is provided by the `build-essential` package.
|
|
||||||
|
|
||||||
If it wasn't obvious already, you require a X11 server to properly run the emulator within OmniOS, [this guide](https://web.archive.org/web/20260424200928/https://geekblood.wordpress.com/2017/10/26/installing-x11-and-a-desktop-environment-on-omnios/) is a great starting point for that, the links to pkgsrc are outdated so follow [this exemplar](https://pkgsrc.smartos.org/install-on-illumos/) as well.
|
|
||||||
|
|
||||||
For Solaris based OSes, `${CMAKE_SYSTEM_NAME}` isn't properly set on CMake (it's set to i686 on AMD64), you may find issues when building OpenSSL from `openssl-cmake`.
|
|
||||||
|
|
||||||
## HaikuOS
|
## HaikuOS
|
||||||
|
|
||||||
@@ -108,6 +102,8 @@ If you have `quazip1_qt6_devel`, uninstall it. It may call `Core5Compat` on CMak
|
|||||||
|
|
||||||
## OpenBSD
|
## OpenBSD
|
||||||
|
|
||||||
|
OpenSSL 4.0 is available via ports, needs to be pointed to directly via `-DOPENSSL_ROOT_DIR=/usr/local/include/eopenssl40`.
|
||||||
|
|
||||||
System boost doesn't have `context` (as of 7.8); so you may need to specify `-DYUZU_USE_CPM=ON -DBoost_FORCE_BUNDLED=ON`.
|
System boost doesn't have `context` (as of 7.8); so you may need to specify `-DYUZU_USE_CPM=ON -DBoost_FORCE_BUNDLED=ON`.
|
||||||
|
|
||||||
After configuration, you may need to modify `externals/ffmpeg/CMakeFiles/ffmpeg-build/build.make` to use `-j$(nproc)` instead of just `-j`.
|
After configuration, you may need to modify `externals/ffmpeg/CMakeFiles/ffmpeg-build/build.make` to use `-j$(nproc)` instead of just `-j`.
|
||||||
@@ -147,15 +143,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.
|
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.
|
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:
|
||||||
|
|
||||||
glslang is not available on NetBSD, to circumvent this simply build glslang by yourself:
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
pkgin python313
|
pkgin install python314
|
||||||
git clone --depth=1 https://github.com/KhronosGroup/glslang.git
|
git clone --depth=1 https://github.com/KhronosGroup/glslang.git
|
||||||
cd glslang
|
cd glslang
|
||||||
python3.13 ./update_glslang_sources.py
|
python3.14 ./update_glslang_sources.py
|
||||||
cmake -B build -DCMAKE_BUILD_TYPE=Release
|
cmake -B build -DCMAKE_BUILD_TYPE=Release
|
||||||
cmake --build build -- -j`nproc`
|
cmake --build build -- -j`nproc`
|
||||||
cmake --install build
|
cmake --install build
|
||||||
@@ -163,7 +157,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.
|
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
|
## DragonFlyBSD
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -213,7 +213,7 @@ First, enable the community repository; [see here](https://wiki.alpinelinux.org/
|
|||||||
# Enable the community repository
|
# Enable the community repository
|
||||||
setup-apkrepos -c
|
setup-apkrepos -c
|
||||||
# Install
|
# 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>
|
</details>
|
||||||
@@ -286,7 +286,7 @@ pkgin install git cmake boost fmtlib SDL3 catch2 libjwt spirv-headers spirv-tool
|
|||||||
|
|
||||||
```sh
|
```sh
|
||||||
pkg_add -u
|
pkg_add -u
|
||||||
pkg_add cmake nasm git boost unzip--iconv autoconf-2.72p0 bash ffmpeg glslang gmake qt6 jq fmt nlohmann-json enet boost vulkan-utility-libraries vulkan-headers spirv-headers spirv-tools catch2 sdl3 libusb1-1.0.29 quazip-qt6
|
pkg_add cmake nasm git boost unzip--iconv autoconf-2.72p0 bash ffmpeg glslang gmake qt6 jq fmt nlohmann-json enet boost vulkan-utility-libraries vulkan-headers spirv-headers spirv-tools catch2 sdl3 libusb1-1.0.29 quazip-qt6 openssl-4.0.2v0
|
||||||
```
|
```
|
||||||
|
|
||||||
[Caveats](./Caveats.md#openbsd).
|
[Caveats](./Caveats.md#openbsd).
|
||||||
@@ -316,7 +316,7 @@ sudo pkg install git cmake qt6 boost glslang libzip library/lz4 libusb-1 nlohman
|
|||||||
<summary>OmniOS</summary>
|
<summary>OmniOS</summary>
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sudo pkgin install git cmake autoconf build-essential libusb-1 nasm gcc13
|
sudo pkg install git cmake autoconf build-essential libusb-1 nasm gcc15 ffmpeg lz4 pkg-config unzip bash jq xsvc
|
||||||
```
|
```
|
||||||
|
|
||||||
[Caveats](./Caveats.md#omnios).
|
[Caveats](./Caveats.md#omnios).
|
||||||
|
|||||||
Vendored
+1
-1
@@ -15,7 +15,7 @@
|
|||||||
## Cloning Eden with Git
|
## Cloning Eden with Git
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
git clone --recursive https://git.eden-emu.dev/eden-emu/eden.git
|
git clone --depth=1 https://git.eden-emu.dev/eden-emu/eden.git
|
||||||
```
|
```
|
||||||
|
|
||||||
Eden by default will be cloned into:
|
Eden by default will be cloned into:
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ add_library(
|
|||||||
logging.h
|
logging.h
|
||||||
lz4_compression.cpp
|
lz4_compression.cpp
|
||||||
lz4_compression.h
|
lz4_compression.h
|
||||||
|
make_unique_for_overwrite.h
|
||||||
math_util.h
|
math_util.h
|
||||||
memory_detect.cpp
|
memory_detect.cpp
|
||||||
memory_detect.h
|
memory_detect.h
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
requires(!std::is_array_v<T>)
|
||||||
|
std::unique_ptr<T> make_unique_for_overwrite() {
|
||||||
|
return std::unique_ptr<T>(new T);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
requires std::is_unbounded_array_v<T>
|
||||||
|
std::unique_ptr<T> make_unique_for_overwrite(std::size_t n) {
|
||||||
|
return std::unique_ptr<T>(new std::remove_extent_t<T>[n]);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, class... Args>
|
||||||
|
requires std::is_bounded_array_v<T>
|
||||||
|
void make_unique_for_overwrite(Args&&...) = delete;
|
||||||
|
|
||||||
|
} // namespace Common
|
||||||
@@ -8,7 +8,8 @@
|
|||||||
|
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <memory>
|
|
||||||
|
#include "common/make_unique_for_overwrite.h"
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
@@ -37,9 +38,8 @@ public:
|
|||||||
ScratchBuffer() = default;
|
ScratchBuffer() = default;
|
||||||
|
|
||||||
explicit ScratchBuffer(size_type initial_capacity)
|
explicit ScratchBuffer(size_type initial_capacity)
|
||||||
: last_requested_size{initial_capacity}
|
: last_requested_size{initial_capacity}, buffer_capacity{initial_capacity},
|
||||||
, buffer_capacity{initial_capacity}
|
buffer{Common::make_unique_for_overwrite<T[]>(initial_capacity)} {}
|
||||||
, buffer{std::make_unique_for_overwrite<T[]>(initial_capacity)} {}
|
|
||||||
|
|
||||||
~ScratchBuffer() = default;
|
~ScratchBuffer() = default;
|
||||||
ScratchBuffer(const ScratchBuffer&) = delete;
|
ScratchBuffer(const ScratchBuffer&) = delete;
|
||||||
@@ -64,7 +64,7 @@ public:
|
|||||||
/// The previously held data will remain intact.
|
/// The previously held data will remain intact.
|
||||||
void resize(size_type size) {
|
void resize(size_type size) {
|
||||||
if (size > buffer_capacity) {
|
if (size > buffer_capacity) {
|
||||||
auto new_buffer = std::make_unique_for_overwrite<T[]>(size);
|
auto new_buffer = Common::make_unique_for_overwrite<T[]>(size);
|
||||||
std::memcpy(new_buffer.get(), buffer.get(), buffer_capacity * sizeof(T));
|
std::memcpy(new_buffer.get(), buffer.get(), buffer_capacity * sizeof(T));
|
||||||
buffer = std::move(new_buffer);
|
buffer = std::move(new_buffer);
|
||||||
buffer_capacity = size;
|
buffer_capacity = size;
|
||||||
@@ -77,7 +77,7 @@ public:
|
|||||||
void resize_destructive(size_type size) {
|
void resize_destructive(size_type size) {
|
||||||
if (size > buffer_capacity) {
|
if (size > buffer_capacity) {
|
||||||
buffer_capacity = size;
|
buffer_capacity = size;
|
||||||
buffer = std::make_unique_for_overwrite<T[]>(buffer_capacity);
|
buffer = Common::make_unique_for_overwrite<T[]>(buffer_capacity);
|
||||||
}
|
}
|
||||||
last_requested_size = size;
|
last_requested_size = size;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,7 +109,8 @@ VirtualFile RealVfsFilesystem::OpenFileFromEntry(std::string_view path_, std::op
|
|||||||
auto reference = std::make_unique<FileReference>();
|
auto reference = std::make_unique<FileReference>();
|
||||||
this->InsertReferenceIntoListLocked(*reference);
|
this->InsertReferenceIntoListLocked(*reference);
|
||||||
|
|
||||||
auto file = std::make_shared<RealVfsFile>(*this, std::move(reference), path, perms, size, std::move(parent_path));
|
auto file = std::shared_ptr<RealVfsFile>(
|
||||||
|
new RealVfsFile(*this, std::move(reference), path, perms, size, std::move(parent_path)));
|
||||||
cache[path] = file;
|
cache[path] = file;
|
||||||
|
|
||||||
return file;
|
return file;
|
||||||
@@ -176,7 +177,7 @@ bool RealVfsFilesystem::DeleteFile(std::string_view path_) {
|
|||||||
|
|
||||||
VirtualDir RealVfsFilesystem::OpenDirectory(std::string_view path_, OpenMode perms) {
|
VirtualDir RealVfsFilesystem::OpenDirectory(std::string_view path_, OpenMode perms) {
|
||||||
const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault);
|
const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault);
|
||||||
return std::make_shared<RealVfsDirectory>(*this, path, perms);
|
return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms));
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualDir RealVfsFilesystem::CreateDirectory(std::string_view path_, OpenMode perms) {
|
VirtualDir RealVfsFilesystem::CreateDirectory(std::string_view path_, OpenMode perms) {
|
||||||
@@ -184,7 +185,7 @@ VirtualDir RealVfsFilesystem::CreateDirectory(std::string_view path_, OpenMode p
|
|||||||
if (!FS::CreateDirs(path)) {
|
if (!FS::CreateDirs(path)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return std::make_shared<RealVfsDirectory>(*this, path, perms);
|
return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms));
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualDir RealVfsFilesystem::CopyDirectory(std::string_view old_path_,
|
VirtualDir RealVfsFilesystem::CopyDirectory(std::string_view old_path_,
|
||||||
|
|||||||
@@ -82,9 +82,6 @@ class RealVfsFile : public VfsFile {
|
|||||||
friend class RealVfsFilesystem;
|
friend class RealVfsFilesystem;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RealVfsFile(RealVfsFilesystem& base, std::unique_ptr<FileReference> reference,
|
|
||||||
const std::string& path, OpenMode perms = OpenMode::Read,
|
|
||||||
std::optional<u64> size = {}, std::optional<std::string> parent_path = {});
|
|
||||||
~RealVfsFile() override;
|
~RealVfsFile() override;
|
||||||
|
|
||||||
std::string GetName() const override;
|
std::string GetName() const override;
|
||||||
@@ -98,6 +95,9 @@ public:
|
|||||||
bool Rename(std::string_view name) override;
|
bool Rename(std::string_view name) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
RealVfsFile(RealVfsFilesystem& base, std::unique_ptr<FileReference> reference,
|
||||||
|
const std::string& path, OpenMode perms = OpenMode::Read,
|
||||||
|
std::optional<u64> size = {}, std::optional<std::string> parent_path = {});
|
||||||
|
|
||||||
RealVfsFilesystem& base;
|
RealVfsFilesystem& base;
|
||||||
std::unique_ptr<FileReference> reference;
|
std::unique_ptr<FileReference> reference;
|
||||||
@@ -113,8 +113,6 @@ class RealVfsDirectory : public VfsDirectory {
|
|||||||
friend class RealVfsFilesystem;
|
friend class RealVfsFilesystem;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RealVfsDirectory(RealVfsFilesystem& base, const std::string& path,
|
|
||||||
OpenMode perms = OpenMode::Read);
|
|
||||||
~RealVfsDirectory() override;
|
~RealVfsDirectory() override;
|
||||||
|
|
||||||
VirtualFile GetFileRelative(std::string_view relative_path) const override;
|
VirtualFile GetFileRelative(std::string_view relative_path) const override;
|
||||||
@@ -140,6 +138,9 @@ public:
|
|||||||
std::map<std::string, VfsEntryType, std::less<>> GetEntries() const override;
|
std::map<std::string, VfsEntryType, std::less<>> GetEntries() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
RealVfsDirectory(RealVfsFilesystem& base, const std::string& path,
|
||||||
|
OpenMode perms = OpenMode::Read);
|
||||||
|
|
||||||
template <typename T, typename R>
|
template <typename T, typename R>
|
||||||
std::vector<std::shared_ptr<R>> IterateEntries() const;
|
std::vector<std::shared_ptr<R>> IterateEntries() const;
|
||||||
|
|
||||||
|
|||||||
@@ -517,7 +517,7 @@ void WindowSystem::UpdateAppletStateLocked(Applet* applet, bool is_foreground, b
|
|||||||
// Layer ordering. Composition sorts back-to-front. Now with enums for calrity.
|
// Layer ordering. Composition sorts back-to-front. Now with enums for calrity.
|
||||||
s32 z_index = Background;
|
s32 z_index = Background;
|
||||||
if (is_overlay) {
|
if (is_overlay) {
|
||||||
z_index = this->IsOverlayOpenLocked(*applet) ? Overlay : Background;
|
z_index = Overlay;
|
||||||
} else if (inherited_foreground) {
|
} else if (inherited_foreground) {
|
||||||
z_index = is_obscured ? Foreground : ForegroundVisible;
|
z_index = is_obscured ? Foreground : ForegroundVisible;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
@@ -24,7 +24,7 @@ IReceiverService::~IReceiverService() = default;
|
|||||||
|
|
||||||
Result IReceiverService::OpenReceiver(Out<SharedPointer<IReceiver>> out_receiver) {
|
Result IReceiverService::OpenReceiver(Out<SharedPointer<IReceiver>> out_receiver) {
|
||||||
LOG_DEBUG(Service_PSC, "called");
|
LOG_DEBUG(Service_PSC, "called");
|
||||||
*out_receiver = std::make_shared<IReceiver>(system);
|
*out_receiver = std::shared_ptr<IReceiver>(new IReceiver(system));
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,9 +67,7 @@
|
|||||||
#else
|
#else
|
||||||
# define CTX_SP (_UC_MACHINE_SP(ucontext))
|
# define CTX_SP (_UC_MACHINE_SP(ucontext))
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#elif defined(ARCHITECTURE_arm64)
|
||||||
|
|
||||||
#if defined(ARCHITECTURE_arm64)
|
|
||||||
# if defined(__APPLE__)
|
# if defined(__APPLE__)
|
||||||
# define CTX_PC (mctx->__ss.__pc)
|
# define CTX_PC (mctx->__ss.__pc)
|
||||||
# define CTX_SP (mctx->__ss.__sp)
|
# define CTX_SP (mctx->__ss.__sp)
|
||||||
|
|||||||
@@ -45,19 +45,6 @@ NPad::NPad(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service
|
|||||||
AbstractPad{hid_core_.kernel},
|
AbstractPad{hid_core_.kernel},
|
||||||
}}
|
}}
|
||||||
{
|
{
|
||||||
for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; ++aruid_index) {
|
|
||||||
for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) {
|
|
||||||
auto& controller = controller_data[aruid_index][i];
|
|
||||||
controller.device = hid_core.GetEmulatedControllerByIndex(i);
|
|
||||||
Core::HID::ControllerUpdateCallback engine_callback{
|
|
||||||
.on_change = [this, i, kernel = &hid_core.kernel](Core::HID::ControllerTriggerType type) {
|
|
||||||
ControllerUpdate(*kernel, type, i);
|
|
||||||
},
|
|
||||||
.is_npad_service = true,
|
|
||||||
};
|
|
||||||
controller.callback_key = controller.device->SetCallback(engine_callback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (std::size_t i = 0; i < abstracted_pads.size(); ++i) {
|
for (std::size_t i = 0; i < abstracted_pads.size(); ++i) {
|
||||||
abstracted_pads[i].SetNpadId(IndexToNpadIdType(i));
|
abstracted_pads[i].SetNpadId(IndexToNpadIdType(i));
|
||||||
}
|
}
|
||||||
@@ -106,6 +93,16 @@ Result NPad::Activate(u64 aruid) {
|
|||||||
for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) {
|
for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) {
|
||||||
auto& controller = controller_data[aruid_index][i];
|
auto& controller = controller_data[aruid_index][i];
|
||||||
controller.shared_memory = &data->shared_memory_format->npad.npad_entry[i].internal_state;
|
controller.shared_memory = &data->shared_memory_format->npad.npad_entry[i].internal_state;
|
||||||
|
controller.device = hid_core.GetEmulatedControllerByIndex(i);
|
||||||
|
if (!controller.callback_key) {
|
||||||
|
Core::HID::ControllerUpdateCallback engine_callback{
|
||||||
|
.on_change = [this, i](Core::HID::ControllerTriggerType type) {
|
||||||
|
ControllerUpdate(hid_core.kernel, type, i);
|
||||||
|
},
|
||||||
|
.is_npad_service = true,
|
||||||
|
};
|
||||||
|
controller.callback_key = controller.device->SetCallback(engine_callback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prefill controller buffers
|
// Prefill controller buffers
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
#include "common/bit_field.h"
|
#include "common/bit_field.h"
|
||||||
#include "common/common_funcs.h"
|
#include "common/common_funcs.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ if (ENABLE_OPENGL)
|
|||||||
target_compile_definitions(qt_common PUBLIC HAS_OPENGL)
|
target_compile_definitions(qt_common PUBLIC HAS_OPENGL)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (UNIX AND NOT APPLE)
|
if (LINUX OR FREEBSD)
|
||||||
if (DEFINED Qt6Gui_PRIVATE_INCLUDE_DIRS)
|
if (DEFINED Qt6Gui_PRIVATE_INCLUDE_DIRS)
|
||||||
target_include_directories(qt_common PRIVATE ${Qt6Gui_PRIVATE_INCLUDE_DIRS})
|
target_include_directories(qt_common PRIVATE ${Qt6Gui_PRIVATE_INCLUDE_DIRS})
|
||||||
else()
|
else()
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ void BufferCache<P>::UnmapGPUMemory(size_t as_id, GPUVAddr gpu_addr, size_t size
|
|||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
void BufferCache<P>::WriteMemory(DAddr device_addr, u64 size) {
|
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);
|
ClearDownload(device_addr, size);
|
||||||
gpu_modified_ranges.Subtract(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);
|
MarkWrittenBuffer(buffer_id, device_addr, size);
|
||||||
break;
|
break;
|
||||||
case ObtainBufferOperation::DiscardWrite: {
|
case ObtainBufferOperation::DiscardWrite: {
|
||||||
ClearDownload(device_addr, size);
|
const DAddr device_addr_start = Common::AlignDown(device_addr, 64);
|
||||||
gpu_modified_ranges.Subtract(device_addr, size);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -1739,24 +1742,14 @@ bool BufferCache<P>::SynchronizeBuffer(Buffer& buffer, DAddr device_addr, u32 si
|
|||||||
u64 total_size_bytes = 0;
|
u64 total_size_bytes = 0;
|
||||||
u64 largest_copy = 0;
|
u64 largest_copy = 0;
|
||||||
const DAddr buffer_start = buffer.cpu_addr_cached;
|
const DAddr buffer_start = buffer.cpu_addr_cached;
|
||||||
const auto add_upload = [&](DAddr start, DAddr end) {
|
memory_tracker.ForEachUploadRange(device_addr, size, [&](u64 device_addr_out, u64 range_size) {
|
||||||
if (start == end) return;
|
|
||||||
const u64 range_size = end - start;
|
|
||||||
upload_copies.push_back(BufferCopy{
|
upload_copies.push_back(BufferCopy{
|
||||||
.src_offset = total_size_bytes,
|
.src_offset = total_size_bytes,
|
||||||
.dst_offset = start - buffer_start,
|
.dst_offset = device_addr_out - buffer_start,
|
||||||
.size = range_size,
|
.size = range_size,
|
||||||
});
|
});
|
||||||
total_size_bytes += range_size;
|
total_size_bytes += range_size;
|
||||||
largest_copy = (std::max)(largest_copy, 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) {
|
if (total_size_bytes == 0) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
|
|
||||||
constexpr u32 MacroRegistersStart = 0xE00;
|
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_)
|
DmaPusher::DmaPusher(Core::System& system_, MemoryManager& memory_manager_, Control::ChannelState& channel_state_)
|
||||||
: system{system_}
|
: system{system_}
|
||||||
@@ -73,16 +73,11 @@ bool DmaPusher::Step() {
|
|||||||
synced = false;
|
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 (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();
|
const bool use_safe = Settings::IsDMALevelDefault() ? Settings::IsGPULevelHigh() : Settings::IsDMALevelSafe();
|
||||||
if (use_safe) {
|
if (use_safe) {
|
||||||
Tegra::Memory::GpuGuestMemory<Tegra::CommandHeader, Tegra::Memory::GuestMemoryFlags::SafeRead>headers(memory_manager, dma_state.dma_get, header.size, &command_headers);
|
Tegra::Memory::GpuGuestMemory<Tegra::CommandHeader, Tegra::Memory::GuestMemoryFlags::SafeRead>headers(memory_manager, dma_state.dma_get, header.size, &command_headers);
|
||||||
|
|||||||
@@ -49,16 +49,13 @@ void KeplerCompute::CallMethod(Core::System& system, u32 method, u32 method_argu
|
|||||||
case KEPLER_COMPUTE_REG_INDEX(exec_upload): {
|
case KEPLER_COMPUTE_REG_INDEX(exec_upload): {
|
||||||
UploadInfo info{.upload_address = upload_address,
|
UploadInfo info{.upload_address = upload_address,
|
||||||
.exec_address = upload_state.ExecTargetAddress(),
|
.exec_address = upload_state.ExecTargetAddress(),
|
||||||
.copy_size = upload_state.GetUploadSize(),
|
.copy_size = upload_state.GetUploadSize()};
|
||||||
.was_dirty = upload_dirty};
|
|
||||||
uploads.push_back(info);
|
uploads.push_back(info);
|
||||||
upload_state.ProcessExec(regs.exec_upload.linear != 0);
|
upload_state.ProcessExec(regs.exec_upload.linear != 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case KEPLER_COMPUTE_REG_INDEX(data_upload): {
|
case KEPLER_COMPUTE_REG_INDEX(data_upload): {
|
||||||
upload_address = current_dma_segment;
|
upload_address = current_dma_segment;
|
||||||
upload_dirty = current_dirty;
|
|
||||||
current_dirty = false;
|
|
||||||
upload_state.ProcessData(method_argument, is_last_call);
|
upload_state.ProcessData(method_argument, is_last_call);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -67,11 +64,9 @@ void KeplerCompute::CallMethod(Core::System& system, u32 method, u32 method_argu
|
|||||||
|
|
||||||
for (auto& data : uploads) {
|
for (auto& data : uploads) {
|
||||||
const GPUVAddr offset = data.exec_address - launch_desc_loc;
|
const GPUVAddr offset = data.exec_address - launch_desc_loc;
|
||||||
if (offset / sizeof(u32) == LAUNCH_REG_INDEX(grid_dim_x)) {
|
if (offset / sizeof(u32) == LAUNCH_REG_INDEX(grid_dim_x) &&
|
||||||
const bool source_dirty = memory_manager.IsMemoryDirty(data.upload_address, data.copy_size);
|
memory_manager.IsMemoryDirty(data.upload_address, data.copy_size)) {
|
||||||
if (data.was_dirty || source_dirty) {
|
indirect_compute = {data.upload_address};
|
||||||
indirect_compute = {data.upload_address};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uploads.clear();
|
uploads.clear();
|
||||||
@@ -88,8 +83,6 @@ void KeplerCompute::CallMultiMethod(Core::System& system, u32 method, const u32*
|
|||||||
switch (method) {
|
switch (method) {
|
||||||
case KEPLER_COMPUTE_REG_INDEX(data_upload):
|
case KEPLER_COMPUTE_REG_INDEX(data_upload):
|
||||||
upload_address = current_dma_segment;
|
upload_address = current_dma_segment;
|
||||||
upload_dirty = current_dirty;
|
|
||||||
current_dirty = false;
|
|
||||||
upload_state.ProcessData(base_start, amount);
|
upload_state.ProcessData(base_start, amount);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -226,13 +226,11 @@ private:
|
|||||||
VideoCore::RasterizerInterface* rasterizer = nullptr;
|
VideoCore::RasterizerInterface* rasterizer = nullptr;
|
||||||
Upload::State upload_state;
|
Upload::State upload_state;
|
||||||
GPUVAddr upload_address;
|
GPUVAddr upload_address;
|
||||||
bool upload_dirty{};
|
|
||||||
|
|
||||||
struct UploadInfo {
|
struct UploadInfo {
|
||||||
GPUVAddr upload_address;
|
GPUVAddr upload_address;
|
||||||
GPUVAddr exec_address;
|
GPUVAddr exec_address;
|
||||||
u32 copy_size;
|
u32 copy_size;
|
||||||
bool was_dirty;
|
|
||||||
};
|
};
|
||||||
std::vector<UploadInfo> uploads;
|
std::vector<UploadInfo> uploads;
|
||||||
std::optional<GPUVAddr> indirect_compute{};
|
std::optional<GPUVAddr> indirect_compute{};
|
||||||
|
|||||||
@@ -94,13 +94,13 @@ void Layer::ConfigureDraw(const Device& device, PresentPushConstants* out_push_c
|
|||||||
const u32 scaled_width = texture_info ? texture_info->scaled_width : texture_width;
|
const u32 scaled_width = texture_info ? texture_info->scaled_width : texture_width;
|
||||||
const u32 scaled_height = texture_info ? texture_info->scaled_height : texture_height;
|
const u32 scaled_height = texture_info ? texture_info->scaled_height : texture_height;
|
||||||
const bool use_accelerated = texture_info.has_value();
|
const bool use_accelerated = texture_info.has_value();
|
||||||
const bool is_applet =
|
|
||||||
(framebuffer.layer_stack_mask & Service::Nvnflinger::LayerStackBit(
|
|
||||||
Service::Nvnflinger::LayerStackId::Recording)) == 0;
|
|
||||||
|
|
||||||
RefreshResources(device, framebuffer);
|
RefreshResources(device, framebuffer);
|
||||||
SetAntiAliasPass(device);
|
SetAntiAliasPass(device);
|
||||||
#ifdef HAS_RESHADE
|
#ifdef HAS_RESHADE
|
||||||
|
const bool is_applet =
|
||||||
|
(framebuffer.layer_stack_mask & Service::Nvnflinger::LayerStackBit(
|
||||||
|
Service::Nvnflinger::LayerStackId::Recording)) == 0;
|
||||||
SetPostProcessPass(device, is_applet);
|
SetPostProcessPass(device, is_applet);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -141,11 +141,8 @@ void Layer::ConfigureDraw(const Device& device, PresentPushConstants* out_push_c
|
|||||||
source_image_view = fsr->Draw(device, scheduler, image_index, source_image, source_image_view, render_extent, crop_rect);
|
source_image_view = fsr->Draw(device, scheduler, image_index, source_image, source_image_view, render_extent, crop_rect);
|
||||||
crop_rect = {0, 0, 1, 1};
|
crop_rect = {0, 0, 1, 1};
|
||||||
} else if (auto* sgsr = std::get_if<SGSR>(&sr_filter)) {
|
} else if (auto* sgsr = std::get_if<SGSR>(&sr_filter)) {
|
||||||
if (!is_applet) {
|
source_image_view = sgsr->Draw(device, scheduler, image_index, source_image, source_image_view, render_extent, crop_rect);
|
||||||
source_image_view = sgsr->Draw(device, scheduler, image_index, source_image,
|
crop_rect = {0, 0, 1, 1};
|
||||||
source_image_view, render_extent, crop_rect);
|
|
||||||
crop_rect = {0, 0, 1, 1};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SetMatrixData(device, *out_push_constants, layout);
|
SetMatrixData(device, *out_push_constants, layout);
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ public:
|
|||||||
if (host_visible) {
|
if (host_visible) {
|
||||||
return StagingBufferRef{};
|
return StagingBufferRef{};
|
||||||
}
|
}
|
||||||
return staging_pool.Request(device, size_bytes, MemoryUsage::Upload);
|
return staging_pool.Request(size_bytes, MemoryUsage::Upload);
|
||||||
}();
|
}();
|
||||||
|
|
||||||
u8* staging_data = host_visible ? buffer.Mapped().data() : staging.mapped_span.data();
|
u8* staging_data = host_visible ? buffer.Mapped().data() : staging.mapped_span.data();
|
||||||
@@ -375,11 +375,11 @@ BufferCacheRuntime::BufferCacheRuntime(const Device& device_, MemoryAllocator& m
|
|||||||
}
|
}
|
||||||
|
|
||||||
StagingBufferRef BufferCacheRuntime::UploadStagingBuffer(size_t size) {
|
StagingBufferRef BufferCacheRuntime::UploadStagingBuffer(size_t size) {
|
||||||
return staging_pool.Request(device, size, MemoryUsage::Upload);
|
return staging_pool.Request(size, MemoryUsage::Upload);
|
||||||
}
|
}
|
||||||
|
|
||||||
StagingBufferRef BufferCacheRuntime::DownloadStagingBuffer(size_t size, bool deferred) {
|
StagingBufferRef BufferCacheRuntime::DownloadStagingBuffer(size_t size, bool deferred) {
|
||||||
return staging_pool.Request(device, size, MemoryUsage::Download, deferred);
|
return staging_pool.Request(size, MemoryUsage::Download, deferred);
|
||||||
}
|
}
|
||||||
|
|
||||||
VkFormat BufferCacheRuntime::TexelBufferFormat(VideoCore::Surface::PixelFormat format) const {
|
VkFormat BufferCacheRuntime::TexelBufferFormat(VideoCore::Surface::PixelFormat format) const {
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ public:
|
|||||||
std::span<u8> BindMappedUniformBuffer([[maybe_unused]] size_t stage,
|
std::span<u8> BindMappedUniformBuffer([[maybe_unused]] size_t stage,
|
||||||
[[maybe_unused]] u32 binding_index,
|
[[maybe_unused]] u32 binding_index,
|
||||||
u32 size) {
|
u32 size) {
|
||||||
const StagingBufferRef ref = staging_pool.Request(device, size, MemoryUsage::Upload);
|
const StagingBufferRef ref = staging_pool.Request(size, MemoryUsage::Upload);
|
||||||
guest_descriptor_queue.AddBuffer(ref.buffer, ref.device_address,
|
guest_descriptor_queue.AddBuffer(ref.buffer, ref.device_address,
|
||||||
static_cast<u32>(ref.offset), size);
|
static_cast<u32>(ref.offset), size);
|
||||||
return ref.mapped_span;
|
return ref.mapped_span;
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ Uint8Pass::~Uint8Pass() = default;
|
|||||||
std::pair<VkBuffer, VkDeviceSize> Uint8Pass::Assemble(u32 num_vertices, VkBuffer src_buffer,
|
std::pair<VkBuffer, VkDeviceSize> Uint8Pass::Assemble(u32 num_vertices, VkBuffer src_buffer,
|
||||||
u32 src_offset) {
|
u32 src_offset) {
|
||||||
const u32 staging_size = static_cast<u32>(num_vertices * sizeof(u16));
|
const u32 staging_size = static_cast<u32>(num_vertices * sizeof(u16));
|
||||||
const auto staging = staging_buffer_pool.Request(device, staging_size, MemoryUsage::DeviceLocal);
|
const auto staging = staging_buffer_pool.Request(staging_size, MemoryUsage::DeviceLocal);
|
||||||
|
|
||||||
compute_pass_descriptor_queue.Acquire(scheduler, 2);
|
compute_pass_descriptor_queue.Acquire(scheduler, 2);
|
||||||
compute_pass_descriptor_queue.AddBuffer(src_buffer, src_offset, num_vertices);
|
compute_pass_descriptor_queue.AddBuffer(src_buffer, src_offset, num_vertices);
|
||||||
@@ -345,7 +345,7 @@ std::pair<VkBuffer, VkDeviceSize> QuadIndexedPass::Assemble(
|
|||||||
const u32 num_tri_vertices = (is_strip ? (num_vertices - 2) / 2 : num_vertices / 4) * 6;
|
const u32 num_tri_vertices = (is_strip ? (num_vertices - 2) / 2 : num_vertices / 4) * 6;
|
||||||
|
|
||||||
const std::size_t staging_size = num_tri_vertices * sizeof(u32);
|
const std::size_t staging_size = num_tri_vertices * sizeof(u32);
|
||||||
const auto staging = staging_buffer_pool.Request(device, staging_size, MemoryUsage::DeviceLocal);
|
const auto staging = staging_buffer_pool.Request(staging_size, MemoryUsage::DeviceLocal);
|
||||||
|
|
||||||
compute_pass_descriptor_queue.Acquire(scheduler, 2);
|
compute_pass_descriptor_queue.Acquire(scheduler, 2);
|
||||||
compute_pass_descriptor_queue.AddBuffer(src_buffer, src_offset, input_size);
|
compute_pass_descriptor_queue.AddBuffer(src_buffer, src_offset, input_size);
|
||||||
|
|||||||
@@ -852,7 +852,7 @@ public:
|
|||||||
|
|
||||||
void PushUnsyncedQueries() override {
|
void PushUnsyncedQueries() override {
|
||||||
CloseCounter();
|
CloseCounter();
|
||||||
auto staging_ref = staging_pool.Request(device,
|
auto staging_ref = staging_pool.Request(
|
||||||
pending_flush_queries.size() * TFBQueryBank::QUERY_SIZE, MemoryUsage::Download, true);
|
pending_flush_queries.size() * TFBQueryBank::QUERY_SIZE, MemoryUsage::Download, true);
|
||||||
size_t offset_base = staging_ref.offset;
|
size_t offset_base = staging_ref.offset;
|
||||||
for (auto q : pending_flush_queries) {
|
for (auto q : pending_flush_queries) {
|
||||||
@@ -1657,7 +1657,7 @@ void QueryCacheRuntime::SyncValues(std::span<SyncValuesType> values, VkBuffer ba
|
|||||||
impl->copies_setup.clear();
|
impl->copies_setup.clear();
|
||||||
impl->copies_setup.resize(impl->little_cache.size());
|
impl->copies_setup.resize(impl->little_cache.size());
|
||||||
if constexpr (SyncValuesType::GeneratesBaseBuffer) {
|
if constexpr (SyncValuesType::GeneratesBaseBuffer) {
|
||||||
ref = impl->staging_pool.Request(impl->device, total_size, MemoryUsage::Upload);
|
ref = impl->staging_pool.Request(total_size, MemoryUsage::Upload);
|
||||||
size_t current_offset = ref.offset;
|
size_t current_offset = ref.offset;
|
||||||
size_t accumulated_size = 0;
|
size_t accumulated_size = 0;
|
||||||
for (size_t i = 0; i < values.size(); i++) {
|
for (size_t i = 0; i < values.size(); i++) {
|
||||||
|
|||||||
@@ -28,42 +28,55 @@ using namespace Common::Literals;
|
|||||||
// Maximum potential alignment of a Vulkan buffer
|
// Maximum potential alignment of a Vulkan buffer
|
||||||
constexpr VkDeviceSize MAX_ALIGNMENT = 256;
|
constexpr VkDeviceSize MAX_ALIGNMENT = 256;
|
||||||
|
|
||||||
size_t GetStreamBufferSize(const Device& device, size_t max_stream_buffer_size, size_t max_alignment) {
|
// Stream buffer size in bytes
|
||||||
|
// *NIX drivers are more sensitive to increased buffers for streaming.
|
||||||
|
// Windows ones however, can intake bigger buffers and generally do not OOM.
|
||||||
|
// - GTX 960 on Windows will not OOM with 256mib
|
||||||
|
// - GT 1030 on ^NIX will OOM with 256mib
|
||||||
|
#if defined(__FreeBSD__)
|
||||||
|
constexpr VkDeviceSize MAX_STREAM_BUFFER_SIZE = 128_MiB;
|
||||||
|
#else
|
||||||
|
constexpr VkDeviceSize MAX_STREAM_BUFFER_SIZE = 256_MiB;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
size_t GetStreamBufferSize(const Device& device) {
|
||||||
if (!device.HasDebuggingToolAttached()) {
|
if (!device.HasDebuggingToolAttached()) {
|
||||||
return max_stream_buffer_size;
|
return MAX_STREAM_BUFFER_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkDeviceSize size{0};
|
VkDeviceSize size{0};
|
||||||
bool has_device_local_host_visible_heap{};
|
bool has_device_local_host_visible_heap{};
|
||||||
ForEachDeviceLocalHostVisibleHeap(device, [&size, &has_device_local_host_visible_heap](size_t index, VkMemoryHeap& heap) {
|
ForEachDeviceLocalHostVisibleHeap(device, [&size, &has_device_local_host_visible_heap](
|
||||||
|
size_t index, VkMemoryHeap& heap) {
|
||||||
has_device_local_host_visible_heap = true;
|
has_device_local_host_visible_heap = true;
|
||||||
size = std::max<size_t>(size, heap.size);
|
size = (std::max)(size, heap.size);
|
||||||
});
|
});
|
||||||
if (has_device_local_host_visible_heap) {
|
if (has_device_local_host_visible_heap) {
|
||||||
// If rebar is not supported, cut the max heap size to 40%. This will allow 2 captures to be
|
// If rebar is not supported, cut the max heap size to 40%. This will allow 2 captures to be
|
||||||
// loaded at the same time in RenderDoc. If rebar is supported, this shouldn't be an issue
|
// loaded at the same time in RenderDoc. If rebar is supported, this shouldn't be an issue
|
||||||
// as the heap will be much larger.
|
// as the heap will be much larger.
|
||||||
if (size <= max_stream_buffer_size) {
|
if (size <= MAX_STREAM_BUFFER_SIZE) {
|
||||||
size = size * 40 / 100;
|
size = size * 40 / 100;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
size = max_stream_buffer_size;
|
size = MAX_STREAM_BUFFER_SIZE;
|
||||||
}
|
}
|
||||||
return std::min<size_t>(Common::AlignUp(size, max_alignment), max_stream_buffer_size);
|
return (std::min)(Common::AlignUp(size, MAX_ALIGNMENT), MAX_STREAM_BUFFER_SIZE);
|
||||||
}
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
StagingBufferPool::StagingBufferPool(const Device& device, MemoryAllocator& memory_allocator_, Scheduler& scheduler_)
|
StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& memory_allocator_,
|
||||||
: memory_allocator{memory_allocator_}, scheduler{scheduler_}
|
Scheduler& scheduler_)
|
||||||
, stream_buffer_size{GetStreamBufferSize(device, 256_MiB, MAX_ALIGNMENT)}
|
: device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_},
|
||||||
{
|
stream_buffer_size{GetStreamBufferSize(device)}, region_size{stream_buffer_size /
|
||||||
|
StagingBufferPool::NUM_SYNCS} {
|
||||||
VkBufferCreateInfo stream_ci = {
|
VkBufferCreateInfo stream_ci = {
|
||||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.size = stream_buffer_size,
|
.size = stream_buffer_size,
|
||||||
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
|
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
|
||||||
| VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
|
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
|
||||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||||
.queueFamilyIndexCount = 0,
|
.queueFamilyIndexCount = 0,
|
||||||
.pQueueFamilyIndices = nullptr,
|
.pQueueFamilyIndices = nullptr,
|
||||||
@@ -74,16 +87,7 @@ StagingBufferPool::StagingBufferPool(const Device& device, MemoryAllocator& memo
|
|||||||
if (device.IsBufferDeviceAddressSupported()) {
|
if (device.IsBufferDeviceAddressSupported()) {
|
||||||
stream_ci.usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
|
stream_ci.usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
|
||||||
}
|
}
|
||||||
// Some drivers are more sensitive to increased buffer sizes
|
stream_buffer = memory_allocator.CreateBuffer(stream_ci, MemoryUsage::Stream);
|
||||||
try {
|
|
||||||
stream_buffer = memory_allocator.CreateBuffer(stream_ci, MemoryUsage::Stream);
|
|
||||||
} catch (vk::Exception& e) {
|
|
||||||
LOG_ERROR(Render_Vulkan, "Can't fit {} bytes buffer, halving", stream_ci.size);
|
|
||||||
stream_buffer_size = GetStreamBufferSize(device, 128_MiB, MAX_ALIGNMENT);
|
|
||||||
stream_ci.size = stream_buffer_size;
|
|
||||||
stream_buffer = memory_allocator.CreateBuffer(stream_ci, MemoryUsage::Stream);
|
|
||||||
}
|
|
||||||
region_size = stream_buffer_size / StagingBufferPool::NUM_SYNCS;
|
|
||||||
if (device.HasDebuggingToolAttached()) {
|
if (device.HasDebuggingToolAttached()) {
|
||||||
stream_buffer.SetObjectNameEXT("Stream Buffer");
|
stream_buffer.SetObjectNameEXT("Stream Buffer");
|
||||||
}
|
}
|
||||||
@@ -96,10 +100,11 @@ StagingBufferPool::StagingBufferPool(const Device& device, MemoryAllocator& memo
|
|||||||
|
|
||||||
StagingBufferPool::~StagingBufferPool() = default;
|
StagingBufferPool::~StagingBufferPool() = default;
|
||||||
|
|
||||||
StagingBufferRef StagingBufferPool::Request(const Device& device, size_t size, MemoryUsage usage, bool deferred) {
|
StagingBufferRef StagingBufferPool::Request(size_t size, MemoryUsage usage, bool deferred) {
|
||||||
return (!deferred && usage == MemoryUsage::Upload && size <= region_size)
|
if (!deferred && usage == MemoryUsage::Upload && size <= region_size) {
|
||||||
? GetStreamBuffer(device, size)
|
return GetStreamBuffer(size);
|
||||||
: GetStagingBuffer(device, size, usage, deferred);
|
}
|
||||||
|
return GetStagingBuffer(size, usage, deferred);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StagingBufferPool::FreeDeferred(StagingBufferRef& ref) {
|
void StagingBufferPool::FreeDeferred(StagingBufferRef& ref) {
|
||||||
@@ -122,10 +127,11 @@ void StagingBufferPool::TickFrame() {
|
|||||||
ReleaseCache(MemoryUsage::Download);
|
ReleaseCache(MemoryUsage::Download);
|
||||||
}
|
}
|
||||||
|
|
||||||
StagingBufferRef StagingBufferPool::GetStreamBuffer(const Device& device, size_t size) {
|
StagingBufferRef StagingBufferPool::GetStreamBuffer(size_t size) {
|
||||||
if (AreRegionsActive(Region(free_iterator) + 1, (std::min)(Region(iterator + size) + 1, NUM_SYNCS))) {
|
if (AreRegionsActive(Region(free_iterator) + 1,
|
||||||
|
(std::min)(Region(iterator + size) + 1, NUM_SYNCS))) {
|
||||||
// Avoid waiting for the previous usages to be free
|
// Avoid waiting for the previous usages to be free
|
||||||
return GetStagingBuffer(device, size, MemoryUsage::Upload);
|
return GetStagingBuffer(size, MemoryUsage::Upload);
|
||||||
}
|
}
|
||||||
const u64 current_tick = scheduler.CurrentTick();
|
const u64 current_tick = scheduler.CurrentTick();
|
||||||
std::fill(sync_ticks.begin() + Region(used_iterator), sync_ticks.begin() + Region(iterator),
|
std::fill(sync_ticks.begin() + Region(used_iterator), sync_ticks.begin() + Region(iterator),
|
||||||
@@ -134,14 +140,15 @@ StagingBufferRef StagingBufferPool::GetStreamBuffer(const Device& device, size_t
|
|||||||
free_iterator = (std::max)(free_iterator, iterator + size);
|
free_iterator = (std::max)(free_iterator, iterator + size);
|
||||||
|
|
||||||
if (iterator + size >= stream_buffer_size) {
|
if (iterator + size >= stream_buffer_size) {
|
||||||
std::fill(sync_ticks.begin() + Region(used_iterator), sync_ticks.begin() + NUM_SYNCS, current_tick);
|
std::fill(sync_ticks.begin() + Region(used_iterator), sync_ticks.begin() + NUM_SYNCS,
|
||||||
|
current_tick);
|
||||||
used_iterator = 0;
|
used_iterator = 0;
|
||||||
iterator = 0;
|
iterator = 0;
|
||||||
free_iterator = size;
|
free_iterator = size;
|
||||||
|
|
||||||
if (AreRegionsActive(0, Region(size) + 1)) {
|
if (AreRegionsActive(0, Region(size) + 1)) {
|
||||||
// Avoid waiting for the previous usages to be free
|
// Avoid waiting for the previous usages to be free
|
||||||
return GetStagingBuffer(device, size, MemoryUsage::Upload);
|
return GetStagingBuffer(size, MemoryUsage::Upload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const size_t offset = iterator;
|
const size_t offset = iterator;
|
||||||
@@ -149,7 +156,7 @@ StagingBufferRef StagingBufferPool::GetStreamBuffer(const Device& device, size_t
|
|||||||
return StagingBufferRef{
|
return StagingBufferRef{
|
||||||
.buffer = *stream_buffer,
|
.buffer = *stream_buffer,
|
||||||
.device_address = stream_buffer_address,
|
.device_address = stream_buffer_address,
|
||||||
.offset = VkDeviceSize(offset),
|
.offset = static_cast<VkDeviceSize>(offset),
|
||||||
.mapped_span = stream_pointer.subspan(offset, size),
|
.mapped_span = stream_pointer.subspan(offset, size),
|
||||||
.usage{},
|
.usage{},
|
||||||
.log2_level{},
|
.log2_level{},
|
||||||
@@ -159,18 +166,21 @@ StagingBufferRef StagingBufferPool::GetStreamBuffer(const Device& device, size_t
|
|||||||
|
|
||||||
bool StagingBufferPool::AreRegionsActive(size_t region_begin, size_t region_end) const {
|
bool StagingBufferPool::AreRegionsActive(size_t region_begin, size_t region_end) const {
|
||||||
const u64 gpu_tick = scheduler.GetMasterSemaphore().KnownGpuTick();
|
const u64 gpu_tick = scheduler.GetMasterSemaphore().KnownGpuTick();
|
||||||
return std::any_of(sync_ticks.begin() + region_begin, sync_ticks.begin() + region_end, [gpu_tick](u64 sync_tick) {
|
return std::any_of(sync_ticks.begin() + region_begin, sync_ticks.begin() + region_end,
|
||||||
return gpu_tick < sync_tick;
|
[gpu_tick](u64 sync_tick) { return gpu_tick < sync_tick; });
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
StagingBufferRef StagingBufferPool::GetStagingBuffer(const Device& device, size_t size, MemoryUsage usage, bool deferred) {
|
StagingBufferRef StagingBufferPool::GetStagingBuffer(size_t size, MemoryUsage usage,
|
||||||
if (const std::optional<StagingBufferRef> ref = TryGetReservedBuffer(size, usage, deferred))
|
bool deferred) {
|
||||||
|
if (const std::optional<StagingBufferRef> ref = TryGetReservedBuffer(size, usage, deferred)) {
|
||||||
return *ref;
|
return *ref;
|
||||||
return CreateStagingBuffer(device, size, usage, deferred);
|
}
|
||||||
|
return CreateStagingBuffer(size, usage, deferred);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<StagingBufferRef> StagingBufferPool::TryGetReservedBuffer(size_t size, MemoryUsage usage, bool deferred) {
|
std::optional<StagingBufferRef> StagingBufferPool::TryGetReservedBuffer(size_t size,
|
||||||
|
MemoryUsage usage,
|
||||||
|
bool deferred) {
|
||||||
StagingBuffers& cache_level = GetCache(usage)[Common::Log2Ceil(size)];
|
StagingBuffers& cache_level = GetCache(usage)[Common::Log2Ceil(size)];
|
||||||
|
|
||||||
const auto is_free = [this](const StagingBuffer& entry) {
|
const auto is_free = [this](const StagingBuffer& entry) {
|
||||||
@@ -192,7 +202,7 @@ std::optional<StagingBufferRef> StagingBufferPool::TryGetReservedBuffer(size_t s
|
|||||||
return it->Ref();
|
return it->Ref();
|
||||||
}
|
}
|
||||||
|
|
||||||
StagingBufferRef StagingBufferPool::CreateStagingBuffer(const Device& device, size_t size, MemoryUsage usage, bool deferred) {
|
StagingBufferRef StagingBufferPool::CreateStagingBuffer(size_t size, MemoryUsage usage, bool deferred) {
|
||||||
auto const log2_size = Common::Log2Ceil<u32>(u32(size));
|
auto const log2_size = Common::Log2Ceil<u32>(u32(size));
|
||||||
VkBufferCreateInfo buffer_ci = {
|
VkBufferCreateInfo buffer_ci = {
|
||||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||||
|
|||||||
@@ -33,10 +33,11 @@ class StagingBufferPool {
|
|||||||
public:
|
public:
|
||||||
static constexpr size_t NUM_SYNCS = 16;
|
static constexpr size_t NUM_SYNCS = 16;
|
||||||
|
|
||||||
explicit StagingBufferPool(const Device& device, MemoryAllocator& memory_allocator, Scheduler& scheduler);
|
explicit StagingBufferPool(const Device& device, MemoryAllocator& memory_allocator,
|
||||||
|
Scheduler& scheduler);
|
||||||
~StagingBufferPool();
|
~StagingBufferPool();
|
||||||
|
|
||||||
StagingBufferRef Request(const Device& device, size_t size, MemoryUsage usage, bool deferred = false);
|
StagingBufferRef Request(size_t size, MemoryUsage usage, bool deferred = false);
|
||||||
void FreeDeferred(StagingBufferRef& ref);
|
void FreeDeferred(StagingBufferRef& ref);
|
||||||
|
|
||||||
[[nodiscard]] VkBuffer StreamBuf() const noexcept {
|
[[nodiscard]] VkBuffer StreamBuf() const noexcept {
|
||||||
@@ -83,18 +84,27 @@ private:
|
|||||||
static constexpr size_t NUM_LEVELS = sizeof(size_t) * CHAR_BIT;
|
static constexpr size_t NUM_LEVELS = sizeof(size_t) * CHAR_BIT;
|
||||||
using StagingBuffersCache = std::array<StagingBuffers, NUM_LEVELS>;
|
using StagingBuffersCache = std::array<StagingBuffers, NUM_LEVELS>;
|
||||||
|
|
||||||
StagingBufferRef GetStreamBuffer(const Device& device, size_t size);
|
StagingBufferRef GetStreamBuffer(size_t size);
|
||||||
|
|
||||||
bool AreRegionsActive(size_t region_begin, size_t region_end) const;
|
bool AreRegionsActive(size_t region_begin, size_t region_end) const;
|
||||||
StagingBufferRef GetStagingBuffer(const Device& device, size_t size, MemoryUsage usage, bool deferred = false);
|
|
||||||
std::optional<StagingBufferRef> TryGetReservedBuffer(size_t size, MemoryUsage usage, bool deferred);
|
StagingBufferRef GetStagingBuffer(size_t size, MemoryUsage usage, bool deferred = false);
|
||||||
StagingBufferRef CreateStagingBuffer(const Device& device, size_t size, MemoryUsage usage, bool deferred);
|
|
||||||
|
std::optional<StagingBufferRef> TryGetReservedBuffer(size_t size, MemoryUsage usage,
|
||||||
|
bool deferred);
|
||||||
|
|
||||||
|
StagingBufferRef CreateStagingBuffer(size_t size, MemoryUsage usage, bool deferred);
|
||||||
|
|
||||||
StagingBuffersCache& GetCache(MemoryUsage usage);
|
StagingBuffersCache& GetCache(MemoryUsage usage);
|
||||||
|
|
||||||
void ReleaseCache(MemoryUsage usage);
|
void ReleaseCache(MemoryUsage usage);
|
||||||
|
|
||||||
void ReleaseLevel(StagingBuffersCache& cache, size_t log2);
|
void ReleaseLevel(StagingBuffersCache& cache, size_t log2);
|
||||||
size_t Region(size_t iter) const noexcept {
|
size_t Region(size_t iter) const noexcept {
|
||||||
return iter / region_size;
|
return iter / region_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Device& device;
|
||||||
MemoryAllocator& memory_allocator;
|
MemoryAllocator& memory_allocator;
|
||||||
Scheduler& scheduler;
|
Scheduler& scheduler;
|
||||||
|
|
||||||
|
|||||||
@@ -975,11 +975,11 @@ void TextureCacheRuntime::Finish() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StagingBufferRef TextureCacheRuntime::UploadStagingBuffer(size_t size, bool deferred) {
|
StagingBufferRef TextureCacheRuntime::UploadStagingBuffer(size_t size, bool deferred) {
|
||||||
return staging_buffer_pool.Request(device, size, MemoryUsage::Upload, deferred);
|
return staging_buffer_pool.Request(size, MemoryUsage::Upload, deferred);
|
||||||
}
|
}
|
||||||
|
|
||||||
StagingBufferRef TextureCacheRuntime::DownloadStagingBuffer(size_t size, bool deferred) {
|
StagingBufferRef TextureCacheRuntime::DownloadStagingBuffer(size_t size, bool deferred) {
|
||||||
return staging_buffer_pool.Request(device, size, MemoryUsage::Download, deferred);
|
return staging_buffer_pool.Request(size, MemoryUsage::Download, deferred);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureCacheRuntime::FreeDeferredStagingBuffer(StagingBufferRef& ref) {
|
void TextureCacheRuntime::FreeDeferredStagingBuffer(StagingBufferRef& ref) {
|
||||||
|
|||||||
@@ -43,26 +43,32 @@ namespace {
|
|||||||
switch (window_type) {
|
switch (window_type) {
|
||||||
case Core::Frontend::WindowSystemType::Headless:
|
case Core::Frontend::WindowSystemType::Headless:
|
||||||
break;
|
break;
|
||||||
#ifdef _WIN32
|
#if defined(VK_USE_PLATFORM_WIN32_KHR)
|
||||||
case Core::Frontend::WindowSystemType::Windows:
|
case Core::Frontend::WindowSystemType::Windows:
|
||||||
extensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
|
extensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
|
||||||
break;
|
break;
|
||||||
#elif defined(__APPLE__)
|
#endif
|
||||||
|
#if defined(VK_USE_PLATFORM_METAL_EXT)
|
||||||
case Core::Frontend::WindowSystemType::Cocoa:
|
case Core::Frontend::WindowSystemType::Cocoa:
|
||||||
extensions.push_back(VK_EXT_METAL_SURFACE_EXTENSION_NAME);
|
extensions.push_back(VK_EXT_METAL_SURFACE_EXTENSION_NAME);
|
||||||
break;
|
break;
|
||||||
#elif defined(__ANDROID__)
|
#endif
|
||||||
|
#if defined(VK_USE_PLATFORM_ANDROID_KHR)
|
||||||
case Core::Frontend::WindowSystemType::Android:
|
case Core::Frontend::WindowSystemType::Android:
|
||||||
extensions.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
|
extensions.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
|
||||||
break;
|
break;
|
||||||
#elif defined(__HAIKU__)
|
#endif
|
||||||
|
#if defined(VK_USE_PLATFORM_XCB_KHR)
|
||||||
case Core::Frontend::WindowSystemType::Xcb:
|
case Core::Frontend::WindowSystemType::Xcb:
|
||||||
extensions.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
|
extensions.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
|
||||||
break;
|
break;
|
||||||
#else
|
#endif
|
||||||
|
#if defined(VK_USE_PLATFORM_XLIB_KHR)
|
||||||
case Core::Frontend::WindowSystemType::X11:
|
case Core::Frontend::WindowSystemType::X11:
|
||||||
extensions.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
|
extensions.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
|
||||||
case Core::Frontend::WindowSystemType::Wayland:
|
case Core::Frontend::WindowSystemType::Wayland:
|
||||||
extensions.push_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
|
extensions.push_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "core/frontend/emu_window.h"
|
#include "core/frontend/emu_window.h"
|
||||||
#include "video_core/vulkan_common/vulkan_surface.h"
|
#include "video_core/vulkan_common/vulkan_surface.h"
|
||||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||||
|
#include "video_core/vulkan_common/vulkan.h"
|
||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
@@ -17,7 +18,7 @@ vk::SurfaceKHR CreateSurface(
|
|||||||
[[maybe_unused]] const vk::InstanceDispatch& dld = instance.Dispatch();
|
[[maybe_unused]] const vk::InstanceDispatch& dld = instance.Dispatch();
|
||||||
VkSurfaceKHR unsafe_surface = VkSurfaceKHR{};
|
VkSurfaceKHR unsafe_surface = VkSurfaceKHR{};
|
||||||
|
|
||||||
#ifdef _WIN32
|
#if defined(VK_USE_PLATFORM_WIN32_KHR)
|
||||||
if (window_info.type == Core::Frontend::WindowSystemType::Windows) {
|
if (window_info.type == Core::Frontend::WindowSystemType::Windows) {
|
||||||
const HWND hWnd = static_cast<HWND>(window_info.render_surface);
|
const HWND hWnd = static_cast<HWND>(window_info.render_surface);
|
||||||
const VkWin32SurfaceCreateInfoKHR win32_ci{VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR,
|
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);
|
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) {
|
if (window_info.type == Core::Frontend::WindowSystemType::Cocoa) {
|
||||||
const VkMetalSurfaceCreateInfoEXT metal_ci = {
|
const VkMetalSurfaceCreateInfoEXT metal_ci = {
|
||||||
.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT,
|
.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT,
|
||||||
@@ -45,7 +47,8 @@ vk::SurfaceKHR CreateSurface(
|
|||||||
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
|
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) {
|
if (window_info.type == Core::Frontend::WindowSystemType::Android) {
|
||||||
const VkAndroidSurfaceCreateInfoKHR android_ci{
|
const VkAndroidSurfaceCreateInfoKHR android_ci{
|
||||||
VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR, nullptr, 0,
|
VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR, nullptr, 0,
|
||||||
@@ -59,7 +62,8 @@ vk::SurfaceKHR CreateSurface(
|
|||||||
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
|
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) {
|
if (window_info.type == Core::Frontend::WindowSystemType::Xcb) {
|
||||||
const VkXcbSurfaceCreateInfoKHR xcb_ci{
|
const VkXcbSurfaceCreateInfoKHR xcb_ci{
|
||||||
.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR,
|
.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR,
|
||||||
@@ -76,7 +80,8 @@ vk::SurfaceKHR CreateSurface(
|
|||||||
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
|
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#endif
|
||||||
|
#if defined(VK_USE_PLATFORM_XLIB_KHR)
|
||||||
if (window_info.type == Core::Frontend::WindowSystemType::X11) {
|
if (window_info.type == Core::Frontend::WindowSystemType::X11) {
|
||||||
const VkXlibSurfaceCreateInfoKHR xlib_ci{
|
const VkXlibSurfaceCreateInfoKHR xlib_ci{
|
||||||
VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, nullptr, 0,
|
VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, nullptr, 0,
|
||||||
@@ -90,6 +95,8 @@ vk::SurfaceKHR CreateSurface(
|
|||||||
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
|
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
|
||||||
if (window_info.type == Core::Frontend::WindowSystemType::Wayland) {
|
if (window_info.type == Core::Frontend::WindowSystemType::Wayland) {
|
||||||
const VkWaylandSurfaceCreateInfoKHR wayland_ci{
|
const VkWaylandSurfaceCreateInfoKHR wayland_ci{
|
||||||
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR, nullptr, 0,
|
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR, nullptr, 0,
|
||||||
@@ -105,7 +112,6 @@ vk::SurfaceKHR CreateSurface(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!unsafe_surface) {
|
if (!unsafe_surface) {
|
||||||
LOG_ERROR(Render_Vulkan, "Presentation not supported on this platform");
|
LOG_ERROR(Render_Vulkan, "Presentation not supported on this platform");
|
||||||
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
|
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
|
||||||
|
|||||||
Reference in New Issue
Block a user