mirror of
https://github.com/izzy2lost/WeeU.git
synced 2026-07-06 00:19:59 -07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9d10a9581 | ||
|
|
2842615edb | ||
|
|
94b179ef5a | ||
|
|
7f21104b54 | ||
|
|
bbd8d6d5ac | ||
|
|
4d68446f14 | ||
|
|
a0e69ffbbd | ||
|
|
c3d6cad428 | ||
|
|
58c7b56c60 | ||
|
|
be287a1f4e | ||
|
|
5adb1e9618 | ||
|
|
138510106c | ||
|
|
948460cad7 | ||
|
|
3df8217a02 | ||
|
|
ec6726e85c | ||
|
|
348d86648f | ||
|
|
592c9b2776 | ||
|
|
5d156672e8 | ||
|
|
2f86622a68 | ||
|
|
a40b226e00 |
+36
-12
@@ -22,34 +22,36 @@ jobs:
|
|||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: "recursive"
|
submodules: "recursive"
|
||||||
|
|
||||||
- name: Setup release mode parameters (for deploy)
|
- name: Setup release mode parameters (for deploy)
|
||||||
if: ${{ inputs.deploymode == 'release' }}
|
if: ${{ inputs.deploymode == 'release' }}
|
||||||
run: |
|
run: |
|
||||||
echo "BUILD_MODE=release" >> $GITHUB_ENV
|
echo "BUILD_MODE=release" >> $GITHUB_ENV
|
||||||
echo "BUILD_FLAGS=" >> $GITHUB_ENV
|
echo "BUILD_FLAGS=" >> $GITHUB_ENV
|
||||||
echo "Build mode is release"
|
echo "Build mode is release"
|
||||||
|
|
||||||
- name: Setup debug mode parameters (for continous build)
|
- name: Setup debug mode parameters (for continous build)
|
||||||
if: ${{ inputs.deploymode != 'release' }}
|
if: ${{ inputs.deploymode != 'release' }}
|
||||||
run: |
|
run: |
|
||||||
echo "BUILD_MODE=debug" >> $GITHUB_ENV
|
echo "BUILD_MODE=debug" >> $GITHUB_ENV
|
||||||
echo "BUILD_FLAGS=" >> $GITHUB_ENV
|
echo "BUILD_FLAGS=" >> $GITHUB_ENV
|
||||||
echo "Build mode is debug"
|
echo "Build mode is debug"
|
||||||
|
|
||||||
- name: Setup version for experimental
|
- name: Setup version for experimental
|
||||||
if: ${{ inputs.experimentalversion != '' }}
|
if: ${{ inputs.experimentalversion != '' }}
|
||||||
run: |
|
run: |
|
||||||
echo "[INFO] Experimental version ${{ inputs.experimentalversion }}"
|
echo "[INFO] Experimental version ${{ inputs.experimentalversion }}"
|
||||||
echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEXPERIMENTAL_VERSION=${{ inputs.experimentalversion }}" >> $GITHUB_ENV
|
echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEXPERIMENTAL_VERSION=${{ inputs.experimentalversion }}" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: "Install system dependencies"
|
- name: "Install system dependencies"
|
||||||
run: |
|
run: |
|
||||||
sudo apt update -qq
|
sudo apt update -qq
|
||||||
sudo apt install -y clang-12 cmake freeglut3-dev libgcrypt20-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev nasm ninja-build
|
sudo apt install -y clang-12 cmake freeglut3-dev libgcrypt20-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev nasm ninja-build
|
||||||
|
|
||||||
- name: "Bootstrap vcpkg"
|
- name: "Bootstrap vcpkg"
|
||||||
run: |
|
run: |
|
||||||
bash ./dependencies/vcpkg/bootstrap-vcpkg.sh
|
bash ./dependencies/vcpkg/bootstrap-vcpkg.sh
|
||||||
|
|
||||||
- name: 'Setup NuGet Credentials for vcpkg'
|
- name: 'Setup NuGet Credentials for vcpkg'
|
||||||
shell: 'bash'
|
shell: 'bash'
|
||||||
run: |
|
run: |
|
||||||
@@ -66,15 +68,12 @@ jobs:
|
|||||||
|
|
||||||
- name: "cmake"
|
- name: "cmake"
|
||||||
run: |
|
run: |
|
||||||
mkdir -p build
|
cmake -S . -B build ${{ env.BUILD_FLAGS }} -DCMAKE_BUILD_TYPE=${{ env.BUILD_MODE }} -DPORTABLE=OFF -DCMAKE_C_COMPILER=/usr/bin/clang-12 -DCMAKE_CXX_COMPILER=/usr/bin/clang++-12 -G Ninja -DCMAKE_MAKE_PROGRAM=/usr/bin/ninja
|
||||||
cd build
|
|
||||||
cmake .. ${{ env.BUILD_FLAGS }} -DCMAKE_BUILD_TYPE=${{ env.BUILD_MODE }} -DCMAKE_C_COMPILER=/usr/bin/clang-12 -DCMAKE_CXX_COMPILER=/usr/bin/clang++-12 -G Ninja -DCMAKE_MAKE_PROGRAM=/usr/bin/ninja
|
|
||||||
|
|
||||||
- name: "Build Cemu"
|
- name: "Build Cemu"
|
||||||
run: |
|
run: |
|
||||||
cd build
|
cmake --build build
|
||||||
ninja
|
|
||||||
|
|
||||||
- name: Prepare artifact
|
- name: Prepare artifact
|
||||||
if: ${{ inputs.deploymode == 'release' }}
|
if: ${{ inputs.deploymode == 'release' }}
|
||||||
run: mv bin/Cemu_release bin/Cemu
|
run: mv bin/Cemu_release bin/Cemu
|
||||||
@@ -85,8 +84,33 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: cemu-bin-linux-x64
|
name: cemu-bin-linux-x64
|
||||||
path: ./bin/Cemu
|
path: ./bin/Cemu
|
||||||
|
|
||||||
|
build-appimage:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
needs: build-ubuntu
|
||||||
|
steps:
|
||||||
|
- name: Checkout Upstream Repo
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: cemu-bin-linux-x64
|
||||||
|
path: bin
|
||||||
|
|
||||||
|
- name: "Install system dependencies"
|
||||||
|
run: |
|
||||||
|
sudo apt update -qq
|
||||||
|
sudo apt install -y clang-12 cmake freeglut3-dev libgcrypt20-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev nasm ninja-build
|
||||||
|
|
||||||
|
- name: "Build AppImage"
|
||||||
|
run: dist/linux/appimage.sh
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: cemu-appimage-x64
|
||||||
|
path: artifacts
|
||||||
|
|
||||||
build-windows:
|
build-windows:
|
||||||
runs-on: windows-2022
|
runs-on: windows-2022
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
@@ -13,13 +13,18 @@ jobs:
|
|||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
needs: call-release-build
|
needs: call-release-build
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- uses: actions/download-artifact@v3
|
- uses: actions/download-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: cemu-bin-linux-x64
|
name: cemu-bin-linux-x64
|
||||||
path: cemu-bin-linux-x64
|
path: cemu-bin-linux-x64
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: cemu-appimage-x64
|
||||||
|
path: cemu-appimage-x64
|
||||||
|
|
||||||
- uses: actions/download-artifact@v3
|
- uses: actions/download-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: cemu-bin-windows-x64
|
name: cemu-bin-windows-x64
|
||||||
@@ -53,7 +58,14 @@ jobs:
|
|||||||
mv cemu-bin-windows-x64/Cemu.exe ./${{ env.CEMU_FOLDER_NAME }}/Cemu.exe
|
mv cemu-bin-windows-x64/Cemu.exe ./${{ env.CEMU_FOLDER_NAME }}/Cemu.exe
|
||||||
zip -9 -r upload/cemu-${{ env.CEMU_VERSION }}-windows-x64.zip ${{ env.CEMU_FOLDER_NAME }}
|
zip -9 -r upload/cemu-${{ env.CEMU_VERSION }}-windows-x64.zip ${{ env.CEMU_FOLDER_NAME }}
|
||||||
rm -r ./${{ env.CEMU_FOLDER_NAME }}
|
rm -r ./${{ env.CEMU_FOLDER_NAME }}
|
||||||
|
|
||||||
|
- name: Create appimage
|
||||||
|
run: |
|
||||||
|
VERSION=${{ env.CEMU_VERSION }}
|
||||||
|
echo "Cemu Version is $VERSION"
|
||||||
|
ls cemu-appimage-x64
|
||||||
|
mv cemu-appimage-x64/Cemu-*-x86_64.AppImage upload/Cemu-$VERSION-x86_64.AppImage
|
||||||
|
|
||||||
- name: Create release from linux-bin
|
- name: Create release from linux-bin
|
||||||
run: |
|
run: |
|
||||||
ls ./
|
ls ./
|
||||||
|
|||||||
@@ -15,13 +15,18 @@ jobs:
|
|||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
needs: call-release-build
|
needs: call-release-build
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- uses: actions/download-artifact@v3
|
- uses: actions/download-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: cemu-bin-linux-x64
|
name: cemu-bin-linux-x64
|
||||||
path: cemu-bin-linux-x64
|
path: cemu-bin-linux-x64
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: cemu-appimage-x64
|
||||||
|
path: cemu-appimage-x64
|
||||||
|
|
||||||
- uses: actions/download-artifact@v3
|
- uses: actions/download-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: cemu-bin-windows-x64
|
name: cemu-bin-windows-x64
|
||||||
@@ -44,11 +49,7 @@ jobs:
|
|||||||
echo "Cemu CI version: $(./getversion)"
|
echo "Cemu CI version: $(./getversion)"
|
||||||
echo "CEMU_FOLDER_NAME=Cemu_$(./getversion)" >> $GITHUB_ENV
|
echo "CEMU_FOLDER_NAME=Cemu_$(./getversion)" >> $GITHUB_ENV
|
||||||
echo "CEMU_VERSION=$(./getversion)" >> $GITHUB_ENV
|
echo "CEMU_VERSION=$(./getversion)" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Create appimage
|
|
||||||
run: |
|
|
||||||
echo "to do"
|
|
||||||
|
|
||||||
- name: Create release from windows-bin
|
- name: Create release from windows-bin
|
||||||
run: |
|
run: |
|
||||||
ls ./
|
ls ./
|
||||||
@@ -57,6 +58,13 @@ jobs:
|
|||||||
mv cemu-bin-windows-x64/Cemu.exe ./${{ env.CEMU_FOLDER_NAME }}/Cemu.exe
|
mv cemu-bin-windows-x64/Cemu.exe ./${{ env.CEMU_FOLDER_NAME }}/Cemu.exe
|
||||||
zip -9 -r upload/cemu-${{ env.CEMU_VERSION }}-windows-x64.zip ${{ env.CEMU_FOLDER_NAME }}
|
zip -9 -r upload/cemu-${{ env.CEMU_VERSION }}-windows-x64.zip ${{ env.CEMU_FOLDER_NAME }}
|
||||||
rm -r ./${{ env.CEMU_FOLDER_NAME }}
|
rm -r ./${{ env.CEMU_FOLDER_NAME }}
|
||||||
|
|
||||||
|
- name: Create appimage
|
||||||
|
run: |
|
||||||
|
VERSION=${{ env.CEMU_VERSION }}
|
||||||
|
echo "Cemu Version is $VERSION"
|
||||||
|
ls cemu-appimage-x64
|
||||||
|
mv cemu-appimage-x64/Cemu-*-x86_64.AppImage upload/Cemu-$VERSION-x86_64.AppImage
|
||||||
|
|
||||||
- name: Create release from ubuntu-bin
|
- name: Create release from ubuntu-bin
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
*.out
|
*.out
|
||||||
*.app
|
*.app
|
||||||
.vs
|
.vs
|
||||||
|
.vscode
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
build/
|
build/
|
||||||
|
|||||||
@@ -57,21 +57,32 @@ You can use it by replacing the step 3 with the following:
|
|||||||
- If step 3 is still failing or if you're not able to find the cause, please make an issue on our Github about it!
|
- If step 3 is still failing or if you're not able to find the cause, please make an issue on our Github about it!
|
||||||
- If step 4 gives you an error that contains something like `main.cpp.o: in function 'std::__cxx11::basic_string...`, you likely are experiencing a clang-14 issue. This can only be fixed by either lowering the clang version or using GCC, see below.
|
- If step 4 gives you an error that contains something like `main.cpp.o: in function 'std::__cxx11::basic_string...`, you likely are experiencing a clang-14 issue. This can only be fixed by either lowering the clang version or using GCC, see below.
|
||||||
- If step 4 gives you a different error, you could report it to this repo or try using GCC. Just make sure your standard library and compilers are updated since Cemu uses a lot of modern features!
|
- If step 4 gives you a different error, you could report it to this repo or try using GCC. Just make sure your standard library and compilers are updated since Cemu uses a lot of modern features!
|
||||||
- If step 4 gives you undefined libdecor_xx, you are likely experiencing an issue with sdl2 package that comes with vcpkg. Delete sdl2 from vcpkg.json in source file and recompile.
|
- If step 4 gives you undefined libdecor_xx, you are likely experiencing an issue with sdl2 package that comes with vcpkg. Delete sdl2 from vcpkg.json in source file and recompile.
|
||||||
|
- If step 3 fails during rebuild after `git pull` with an error that mentions RPATH, add this to the end of step 3: `-DCMAKE_BUILD_WITH_INSTALL_RPATH=ON`
|
||||||
|
|
||||||
## MacOS
|
## macOS
|
||||||
|
|
||||||
To compile Cemu, a recent enough compiler and STL with C++20 support is required! LLVM 13 and
|
To compile Cemu, a recent enough compiler and STL with C++20 support is required! LLVM 13 and
|
||||||
below, built in LLVM, and Xcode LLVM don't support the C++20 feature set required. Currently,
|
below, built in LLVM, and Xcode LLVM don't support the C++20 feature set required. Currently,
|
||||||
LLVM 15 isn't supported due to compatibility issues with Boost dependency. The OpenGL graphics
|
LLVM 15 isn't supported due to compatibility issues with Boost dependency. The OpenGL graphics
|
||||||
API isn't support on MacOS, Vulkan must be used. Additionally Vulkan must be used through the
|
API isn't support on macOS, Vulkan must be used. Additionally Vulkan must be used through the
|
||||||
Molten-VK compatibility layer.
|
Molten-VK compatibility layer
|
||||||
|
|
||||||
|
### On Apple Silicon Macs, Rosetta 2 and the x86_64 version of Homebrew must be used
|
||||||
|
|
||||||
|
You can skip this section if you have an Intel Mac. Every time you compile, you need to perform steps 2.
|
||||||
|
|
||||||
|
1. `softwareupdate --install-rosetta` # Install Rosetta 2 if you don't have it. This only has to be done once
|
||||||
|
2. `arch -x86_64 zsh` # run an x64 shell
|
||||||
|
|
||||||
### Installing brew
|
### Installing brew
|
||||||
`/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`
|
|
||||||
|
1. `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`
|
||||||
|
2. `eval "$(/usr/local/Homebrew/bin/brew shellenv)"` # set x86_64 brew env
|
||||||
|
|
||||||
### Installing dependencies
|
### Installing dependencies
|
||||||
`brew install git cmake llvm@14 ninja nasm molten-vk`
|
|
||||||
|
`brew install boost git cmake llvm@14 ninja nasm molten-vk`
|
||||||
|
|
||||||
### Build Cemu using cmake and clang
|
### Build Cemu using cmake and clang
|
||||||
1. `git clone --recursive https://github.com/cemu-project/Cemu`
|
1. `git clone --recursive https://github.com/cemu-project/Cemu`
|
||||||
|
|||||||
+8
-1
@@ -6,7 +6,14 @@ option(MACOS_BUNDLE "The executable when built on macOS will be created as an ap
|
|||||||
set(EXPERIMENTAL_VERSION "" CACHE STRING "") # used by CI script to set experimental version
|
set(EXPERIMENTAL_VERSION "" CACHE STRING "") # used by CI script to set experimental version
|
||||||
|
|
||||||
if (EXPERIMENTAL_VERSION)
|
if (EXPERIMENTAL_VERSION)
|
||||||
add_definitions(-DEMULATOR_VERSION_MINOR=${EXPERIMENTAL_VERSION})
|
add_definitions(-DEMULATOR_VERSION_MINOR=${EXPERIMENTAL_VERSION})
|
||||||
|
execute_process(
|
||||||
|
COMMAND git log --format=%h -1
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
|
||||||
|
OUTPUT_VARIABLE GIT_HASH
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
add_definitions(-DEMULATOR_HASH=${GIT_HASH})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (ENABLE_VCPKG)
|
if (ENABLE_VCPKG)
|
||||||
|
|||||||
+51
@@ -0,0 +1,51 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [ -z "${GITHUB_WORKSPACE}" ]; then
|
||||||
|
export GITHUB_WORKSPACE="."
|
||||||
|
fi
|
||||||
|
|
||||||
|
curl -sSfLO "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage"
|
||||||
|
chmod a+x linuxdeploy*.AppImage
|
||||||
|
curl -sSfL https://github.com$(curl https://github.com/probonopd/go-appimage/releases/expanded_assets/continuous | grep "mkappimage-.*-x86_64.AppImage" | head -n 1 | cut -d '"' -f 2) -o mkappimage.AppImage
|
||||||
|
chmod a+x mkappimage.AppImage
|
||||||
|
curl -sSfLO "https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gtk/master/linuxdeploy-plugin-gtk.sh"
|
||||||
|
chmod a+x linuxdeploy-plugin-gtk.sh
|
||||||
|
|
||||||
|
if [[ ! -e /usr/lib/x86_64-linux-gnu ]]; then
|
||||||
|
sed -i 's#lib\/x86_64-linux-gnu#lib64#g' linuxdeploy-plugin-gtk.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p AppDir/usr/
|
||||||
|
cp dist/linux/{info.cemu.Cemu.desktop,info.cemu.Cemu.png} AppDir/
|
||||||
|
|
||||||
|
mkdir -p AppDir/usr/share/applications
|
||||||
|
mkdir -p AppDir/usr/share/icons/hicolor/scalable/apps
|
||||||
|
mkdir -p AppDir/usr/lib
|
||||||
|
|
||||||
|
cp -r bin AppDir/usr/
|
||||||
|
cp /usr/lib/x86_64-linux-gnu/{libsepol.so.1,libffi.so.7,libpcre.so.3,libGLU.so.1,libthai.so.0} AppDir/usr/lib
|
||||||
|
|
||||||
|
chmod +x AppDir/usr/bin/Cemu
|
||||||
|
#chmod +x AppDir/AppRun
|
||||||
|
|
||||||
|
export UPD_INFO="gh-releases-zsync|cemu-project|Cemu|ci|Cemu.AppImage.zsync"
|
||||||
|
./linuxdeploy-x86_64.AppImage --appimage-extract-and-run\
|
||||||
|
--appdir="$GITHUB_WORKSPACE"/AppDir/ \
|
||||||
|
-d "$GITHUB_WORKSPACE"/AppDir/info.cemu.Cemu.desktop \
|
||||||
|
-i "$GITHUB_WORKSPACE"/AppDir/info.cemu.Cemu.png \
|
||||||
|
-e "$GITHUB_WORKSPACE"/AppDir/usr/bin/Cemu \
|
||||||
|
--plugin gtk
|
||||||
|
|
||||||
|
GITVERSION=$(git rev-parse --short HEAD)
|
||||||
|
echo $GITVERSION
|
||||||
|
if [[ -z ${GITVERSION} ]]; then
|
||||||
|
GITVERSION=experimental
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Cemu Version Cemu-${GITVERSION}"
|
||||||
|
rm AppDir/usr/lib/libwayland-client.so.0
|
||||||
|
echo "export LC_ALL=C" >> AppDir/apprun-hooks/linuxdeploy-plugin-gtk.sh
|
||||||
|
VERSION=${GITVERSION} ./mkappimage.AppImage --appimage-extract-and-run "$GITHUB_WORKSPACE"/AppDir
|
||||||
|
|
||||||
|
mkdir -p "$GITHUB_WORKSPACE"/artifacts/
|
||||||
|
mv Cemu-${GITVERSION}-x86_64.AppImage "$GITHUB_WORKSPACE"/artifacts/
|
||||||
Vendored
BIN
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -34,6 +34,13 @@ elseif(UNIX)
|
|||||||
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||||
add_compile_options(-Wno-ambiguous-reversed-operator)
|
add_compile_options(-Wno-ambiguous-reversed-operator)
|
||||||
endif()
|
endif()
|
||||||
|
# most linux environments should enable pie by default, but make sure just in case.
|
||||||
|
# the same cannot be said for no executable stack which some linkers
|
||||||
|
# and configurations thereof might enable due to the assembly in the project
|
||||||
|
if(NOT APPLE)
|
||||||
|
add_compile_options(-fpie)
|
||||||
|
add_link_options(-pie -z noexecstack)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_compile_options(-Wno-multichar -Wno-invalid-offsetof -Wno-switch -Wno-ignored-attributes -Wno-deprecated-enum-enum-conversion)
|
add_compile_options(-Wno-multichar -Wno-invalid-offsetof -Wno-switch -Wno-ignored-attributes -Wno-deprecated-enum-enum-conversion)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -178,6 +178,8 @@ add_library(CemuCafe
|
|||||||
HW/Latte/Renderer/Vulkan/LatteTextureVk.h
|
HW/Latte/Renderer/Vulkan/LatteTextureVk.h
|
||||||
HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp
|
HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp
|
||||||
HW/Latte/Renderer/Vulkan/RendererShaderVk.h
|
HW/Latte/Renderer/Vulkan/RendererShaderVk.h
|
||||||
|
HW/Latte/Renderer/Vulkan/SwapchainInfoVk.cpp
|
||||||
|
HW/Latte/Renderer/Vulkan/SwapchainInfoVk.h
|
||||||
HW/Latte/Renderer/Vulkan/TextureReadbackVk.cpp
|
HW/Latte/Renderer/Vulkan/TextureReadbackVk.cpp
|
||||||
HW/Latte/Renderer/Vulkan/VKRBase.h
|
HW/Latte/Renderer/Vulkan/VKRBase.h
|
||||||
HW/Latte/Renderer/Vulkan/VKRMemoryManager.cpp
|
HW/Latte/Renderer/Vulkan/VKRMemoryManager.cpp
|
||||||
|
|||||||
@@ -123,8 +123,8 @@ void LatteOverlay_renderOverlay(ImVec2& position, ImVec2& pivot, sint32 directio
|
|||||||
g_renderer->AppendOverlayDebugInfo();
|
g_renderer->AppendOverlayDebugInfo();
|
||||||
|
|
||||||
position.y += (ImGui::GetWindowSize().y + 10.0f) * direction;
|
position.y += (ImGui::GetWindowSize().y + 10.0f) * direction;
|
||||||
ImGui::End();
|
|
||||||
}
|
}
|
||||||
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
@@ -170,8 +170,8 @@ void LatteOverlay_RenderNotifications(ImVec2& position, ImVec2& pivot, sint32 di
|
|||||||
ImGui::TextUnformatted(s_mii_name.c_str());
|
ImGui::TextUnformatted(s_mii_name.c_str());
|
||||||
|
|
||||||
position.y += (ImGui::GetWindowSize().y + 10.0f) * direction;
|
position.y += (ImGui::GetWindowSize().y + 10.0f) * direction;
|
||||||
ImGui::End();
|
|
||||||
}
|
}
|
||||||
|
ImGui::End();
|
||||||
|
|
||||||
// controller
|
// controller
|
||||||
std::vector<std::pair<int, std::string>> profiles;
|
std::vector<std::pair<int, std::string>> profiles;
|
||||||
@@ -209,8 +209,8 @@ void LatteOverlay_RenderNotifications(ImVec2& position, ImVec2& pivot, sint32 di
|
|||||||
}
|
}
|
||||||
|
|
||||||
position.y += (ImGui::GetWindowSize().y + 10.0f) * direction;
|
position.y += (ImGui::GetWindowSize().y + 10.0f) * direction;
|
||||||
ImGui::End();
|
|
||||||
}
|
}
|
||||||
|
ImGui::End();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
s_init_overlay = true;
|
s_init_overlay = true;
|
||||||
@@ -254,10 +254,8 @@ void LatteOverlay_RenderNotifications(ImVec2& position, ImVec2& pivot, sint32 di
|
|||||||
}
|
}
|
||||||
|
|
||||||
position.y += (ImGui::GetWindowSize().y + 10.0f) * direction;
|
position.y += (ImGui::GetWindowSize().y + 10.0f) * direction;
|
||||||
ImGui::End();
|
|
||||||
}
|
}
|
||||||
|
ImGui::End();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,8 +304,8 @@ void LatteOverlay_RenderNotifications(ImVec2& position, ImVec2& pivot, sint32 di
|
|||||||
}
|
}
|
||||||
|
|
||||||
position.y += (ImGui::GetWindowSize().y + 10.0f) * direction;
|
position.y += (ImGui::GetWindowSize().y + 10.0f) * direction;
|
||||||
ImGui::End();
|
|
||||||
}
|
}
|
||||||
|
ImGui::End();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,8 +361,8 @@ void LatteOverlay_RenderNotifications(ImVec2& position, ImVec2& pivot, sint32 di
|
|||||||
}
|
}
|
||||||
|
|
||||||
position.y += (ImGui::GetWindowSize().y + 10.0f) * direction;
|
position.y += (ImGui::GetWindowSize().y + 10.0f) * direction;
|
||||||
ImGui::End();
|
|
||||||
}
|
}
|
||||||
|
ImGui::End();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -435,8 +433,8 @@ void LatteOverlay_RenderNotifications(ImVec2& position, ImVec2& pivot, sint32 di
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
position.y += (ImGui::GetWindowSize().y + 10.0f) * direction;
|
position.y += (ImGui::GetWindowSize().y + 10.0f) * direction;
|
||||||
ImGui::End();
|
|
||||||
}
|
}
|
||||||
|
ImGui::End();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -475,10 +473,9 @@ void LatteOverlay_RenderNotifications(ImVec2& position, ImVec2& pivot, sint32 di
|
|||||||
}
|
}
|
||||||
|
|
||||||
position.y += (ImGui::GetWindowSize().y + 10.0f) * direction;
|
position.y += (ImGui::GetWindowSize().y + 10.0f) * direction;
|
||||||
ImGui::End();
|
|
||||||
}
|
}
|
||||||
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
ImGui::PopFont();
|
ImGui::PopFont();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,10 +350,10 @@ void LatteShaderCache_load()
|
|||||||
|
|
||||||
ImGui::GetWindowDrawList()->AddImage(g_shaderCacheLoaderState.textureTVId, ImVec2(paddingLeftAndRight, paddingTopAndBottom), ImVec2(io.DisplaySize.x-paddingLeftAndRight, io.DisplaySize.y-paddingTopAndBottom), { 0,1 }, { 1,0 });
|
ImGui::GetWindowDrawList()->AddImage(g_shaderCacheLoaderState.textureTVId, ImVec2(paddingLeftAndRight, paddingTopAndBottom), ImVec2(io.DisplaySize.x-paddingLeftAndRight, io.DisplaySize.y-paddingTopAndBottom), { 0,1 }, { 1,0 });
|
||||||
}
|
}
|
||||||
ImGui::End();
|
|
||||||
ImGui::PopStyleVar(2);
|
|
||||||
g_renderer->ImguiEnd();
|
|
||||||
}
|
}
|
||||||
|
ImGui::End();
|
||||||
|
ImGui::PopStyleVar(2);
|
||||||
|
g_renderer->ImguiEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
g_renderer->BeginFrame(false);
|
g_renderer->BeginFrame(false);
|
||||||
@@ -365,7 +365,7 @@ void LatteShaderCache_load()
|
|||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 0,0 });
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 0,0 });
|
||||||
|
|
||||||
if (ImGui::Begin("Background texture2", nullptr, kPopupFlags))
|
if (ImGui::Begin("Background texture2", nullptr, kPopupFlags))
|
||||||
{
|
{
|
||||||
if (g_shaderCacheLoaderState.textureDRCId)
|
if (g_shaderCacheLoaderState.textureDRCId)
|
||||||
{
|
{
|
||||||
float imageDisplayWidth = io.DisplaySize.x;
|
float imageDisplayWidth = io.DisplaySize.x;
|
||||||
@@ -383,11 +383,11 @@ void LatteShaderCache_load()
|
|||||||
|
|
||||||
ImGui::GetWindowDrawList()->AddImage(g_shaderCacheLoaderState.textureDRCId, ImVec2(paddingLeftAndRight, paddingTopAndBottom), ImVec2(io.DisplaySize.x-paddingLeftAndRight, io.DisplaySize.y-paddingTopAndBottom), { 0,1 }, { 1,0 });
|
ImGui::GetWindowDrawList()->AddImage(g_shaderCacheLoaderState.textureDRCId, ImVec2(paddingLeftAndRight, paddingTopAndBottom), ImVec2(io.DisplaySize.x-paddingLeftAndRight, io.DisplaySize.y-paddingTopAndBottom), { 0,1 }, { 1,0 });
|
||||||
}
|
}
|
||||||
ImGui::End();
|
}
|
||||||
ImGui::PopStyleVar(2);
|
ImGui::End();
|
||||||
g_renderer->ImguiEnd();
|
ImGui::PopStyleVar(2);
|
||||||
}
|
g_renderer->ImguiEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
g_renderer->SwapBuffers(true, true);
|
g_renderer->SwapBuffers(true, true);
|
||||||
}
|
}
|
||||||
@@ -452,8 +452,8 @@ void LatteShaderCache_ShowProgress(const std::function <bool(void)>& loadUpdateF
|
|||||||
}
|
}
|
||||||
|
|
||||||
ImGui::GetWindowDrawList()->AddImage(g_shaderCacheLoaderState.textureTVId, ImVec2(paddingLeftAndRight, paddingTopAndBottom), ImVec2(io.DisplaySize.x-paddingLeftAndRight, io.DisplaySize.y-paddingTopAndBottom), { 0,1 }, { 1,0 });
|
ImGui::GetWindowDrawList()->AddImage(g_shaderCacheLoaderState.textureTVId, ImVec2(paddingLeftAndRight, paddingTopAndBottom), ImVec2(io.DisplaySize.x-paddingLeftAndRight, io.DisplaySize.y-paddingTopAndBottom), { 0,1 }, { 1,0 });
|
||||||
ImGui::End();
|
|
||||||
}
|
}
|
||||||
|
ImGui::End();
|
||||||
ImGui::PopStyleVar(2);
|
ImGui::PopStyleVar(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -502,8 +502,8 @@ void LatteShaderCache_ShowProgress(const std::function <bool(void)>& loadUpdateF
|
|||||||
text = fmt::format("{}/{} ({}%)", g_shaderCacheLoaderState.loadedShaderFiles, g_shaderCacheLoaderState.shaderFileCount, (int)(percentLoaded * 100));
|
text = fmt::format("{}/{} ({}%)", g_shaderCacheLoaderState.loadedShaderFiles, g_shaderCacheLoaderState.shaderFileCount, (int)(percentLoaded * 100));
|
||||||
ImGui::SetCursorPosX(width - ImGui::CalcTextSize(text.c_str()).x / 2);
|
ImGui::SetCursorPosX(width - ImGui::CalcTextSize(text.c_str()).x / 2);
|
||||||
ImGui::Text("%s", text.c_str());
|
ImGui::Text("%s", text.c_str());
|
||||||
ImGui::End();
|
|
||||||
}
|
}
|
||||||
|
ImGui::End();
|
||||||
ImGui::PopFont();
|
ImGui::PopFont();
|
||||||
ImGui::PopStyleColor(2);
|
ImGui::PopStyleColor(2);
|
||||||
|
|
||||||
@@ -529,13 +529,11 @@ void LatteShaderCache_ShowProgress(const std::function <bool(void)>& loadUpdateF
|
|||||||
ImGui::Text("Geometry shaders");
|
ImGui::Text("Geometry shaders");
|
||||||
ImGui::SameLine(offset);
|
ImGui::SameLine(offset);
|
||||||
ImGui::Text("%d", shaderCacheScreenStats.geometryShaderCount);
|
ImGui::Text("%d", shaderCacheScreenStats.geometryShaderCount);
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
}
|
}
|
||||||
|
ImGui::End();
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
ImGui::PopFont();
|
ImGui::PopFont();
|
||||||
}
|
}
|
||||||
|
|
||||||
g_renderer->ImguiEnd();
|
g_renderer->ImguiEnd();
|
||||||
lastFrameUpdate = tick_cached();
|
lastFrameUpdate = tick_cached();
|
||||||
}
|
}
|
||||||
@@ -565,11 +563,11 @@ void LatteShaderCache_ShowProgress(const std::function <bool(void)>& loadUpdateF
|
|||||||
}
|
}
|
||||||
ImGui::GetWindowDrawList()->AddImage(g_shaderCacheLoaderState.textureDRCId, ImVec2(paddingLeftAndRight, paddingTopAndBottom), ImVec2(io.DisplaySize.x-paddingLeftAndRight, io.DisplaySize.y-paddingTopAndBottom), { 0,1 }, { 1,0 });
|
ImGui::GetWindowDrawList()->AddImage(g_shaderCacheLoaderState.textureDRCId, ImVec2(paddingLeftAndRight, paddingTopAndBottom), ImVec2(io.DisplaySize.x-paddingLeftAndRight, io.DisplaySize.y-paddingTopAndBottom), { 0,1 }, { 1,0 });
|
||||||
}
|
}
|
||||||
ImGui::End();
|
}
|
||||||
ImGui::PopStyleVar(2);
|
ImGui::End();
|
||||||
g_renderer->ImguiEnd();
|
ImGui::PopStyleVar(2);
|
||||||
}
|
g_renderer->ImguiEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
// finish frame
|
// finish frame
|
||||||
g_renderer->SwapBuffers(true, true);
|
g_renderer->SwapBuffers(true, true);
|
||||||
|
|||||||
@@ -25,8 +25,10 @@
|
|||||||
#define STRINGIFY(X) STRINGIFY2(X)
|
#define STRINGIFY(X) STRINGIFY2(X)
|
||||||
|
|
||||||
#define GLFUNC(__type, __name) __type __name;
|
#define GLFUNC(__type, __name) __type __name;
|
||||||
|
#define EGLFUNC(__type, __name) __type __name;
|
||||||
#include "Common/GLInclude/glFunctions.h"
|
#include "Common/GLInclude/glFunctions.h"
|
||||||
#undef GLFUNC
|
#undef GLFUNC
|
||||||
|
#undef EGLFUNC
|
||||||
|
|
||||||
#include "config/ActiveSettings.h"
|
#include "config/ActiveSettings.h"
|
||||||
#include "config/LaunchSettings.h"
|
#include "config/LaunchSettings.h"
|
||||||
@@ -229,9 +231,17 @@ void LoadOpenGLImports()
|
|||||||
_glXGetProcAddress = (PFNGLXGETPROCADDRESSPROC)dlsym(libGL, "glXGetProcAddressARB");
|
_glXGetProcAddress = (PFNGLXGETPROCADDRESSPROC)dlsym(libGL, "glXGetProcAddressARB");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* libEGL = dlopen("libEGL.so.1", RTLD_NOW | RTLD_GLOBAL);
|
||||||
|
if(!libEGL)
|
||||||
|
{
|
||||||
|
libGL = dlopen("libEGL.so", RTLD_NOW | RTLD_GLOBAL);
|
||||||
|
}
|
||||||
|
|
||||||
#define GLFUNC(__type, __name) __name = (__type)_GetOpenGLFunction(libGL, _glXGetProcAddress, STRINGIFY(__name));
|
#define GLFUNC(__type, __name) __name = (__type)_GetOpenGLFunction(libGL, _glXGetProcAddress, STRINGIFY(__name));
|
||||||
|
#define EGLFUNC(__type, __name) __name = (__type)dlsym(libEGL, STRINGIFY(__name));
|
||||||
#include "Common/GLInclude/glFunctions.h"
|
#include "Common/GLInclude/glFunctions.h"
|
||||||
#undef GLFUNC
|
#undef GLFUNC
|
||||||
|
#undef EGLFUNC
|
||||||
}
|
}
|
||||||
#elif BOOST_OS_MACOS
|
#elif BOOST_OS_MACOS
|
||||||
void LoadOpenGLImports()
|
void LoadOpenGLImports()
|
||||||
@@ -352,20 +362,6 @@ void OpenGLRenderer::NotifyLatteCommandProcessorIdle()
|
|||||||
glFlush();
|
glFlush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLRenderer::UpdateVSyncState()
|
|
||||||
{
|
|
||||||
int configValue = GetConfig().vsync.GetValue();
|
|
||||||
if(m_activeVSyncState != configValue)
|
|
||||||
{
|
|
||||||
#if BOOST_OS_WINDOWS
|
|
||||||
if(wglSwapIntervalEXT)
|
|
||||||
wglSwapIntervalEXT(configValue); // 1 = enabled, 0 = disabled
|
|
||||||
#else
|
|
||||||
cemuLog_log(LogType::Force, "OpenGL vsync not implemented");
|
|
||||||
#endif
|
|
||||||
m_activeVSyncState = configValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsRunningInWine();
|
bool IsRunningInWine();
|
||||||
|
|
||||||
@@ -443,7 +439,6 @@ void OpenGLRenderer::EnableDebugMode()
|
|||||||
void OpenGLRenderer::SwapBuffers(bool swapTV, bool swapDRC)
|
void OpenGLRenderer::SwapBuffers(bool swapTV, bool swapDRC)
|
||||||
{
|
{
|
||||||
GLCanvas_SwapBuffers(swapTV, swapDRC);
|
GLCanvas_SwapBuffers(swapTV, swapDRC);
|
||||||
UpdateVSyncState();
|
|
||||||
|
|
||||||
if (swapTV)
|
if (swapTV)
|
||||||
cleanupAfterFrame();
|
cleanupAfterFrame();
|
||||||
|
|||||||
@@ -168,7 +168,6 @@ private:
|
|||||||
GLuint m_defaultFramebufferId;
|
GLuint m_defaultFramebufferId;
|
||||||
GLuint m_pipeline = 0;
|
GLuint m_pipeline = 0;
|
||||||
|
|
||||||
int m_activeVSyncState{};
|
|
||||||
bool m_isPadViewContext{};
|
bool m_isPadViewContext{};
|
||||||
|
|
||||||
// rendertarget viewport
|
// rendertarget viewport
|
||||||
|
|||||||
@@ -0,0 +1,365 @@
|
|||||||
|
#include "SwapchainInfoVk.h"
|
||||||
|
|
||||||
|
#include "config/CemuConfig.h"
|
||||||
|
#include "Cafe/HW/Latte/Core/Latte.h"
|
||||||
|
#include "Cafe/HW/Latte/Core/LatteTiming.h"
|
||||||
|
#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h"
|
||||||
|
|
||||||
|
void SwapchainInfoVk::Create(VkPhysicalDevice physicalDevice, VkDevice logicalDevice)
|
||||||
|
{
|
||||||
|
m_physicalDevice = physicalDevice;
|
||||||
|
m_logicalDevice = logicalDevice;
|
||||||
|
const auto details = QuerySwapchainSupport(surface, physicalDevice);
|
||||||
|
m_surfaceFormat = ChooseSurfaceFormat(details.formats);
|
||||||
|
m_actualExtent = ChooseSwapExtent(details.capabilities);
|
||||||
|
|
||||||
|
// calculate number of swapchain presentation images
|
||||||
|
uint32_t image_count = details.capabilities.minImageCount + 1;
|
||||||
|
if (details.capabilities.maxImageCount > 0 && image_count > details.capabilities.maxImageCount)
|
||||||
|
image_count = details.capabilities.maxImageCount;
|
||||||
|
|
||||||
|
VkSwapchainCreateInfoKHR create_info = CreateSwapchainCreateInfo(surface, details, m_surfaceFormat, image_count, m_actualExtent);
|
||||||
|
create_info.oldSwapchain = nullptr;
|
||||||
|
create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||||
|
|
||||||
|
VkResult result = vkCreateSwapchainKHR(logicalDevice, &create_info, nullptr, &swapchain);
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
UnrecoverableError("Error attempting to create a swapchain");
|
||||||
|
|
||||||
|
result = vkGetSwapchainImagesKHR(logicalDevice, swapchain, &image_count, nullptr);
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
UnrecoverableError("Error attempting to retrieve the count of swapchain images");
|
||||||
|
|
||||||
|
|
||||||
|
m_swapchainImages.resize(image_count);
|
||||||
|
result = vkGetSwapchainImagesKHR(logicalDevice, swapchain, &image_count, m_swapchainImages.data());
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
UnrecoverableError("Error attempting to retrieve swapchain images");
|
||||||
|
// create default renderpass
|
||||||
|
VkAttachmentDescription colorAttachment = {};
|
||||||
|
colorAttachment.format = m_surfaceFormat.format;
|
||||||
|
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
|
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
|
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
|
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
|
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||||
|
|
||||||
|
VkAttachmentReference colorAttachmentRef = {};
|
||||||
|
colorAttachmentRef.attachment = 0;
|
||||||
|
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
VkSubpassDescription subpass = {};
|
||||||
|
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||||
|
subpass.colorAttachmentCount = 1;
|
||||||
|
subpass.pColorAttachments = &colorAttachmentRef;
|
||||||
|
|
||||||
|
VkRenderPassCreateInfo renderPassInfo = {};
|
||||||
|
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||||
|
renderPassInfo.attachmentCount = 1;
|
||||||
|
renderPassInfo.pAttachments = &colorAttachment;
|
||||||
|
renderPassInfo.subpassCount = 1;
|
||||||
|
renderPassInfo.pSubpasses = &subpass;
|
||||||
|
result = vkCreateRenderPass(logicalDevice, &renderPassInfo, nullptr, &m_swapchainRenderPass);
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
UnrecoverableError("Failed to create renderpass for swapchain");
|
||||||
|
|
||||||
|
// create swapchain image views
|
||||||
|
m_swapchainImageViews.resize(m_swapchainImages.size());
|
||||||
|
for (sint32 i = 0; i < m_swapchainImages.size(); i++)
|
||||||
|
{
|
||||||
|
VkImageViewCreateInfo createInfo = {};
|
||||||
|
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||||
|
createInfo.image = m_swapchainImages[i];
|
||||||
|
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||||
|
createInfo.format = m_surfaceFormat.format;
|
||||||
|
createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||||
|
createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||||
|
createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||||
|
createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||||
|
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
createInfo.subresourceRange.baseMipLevel = 0;
|
||||||
|
createInfo.subresourceRange.levelCount = 1;
|
||||||
|
createInfo.subresourceRange.baseArrayLayer = 0;
|
||||||
|
createInfo.subresourceRange.layerCount = 1;
|
||||||
|
result = vkCreateImageView(logicalDevice, &createInfo, nullptr, &m_swapchainImageViews[i]);
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
UnrecoverableError("Failed to create imageviews for swapchain");
|
||||||
|
}
|
||||||
|
|
||||||
|
// create swapchain framebuffers
|
||||||
|
m_swapchainFramebuffers.resize(m_swapchainImages.size());
|
||||||
|
for (size_t i = 0; i < m_swapchainImages.size(); i++)
|
||||||
|
{
|
||||||
|
VkImageView attachments[1];
|
||||||
|
attachments[0] = m_swapchainImageViews[i];
|
||||||
|
// create framebuffer
|
||||||
|
VkFramebufferCreateInfo framebufferInfo = {};
|
||||||
|
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||||
|
framebufferInfo.renderPass = m_swapchainRenderPass;
|
||||||
|
framebufferInfo.attachmentCount = 1;
|
||||||
|
framebufferInfo.pAttachments = attachments;
|
||||||
|
framebufferInfo.width = m_actualExtent.width;
|
||||||
|
framebufferInfo.height = m_actualExtent.height;
|
||||||
|
framebufferInfo.layers = 1;
|
||||||
|
result = vkCreateFramebuffer(logicalDevice, &framebufferInfo, nullptr, &m_swapchainFramebuffers[i]);
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
UnrecoverableError("Failed to create framebuffer for swapchain");
|
||||||
|
}
|
||||||
|
m_swapchainPresentSemaphores.resize(m_swapchainImages.size());
|
||||||
|
// create present semaphore
|
||||||
|
VkSemaphoreCreateInfo info = {};
|
||||||
|
info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||||
|
for (auto& semaphore : m_swapchainPresentSemaphores){
|
||||||
|
if (vkCreateSemaphore(logicalDevice, &info, nullptr, &semaphore) != VK_SUCCESS)
|
||||||
|
UnrecoverableError("Failed to create semaphore for swapchain present");
|
||||||
|
}
|
||||||
|
|
||||||
|
m_acquireSemaphores.resize(m_swapchainImages.size());
|
||||||
|
for (auto& semaphore : m_acquireSemaphores)
|
||||||
|
{
|
||||||
|
VkSemaphoreCreateInfo info = {};
|
||||||
|
info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||||
|
if (vkCreateSemaphore(logicalDevice, &info, nullptr, &semaphore) != VK_SUCCESS)
|
||||||
|
UnrecoverableError("Failed to create semaphore for swapchain acquire");
|
||||||
|
}
|
||||||
|
m_acquireIndex = 0;
|
||||||
|
|
||||||
|
VkFenceCreateInfo fenceInfo = {};
|
||||||
|
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
||||||
|
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
||||||
|
result = vkCreateFence(logicalDevice, &fenceInfo, nullptr, &m_imageAvailableFence);
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
UnrecoverableError("Failed to create fence for swapchain");
|
||||||
|
}
|
||||||
|
|
||||||
|
void SwapchainInfoVk::Cleanup()
|
||||||
|
{
|
||||||
|
m_swapchainImages.clear();
|
||||||
|
|
||||||
|
for (auto& sem: m_swapchainPresentSemaphores)
|
||||||
|
vkDestroySemaphore(m_logicalDevice, sem, nullptr);
|
||||||
|
m_swapchainPresentSemaphores.clear();
|
||||||
|
|
||||||
|
for (auto& itr: m_acquireSemaphores)
|
||||||
|
vkDestroySemaphore(m_logicalDevice, itr, nullptr);
|
||||||
|
m_acquireSemaphores.clear();
|
||||||
|
|
||||||
|
if (m_swapchainRenderPass)
|
||||||
|
{
|
||||||
|
vkDestroyRenderPass(m_logicalDevice, m_swapchainRenderPass, nullptr);
|
||||||
|
m_swapchainRenderPass = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& imageView : m_swapchainImageViews)
|
||||||
|
vkDestroyImageView(m_logicalDevice, imageView, nullptr);
|
||||||
|
m_swapchainImageViews.clear();
|
||||||
|
|
||||||
|
for (auto& framebuffer : m_swapchainFramebuffers)
|
||||||
|
vkDestroyFramebuffer(m_logicalDevice, framebuffer, nullptr);
|
||||||
|
m_swapchainFramebuffers.clear();
|
||||||
|
|
||||||
|
|
||||||
|
if (m_imageAvailableFence)
|
||||||
|
{
|
||||||
|
vkDestroyFence(m_logicalDevice, m_imageAvailableFence, nullptr);
|
||||||
|
m_imageAvailableFence = nullptr;
|
||||||
|
}
|
||||||
|
if (swapchain)
|
||||||
|
{
|
||||||
|
vkDestroySwapchainKHR(m_logicalDevice, swapchain, nullptr);
|
||||||
|
swapchain = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SwapchainInfoVk::IsValid() const
|
||||||
|
{
|
||||||
|
return swapchain && m_imageAvailableFence;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SwapchainInfoVk::UnrecoverableError(const char* errMsg)
|
||||||
|
{
|
||||||
|
forceLog_printf("Unrecoverable error in Vulkan swapchain");
|
||||||
|
forceLog_printf("Msg: %s", errMsg);
|
||||||
|
throw std::runtime_error(errMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
SwapchainInfoVk::QueueFamilyIndices SwapchainInfoVk::FindQueueFamilies(VkSurfaceKHR surface, VkPhysicalDevice device)
|
||||||
|
{
|
||||||
|
uint32_t queueFamilyCount = 0;
|
||||||
|
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
|
||||||
|
|
||||||
|
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
|
||||||
|
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
|
||||||
|
|
||||||
|
QueueFamilyIndices indices;
|
||||||
|
for (int i = 0; i < (int)queueFamilies.size(); ++i)
|
||||||
|
{
|
||||||
|
const auto& queueFamily = queueFamilies[i];
|
||||||
|
if (queueFamily.queueCount > 0 && queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)
|
||||||
|
indices.graphicsFamily = i;
|
||||||
|
|
||||||
|
VkBool32 presentSupport = false;
|
||||||
|
const VkResult result = vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport);
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
throw std::runtime_error(fmt::format("Error while attempting to check if a surface supports presentation: {}", result));
|
||||||
|
|
||||||
|
if (queueFamily.queueCount > 0 && presentSupport)
|
||||||
|
indices.presentFamily = i;
|
||||||
|
|
||||||
|
if (indices.IsComplete())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return indices;
|
||||||
|
}
|
||||||
|
|
||||||
|
SwapchainInfoVk::SwapchainSupportDetails SwapchainInfoVk::QuerySwapchainSupport(VkSurfaceKHR surface, const VkPhysicalDevice& device)
|
||||||
|
{
|
||||||
|
SwapchainSupportDetails details;
|
||||||
|
|
||||||
|
VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities);
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
if (result != VK_ERROR_SURFACE_LOST_KHR)
|
||||||
|
forceLog_printf("vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed. Error %d", (sint32)result);
|
||||||
|
throw std::runtime_error(fmt::format("Unable to retrieve physical device surface capabilities: {}", result));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t formatCount = 0;
|
||||||
|
result = vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
forceLog_printf("vkGetPhysicalDeviceSurfaceFormatsKHR failed. Error %d", (sint32)result);
|
||||||
|
throw std::runtime_error(fmt::format("Unable to retrieve the number of formats for a surface on a physical device: {}", result));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formatCount != 0)
|
||||||
|
{
|
||||||
|
details.formats.resize(formatCount);
|
||||||
|
result = vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, details.formats.data());
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
forceLog_printf("vkGetPhysicalDeviceSurfaceFormatsKHR failed. Error %d", (sint32)result);
|
||||||
|
throw std::runtime_error(fmt::format("Unable to retrieve the formats for a surface on a physical device: {}", result));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t presentModeCount = 0;
|
||||||
|
result = vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr);
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
forceLog_printf("vkGetPhysicalDeviceSurfacePresentModesKHR failed. Error %d", (sint32)result);
|
||||||
|
throw std::runtime_error(fmt::format("Unable to retrieve the count of present modes for a surface on a physical device: {}", result));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (presentModeCount != 0)
|
||||||
|
{
|
||||||
|
details.presentModes.resize(presentModeCount);
|
||||||
|
result = vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, details.presentModes.data());
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
forceLog_printf("vkGetPhysicalDeviceSurfacePresentModesKHR failed. Error %d", (sint32)result);
|
||||||
|
throw std::runtime_error(fmt::format("Unable to retrieve the present modes for a surface on a physical device: {}", result));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return details;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkSurfaceFormatKHR SwapchainInfoVk::ChooseSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& formats) const
|
||||||
|
{
|
||||||
|
if (formats.size() == 1 && formats[0].format == VK_FORMAT_UNDEFINED)
|
||||||
|
return{ VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
|
||||||
|
|
||||||
|
for (const auto& format : formats)
|
||||||
|
{
|
||||||
|
bool useSRGB = mainWindow ? LatteGPUState.tvBufferUsesSRGB : LatteGPUState.drcBufferUsesSRGB;
|
||||||
|
|
||||||
|
if (useSRGB)
|
||||||
|
{
|
||||||
|
if (format.format == VK_FORMAT_B8G8R8A8_SRGB && format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (format.format == VK_FORMAT_B8G8R8A8_UNORM && format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return formats[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
VkExtent2D SwapchainInfoVk::ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities) const
|
||||||
|
{
|
||||||
|
if (capabilities.currentExtent.width != std::numeric_limits<uint32>::max())
|
||||||
|
return capabilities.currentExtent;
|
||||||
|
|
||||||
|
VkExtent2D actualExtent = { (uint32)m_desiredExtent.x, (uint32)m_desiredExtent.y };
|
||||||
|
actualExtent.width = std::max(capabilities.minImageExtent.width, std::min(capabilities.maxImageExtent.width, actualExtent.width));
|
||||||
|
actualExtent.height = std::max(capabilities.minImageExtent.height, std::min(capabilities.maxImageExtent.height, actualExtent.height));
|
||||||
|
return actualExtent;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPresentModeKHR SwapchainInfoVk::ChoosePresentMode(const std::vector<VkPresentModeKHR>& modes)
|
||||||
|
{
|
||||||
|
const auto vsyncState = (VSync)GetConfig().vsync.GetValue();
|
||||||
|
if (vsyncState == VSync::MAILBOX)
|
||||||
|
{
|
||||||
|
if (std::find(modes.cbegin(), modes.cend(), VK_PRESENT_MODE_MAILBOX_KHR) != modes.cend())
|
||||||
|
return VK_PRESENT_MODE_MAILBOX_KHR;
|
||||||
|
|
||||||
|
forceLog_printf("Vulkan: Can't find mailbox present mode");
|
||||||
|
}
|
||||||
|
else if (vsyncState == VSync::Immediate)
|
||||||
|
{
|
||||||
|
if (std::find(modes.cbegin(), modes.cend(), VK_PRESENT_MODE_IMMEDIATE_KHR) != modes.cend())
|
||||||
|
return VK_PRESENT_MODE_IMMEDIATE_KHR;
|
||||||
|
|
||||||
|
forceLog_printf("Vulkan: Can't find immediate present mode");
|
||||||
|
}
|
||||||
|
else if (vsyncState == VSync::SYNC_AND_LIMIT)
|
||||||
|
{
|
||||||
|
LatteTiming_EnableHostDrivenVSync();
|
||||||
|
// use immediate mode if available, other wise fall back to
|
||||||
|
//if (std::find(modes.cbegin(), modes.cend(), VK_PRESENT_MODE_IMMEDIATE_KHR) != modes.cend())
|
||||||
|
// return VK_PRESENT_MODE_IMMEDIATE_KHR;
|
||||||
|
//else
|
||||||
|
// forceLog_printf("Vulkan: Present mode 'immediate' not available. Vsync might not behave as intended");
|
||||||
|
return VK_PRESENT_MODE_FIFO_KHR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return VK_PRESENT_MODE_FIFO_KHR;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkSwapchainCreateInfoKHR SwapchainInfoVk::CreateSwapchainCreateInfo(VkSurfaceKHR surface, const SwapchainSupportDetails& swapchainSupport, const VkSurfaceFormatKHR& surfaceFormat, uint32 imageCount, const VkExtent2D& extent)
|
||||||
|
{
|
||||||
|
VkSwapchainCreateInfoKHR createInfo{};
|
||||||
|
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||||
|
createInfo.surface = surface;
|
||||||
|
createInfo.minImageCount = imageCount;
|
||||||
|
createInfo.imageFormat = surfaceFormat.format;
|
||||||
|
createInfo.imageExtent = extent;
|
||||||
|
createInfo.imageArrayLayers = 1;
|
||||||
|
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||||
|
|
||||||
|
const QueueFamilyIndices indices = FindQueueFamilies(surface, m_physicalDevice);
|
||||||
|
uint32_t queueFamilyIndices[] = { (uint32)indices.graphicsFamily, (uint32)indices.presentFamily };
|
||||||
|
if (indices.graphicsFamily != indices.presentFamily)
|
||||||
|
{
|
||||||
|
createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
|
||||||
|
createInfo.queueFamilyIndexCount = 2;
|
||||||
|
createInfo.pQueueFamilyIndices = queueFamilyIndices;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
|
||||||
|
createInfo.preTransform = swapchainSupport.capabilities.currentTransform;
|
||||||
|
createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||||
|
createInfo.presentMode = ChoosePresentMode(swapchainSupport.presentModes);
|
||||||
|
createInfo.clipped = VK_TRUE;
|
||||||
|
|
||||||
|
forceLogDebug_printf("vulkan presentation mode: %d", createInfo.presentMode);
|
||||||
|
return createInfo;
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "util/math/vector2.h"
|
||||||
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
|
struct SwapchainInfoVk
|
||||||
|
{
|
||||||
|
enum class VSync
|
||||||
|
{
|
||||||
|
// values here must match GeneralSettings2::m_vsync
|
||||||
|
Immediate = 0,
|
||||||
|
FIFO = 1,
|
||||||
|
MAILBOX = 2,
|
||||||
|
SYNC_AND_LIMIT = 3, // synchronize emulated vsync events to monitor vsync. But skip events if rate higher than virtual vsync period
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueFamilyIndices
|
||||||
|
{
|
||||||
|
int32_t graphicsFamily = -1;
|
||||||
|
int32_t presentFamily = -1;
|
||||||
|
|
||||||
|
bool IsComplete() const { return graphicsFamily >= 0 && presentFamily >= 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SwapchainSupportDetails
|
||||||
|
{
|
||||||
|
VkSurfaceCapabilitiesKHR capabilities;
|
||||||
|
std::vector<VkSurfaceFormatKHR> formats;
|
||||||
|
std::vector<VkPresentModeKHR> presentModes;
|
||||||
|
};
|
||||||
|
|
||||||
|
void Cleanup();
|
||||||
|
void Create(VkPhysicalDevice physicalDevice, VkDevice logicalDevice);
|
||||||
|
|
||||||
|
bool IsValid() const;
|
||||||
|
|
||||||
|
static void UnrecoverableError(const char* errMsg);
|
||||||
|
|
||||||
|
// todo: move this function somewhere more sensible. Not directly swapchain related
|
||||||
|
static QueueFamilyIndices FindQueueFamilies(VkSurfaceKHR surface, VkPhysicalDevice device);
|
||||||
|
static SwapchainSupportDetails QuerySwapchainSupport(VkSurfaceKHR surface, const VkPhysicalDevice& device);
|
||||||
|
|
||||||
|
VkPresentModeKHR ChoosePresentMode(const std::vector<VkPresentModeKHR>& modes);
|
||||||
|
VkSurfaceFormatKHR ChooseSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& formats) const;
|
||||||
|
VkExtent2D ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities) const;
|
||||||
|
|
||||||
|
VkSwapchainCreateInfoKHR CreateSwapchainCreateInfo(VkSurfaceKHR surface, const SwapchainSupportDetails& swapchainSupport, const VkSurfaceFormatKHR& surfaceFormat, uint32 imageCount, const VkExtent2D& extent);
|
||||||
|
|
||||||
|
|
||||||
|
VkExtent2D getExtent() const
|
||||||
|
{
|
||||||
|
return m_actualExtent;
|
||||||
|
}
|
||||||
|
|
||||||
|
SwapchainInfoVk(VkSurfaceKHR surface, bool mainWindow)
|
||||||
|
: surface(surface), mainWindow(mainWindow) {}
|
||||||
|
SwapchainInfoVk(const SwapchainInfoVk&) = delete;
|
||||||
|
SwapchainInfoVk(SwapchainInfoVk&&) noexcept = default;
|
||||||
|
~SwapchainInfoVk()
|
||||||
|
{
|
||||||
|
Cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mainWindow{};
|
||||||
|
|
||||||
|
bool m_shouldRecreate = false;
|
||||||
|
bool m_usesSRGB = false;
|
||||||
|
VSync m_vsyncState = VSync::Immediate;
|
||||||
|
bool hasDefinedSwapchainImage{}; // indicates if the swapchain image is in a defined state
|
||||||
|
|
||||||
|
VkPhysicalDevice m_physicalDevice{};
|
||||||
|
VkDevice m_logicalDevice{};
|
||||||
|
VkSurfaceKHR surface{};
|
||||||
|
VkSurfaceFormatKHR m_surfaceFormat{};
|
||||||
|
VkSwapchainKHR swapchain{};
|
||||||
|
Vector2i m_desiredExtent{};
|
||||||
|
VkFence m_imageAvailableFence{};
|
||||||
|
uint32 swapchainImageIndex = (uint32)-1;
|
||||||
|
uint32 m_acquireIndex = 0; // increases with every successful vkAcquireNextImageKHR
|
||||||
|
|
||||||
|
|
||||||
|
// swapchain image ringbuffer (indexed by swapchainImageIndex)
|
||||||
|
std::vector<VkImage> m_swapchainImages;
|
||||||
|
std::vector<VkImageView> m_swapchainImageViews;
|
||||||
|
std::vector<VkFramebuffer> m_swapchainFramebuffers;
|
||||||
|
std::vector<VkSemaphore> m_swapchainPresentSemaphores;
|
||||||
|
std::vector<VkSemaphore> m_acquireSemaphores; // indexed by acquireIndex
|
||||||
|
|
||||||
|
VkRenderPass m_swapchainRenderPass = nullptr;
|
||||||
|
|
||||||
|
private:
|
||||||
|
VkExtent2D m_actualExtent{};
|
||||||
|
};
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Cafe/HW/Latte/Renderer/Renderer.h"
|
#include "Cafe/HW/Latte/Renderer/Renderer.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h"
|
#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.h"
|
#include "Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.h"
|
||||||
@@ -6,6 +7,7 @@
|
|||||||
#include "Cafe/HW/Latte/Renderer/Vulkan/LatteTextureViewVk.h"
|
#include "Cafe/HW/Latte/Renderer/Vulkan/LatteTextureViewVk.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Vulkan/CachedFBOVk.h"
|
#include "Cafe/HW/Latte/Renderer/Vulkan/CachedFBOVk.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Vulkan/VKRMemoryManager.h"
|
#include "Cafe/HW/Latte/Renderer/Vulkan/VKRMemoryManager.h"
|
||||||
|
#include "Cafe/HW/Latte/Renderer/Vulkan/SwapchainInfoVk.h"
|
||||||
#include "util/math/vector2.h"
|
#include "util/math/vector2.h"
|
||||||
#include "util/helpers/Semaphore.h"
|
#include "util/helpers/Semaphore.h"
|
||||||
#include "util/containers/flat_hash_map.hpp"
|
#include "util/containers/flat_hash_map.hpp"
|
||||||
@@ -124,6 +126,9 @@ class VulkanRenderer : public Renderer
|
|||||||
friend class LatteTextureReadbackInfoVk;
|
friend class LatteTextureReadbackInfoVk;
|
||||||
friend class PipelineCompiler;
|
friend class PipelineCompiler;
|
||||||
|
|
||||||
|
using VSync = SwapchainInfoVk::VSync;
|
||||||
|
using QueueFamilyIndices = SwapchainInfoVk::QueueFamilyIndices;
|
||||||
|
|
||||||
static const inline int UNIFORMVAR_RINGBUFFER_SIZE = 1024 * 1024 * 16; // 16MB
|
static const inline int UNIFORMVAR_RINGBUFFER_SIZE = 1024 * 1024 * 16; // 16MB
|
||||||
static const inline int INDEX_STREAM_BUFFER_SIZE = 16 * 1024 * 1024; // 16 MB
|
static const inline int INDEX_STREAM_BUFFER_SIZE = 16 * 1024 * 1024; // 16 MB
|
||||||
|
|
||||||
@@ -132,15 +137,7 @@ class VulkanRenderer : public Renderer
|
|||||||
static const inline int OCCLUSION_QUERY_POOL_SIZE = 1024;
|
static const inline int OCCLUSION_QUERY_POOL_SIZE = 1024;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum class VSync
|
|
||||||
{
|
|
||||||
// values here must match GeneralSettings2::m_vsync
|
|
||||||
Immediate = 0,
|
|
||||||
FIFO = 1,
|
|
||||||
MAILBOX = 2,
|
|
||||||
SYNC_AND_LIMIT = 3, // synchronize emulated vsync events to monitor vsync. But skip events if rate higher than virtual vsync period
|
|
||||||
};
|
|
||||||
|
|
||||||
// memory management
|
// memory management
|
||||||
VKRMemoryManager* memoryManager{};
|
VKRMemoryManager* memoryManager{};
|
||||||
VKRMemoryManager* GetMemoryManager() const { return memoryManager; };
|
VKRMemoryManager* GetMemoryManager() const { return memoryManager; };
|
||||||
@@ -185,12 +182,15 @@ public:
|
|||||||
|
|
||||||
void GetDeviceFeatures();
|
void GetDeviceFeatures();
|
||||||
void DetermineVendor();
|
void DetermineVendor();
|
||||||
void Initialize(const Vector2i& size, bool isMainWindow);
|
void Initialize(const Vector2i& size, bool mainWindow);
|
||||||
|
|
||||||
|
const std::unique_ptr<SwapchainInfoVk>& GetChainInfoPtr(bool mainWindow) const;
|
||||||
|
SwapchainInfoVk& GetChainInfo(bool mainWindow) const;
|
||||||
|
|
||||||
|
void StopUsingPadAndWait();
|
||||||
bool IsPadWindowActive() override;
|
bool IsPadWindowActive() override;
|
||||||
|
|
||||||
void HandleScreenshotRequest(LatteTextureView* texView, bool padView) override;
|
void HandleScreenshotRequest(LatteTextureView* texView, bool padView) override;
|
||||||
void ResizeSwapchain(const Vector2i& size, bool isMainWindow);
|
|
||||||
|
|
||||||
void QueryMemoryInfo();
|
void QueryMemoryInfo();
|
||||||
void QueryAvailableFormats();
|
void QueryAvailableFormats();
|
||||||
@@ -210,7 +210,7 @@ public:
|
|||||||
void ImguiInit();
|
void ImguiInit();
|
||||||
VkInstance GetVkInstance() const { return m_instance; }
|
VkInstance GetVkInstance() const { return m_instance; }
|
||||||
VkDevice GetLogicalDevice() const { return m_logicalDevice; }
|
VkDevice GetLogicalDevice() const { return m_logicalDevice; }
|
||||||
VkPhysicalDevice GetPhysicalDevice() const { return m_physical_device; }
|
VkPhysicalDevice GetPhysicalDevice() const { return m_physicalDevice; }
|
||||||
|
|
||||||
VkDescriptorPool GetDescriptorPool() const { return m_descriptorPool; }
|
VkDescriptorPool GetDescriptorPool() const { return m_descriptorPool; }
|
||||||
|
|
||||||
@@ -431,86 +431,14 @@ private:
|
|||||||
bool drawSequenceSkip; // if true, skip draw_execute()
|
bool drawSequenceSkip; // if true, skip draw_execute()
|
||||||
}m_state;
|
}m_state;
|
||||||
|
|
||||||
// swapchain - todo move this to m_swapchainState
|
std::unique_ptr<SwapchainInfoVk> m_mainSwapchainInfo{}, m_padSwapchainInfo{};
|
||||||
struct SwapChainInfo
|
Semaphore m_padCloseReadySemaphore;
|
||||||
{
|
bool m_destroyPadSwapchainNextAcquire = false;
|
||||||
SwapChainInfo(VkDevice device, VkSurfaceKHR surface) : m_device(device), surface(surface) {}
|
|
||||||
SwapChainInfo(const SwapChainInfo&) = delete;
|
|
||||||
SwapChainInfo(SwapChainInfo&&) noexcept = default;
|
|
||||||
~SwapChainInfo()
|
|
||||||
{
|
|
||||||
if (m_swapChainRenderPass)
|
|
||||||
{
|
|
||||||
vkDestroyRenderPass(m_device, m_swapChainRenderPass, nullptr);
|
|
||||||
m_swapChainRenderPass = VK_NULL_HANDLE;
|
|
||||||
}
|
|
||||||
if (swapChain)
|
|
||||||
{
|
|
||||||
vkDestroySwapchainKHR(m_device, swapChain, nullptr);
|
|
||||||
swapChain = VK_NULL_HANDLE;
|
|
||||||
}
|
|
||||||
for (auto& imageView : m_swapchainImageViews)
|
|
||||||
vkDestroyImageView(m_device, imageView, nullptr);
|
|
||||||
m_swapchainImageViews.clear();
|
|
||||||
for (auto& framebuffer : m_swapchainFramebuffers)
|
|
||||||
vkDestroyFramebuffer(m_device, framebuffer, nullptr);
|
|
||||||
m_swapchainFramebuffers.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
VkDevice m_device;
|
|
||||||
|
|
||||||
VkSurfaceKHR surface{};
|
|
||||||
VkSwapchainKHR swapChain{};
|
|
||||||
VkExtent2D swapchainExtend{};
|
|
||||||
uint32 swapchainImageIndex = (uint32)-1;
|
|
||||||
uint32 m_acquireIndex = 0; // increases with every successful vkAcquireNextImageKHR
|
|
||||||
VSync m_activeVSyncState = VSync::Immediate;
|
|
||||||
|
|
||||||
struct AcquireInfo
|
|
||||||
{
|
|
||||||
// move fence here?
|
|
||||||
VkSemaphore acquireSemaphore;
|
|
||||||
};
|
|
||||||
std::vector<AcquireInfo> m_acquireInfo; // indexed by acquireIndex
|
|
||||||
|
|
||||||
// swapchain image ringbuffer (indexed by swapchainImageIndex)
|
|
||||||
std::vector<VkImage> m_swapchainImages;
|
|
||||||
std::vector<VkImageView> m_swapchainImageViews;
|
|
||||||
std::vector<VkFramebuffer> m_swapchainFramebuffers;
|
|
||||||
std::vector<VkSemaphore> m_swapchainPresentSemaphores;
|
|
||||||
|
|
||||||
VkFence m_imageAvailableFence = nullptr;
|
|
||||||
VkRenderPass m_swapChainRenderPass = nullptr;
|
|
||||||
VkRenderPass m_imguiRenderPass = nullptr;
|
|
||||||
};
|
|
||||||
std::unique_ptr<SwapChainInfo> m_mainSwapchainInfo{}, m_padSwapchainInfo{};
|
|
||||||
bool IsSwapchainInfoValid(bool mainWindow) const;
|
bool IsSwapchainInfoValid(bool mainWindow) const;
|
||||||
VkSwapchainKHR CreateSwapChain(SwapChainInfo& swap_chain_info, const Vector2i& size, bool mainwindow);
|
|
||||||
|
|
||||||
struct
|
VkRenderPass m_imguiRenderPass = nullptr;
|
||||||
{
|
|
||||||
bool resizeRequestedMainWindow{};
|
|
||||||
Vector2i newExtentMainWindow;
|
|
||||||
bool resizeRequestedPadWindow{};
|
|
||||||
Vector2i newExtentPadWindow;
|
|
||||||
bool tvHasDefinedSwapchainImage{}; // indicates if the swapchain image is in a defined state
|
|
||||||
bool drcHasDefinedSwapchainImage{};
|
|
||||||
}m_swapchainState;
|
|
||||||
|
|
||||||
VkDescriptorPool m_descriptorPool;
|
VkDescriptorPool m_descriptorPool;
|
||||||
VkSurfaceFormatKHR m_swapchainFormat;
|
|
||||||
|
|
||||||
bool m_tvBufferUsesSRGB = false;
|
|
||||||
bool m_drvBufferUsesSRGB = false;
|
|
||||||
|
|
||||||
struct QueueFamilyIndices
|
|
||||||
{
|
|
||||||
int32_t graphicsFamily = -1;
|
|
||||||
int32_t presentFamily = -1;
|
|
||||||
|
|
||||||
bool IsComplete() const { return graphicsFamily >= 0 && presentFamily >= 0; }
|
|
||||||
};
|
|
||||||
static QueueFamilyIndices FindQueueFamilies(VkSurfaceKHR surface, const VkPhysicalDevice& device);
|
|
||||||
|
|
||||||
struct FeatureControl
|
struct FeatureControl
|
||||||
{
|
{
|
||||||
@@ -556,15 +484,8 @@ private:
|
|||||||
static bool CheckDeviceExtensionSupport(const VkPhysicalDevice device, FeatureControl& info);
|
static bool CheckDeviceExtensionSupport(const VkPhysicalDevice device, FeatureControl& info);
|
||||||
static std::vector<const char*> CheckInstanceExtensionSupport(FeatureControl& info);
|
static std::vector<const char*> CheckInstanceExtensionSupport(FeatureControl& info);
|
||||||
|
|
||||||
void UpdateVSyncState(bool main_window);
|
bool UpdateSwapchainProperties(bool mainWindow);
|
||||||
void SwapBuffer(bool main_window);
|
void SwapBuffer(bool mainWindow);
|
||||||
|
|
||||||
struct SwapChainSupportDetails
|
|
||||||
{
|
|
||||||
VkSurfaceCapabilitiesKHR capabilities;
|
|
||||||
std::vector<VkSurfaceFormatKHR> formats;
|
|
||||||
std::vector<VkPresentModeKHR> presentModes;
|
|
||||||
};
|
|
||||||
|
|
||||||
VkDescriptorSetLayout m_swapchainDescriptorSetLayout;
|
VkDescriptorSetLayout m_swapchainDescriptorSetLayout;
|
||||||
|
|
||||||
@@ -572,14 +493,9 @@ private:
|
|||||||
|
|
||||||
// swapchain
|
// swapchain
|
||||||
|
|
||||||
static SwapChainSupportDetails QuerySwapChainSupport(VkSurfaceKHR surface, const VkPhysicalDevice& device);
|
|
||||||
std::vector<VkDeviceQueueCreateInfo> CreateQueueCreateInfos(const std::set<int>& uniqueQueueFamilies) const;
|
std::vector<VkDeviceQueueCreateInfo> CreateQueueCreateInfos(const std::set<int>& uniqueQueueFamilies) const;
|
||||||
VkDeviceCreateInfo CreateDeviceCreateInfo(const std::vector<VkDeviceQueueCreateInfo>& queueCreateInfos, const VkPhysicalDeviceFeatures& deviceFeatures, const void* deviceExtensionStructs, std::vector<const char*>& used_extensions) const;
|
VkDeviceCreateInfo CreateDeviceCreateInfo(const std::vector<VkDeviceQueueCreateInfo>& queueCreateInfos, const VkPhysicalDeviceFeatures& deviceFeatures, const void* deviceExtensionStructs, std::vector<const char*>& used_extensions) const;
|
||||||
static bool IsDeviceSuitable(VkSurfaceKHR surface, const VkPhysicalDevice& device);
|
static bool IsDeviceSuitable(VkSurfaceKHR surface, const VkPhysicalDevice& device);
|
||||||
VkSurfaceFormatKHR ChooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& formats, bool mainWindow) const;
|
|
||||||
VkPresentModeKHR ChooseSwapPresentMode(const std::vector<VkPresentModeKHR>& modes);
|
|
||||||
VkExtent2D ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, const Vector2i& size) const;
|
|
||||||
VkSwapchainCreateInfoKHR CreateSwapchainCreateInfo(VkSurfaceKHR surface, const SwapChainSupportDetails& swapChainSupport, const VkSurfaceFormatKHR& surfaceFormat, uint32 imageCount, const VkExtent2D& extent);
|
|
||||||
|
|
||||||
void CreateCommandPool();
|
void CreateCommandPool();
|
||||||
void CreateCommandBuffers();
|
void CreateCommandBuffers();
|
||||||
@@ -641,8 +557,8 @@ private:
|
|||||||
void CreatePipelineCache();
|
void CreatePipelineCache();
|
||||||
VkPipelineShaderStageCreateInfo CreatePipelineShaderStageCreateInfo(VkShaderStageFlagBits stage, VkShaderModule& module, const char* entryName) const;
|
VkPipelineShaderStageCreateInfo CreatePipelineShaderStageCreateInfo(VkShaderStageFlagBits stage, VkShaderModule& module, const char* entryName) const;
|
||||||
VkPipeline backbufferBlit_createGraphicsPipeline(VkDescriptorSetLayout descriptorLayout, bool padView, RendererOutputShader* shader);
|
VkPipeline backbufferBlit_createGraphicsPipeline(VkDescriptorSetLayout descriptorLayout, bool padView, RendererOutputShader* shader);
|
||||||
void AcquireNextSwapchainImage(bool main_window);
|
bool AcquireNextSwapchainImage(bool mainWindow);
|
||||||
void RecreateSwapchain(bool mainwindow);
|
void RecreateSwapchain(bool mainWindow, bool skipCreate = false);
|
||||||
|
|
||||||
// streamout
|
// streamout
|
||||||
void streamout_setupXfbBuffer(uint32 bufferIndex, sint32 ringBufferOffset, uint32 rangeAddr, uint32 rangeSize) override;
|
void streamout_setupXfbBuffer(uint32 bufferIndex, sint32 ringBufferOffset, uint32 rangeAddr, uint32 rangeSize) override;
|
||||||
@@ -665,7 +581,7 @@ private:
|
|||||||
|
|
||||||
std::vector<const char*> m_layerNames;
|
std::vector<const char*> m_layerNames;
|
||||||
VkInstance m_instance = VK_NULL_HANDLE;
|
VkInstance m_instance = VK_NULL_HANDLE;
|
||||||
VkPhysicalDevice m_physical_device = VK_NULL_HANDLE;
|
VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE;
|
||||||
VkDevice m_logicalDevice = VK_NULL_HANDLE;
|
VkDevice m_logicalDevice = VK_NULL_HANDLE;
|
||||||
VkDebugUtilsMessengerEXT m_debugCallback = nullptr;
|
VkDebugUtilsMessengerEXT m_debugCallback = nullptr;
|
||||||
volatile bool m_destructionRequested = false;
|
volatile bool m_destructionRequested = false;
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ void iosuCrypto_generateDeviceCertificate()
|
|||||||
BIGNUM* bn_x = BN_CTX_get(context);
|
BIGNUM* bn_x = BN_CTX_get(context);
|
||||||
BIGNUM* bn_y = BN_CTX_get(context);
|
BIGNUM* bn_y = BN_CTX_get(context);
|
||||||
|
|
||||||
EC_POINT_get_affine_coordinates_GF2m(group, pubkey, bn_x, bn_y, NULL);
|
EC_POINT_get_affine_coordinates(group, pubkey, bn_x, bn_y, NULL);
|
||||||
|
|
||||||
uint8 publicKeyOutput[0x3C];
|
uint8 publicKeyOutput[0x3C];
|
||||||
memset(publicKeyOutput, 0, sizeof(publicKeyOutput));
|
memset(publicKeyOutput, 0, sizeof(publicKeyOutput));
|
||||||
|
|||||||
@@ -346,7 +346,6 @@ namespace erreula
|
|||||||
std::string button2 = "No";
|
std::string button2 = "No";
|
||||||
if (appearArg.button2Text)
|
if (appearArg.button2Text)
|
||||||
button2 = boost::nowide::narrow(GetText(appearArg.button2Text.GetPtr()));
|
button2 = boost::nowide::narrow(GetText(appearArg.button2Text.GetPtr()));
|
||||||
|
|
||||||
|
|
||||||
float width1 = std::max(100.0f, ImGui::CalcTextSize(button1.c_str()).x + 10.0f);
|
float width1 = std::max(100.0f, ImGui::CalcTextSize(button1.c_str()).x + 10.0f);
|
||||||
float width2 = std::max(100.0f, ImGui::CalcTextSize(button2.c_str()).x + 10.0f);
|
float width2 = std::max(100.0f, ImGui::CalcTextSize(button2.c_str()).x + 10.0f);
|
||||||
@@ -359,10 +358,8 @@ namespace erreula
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
}
|
}
|
||||||
|
ImGui::End();
|
||||||
ImGui::PopFont();
|
ImGui::PopFont();
|
||||||
|
|
||||||
if(g_errEula.buttonPressed || g_errEula.rightButtonPressed)
|
if(g_errEula.buttonPressed || g_errEula.rightButtonPressed)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user