23 Commits
Author SHA1 Message Date
goeiecool9999andGitHub 138510106c Vulkan: Fix freeze when closing pad view (#435) 2022-11-06 00:40:00 +01:00
Exzap 948460cad7 InputSettings: Refresh panels on profile load and other operations 2022-11-06 00:32:33 +01:00
Exzap 3df8217a02 SDLController: Do not manually recycle controller instance
SDL_GameControllerFromInstanceID does not increase internal ref counter.
Fixes a crash when removing an SDL controller that is in use by another profile
2022-11-06 00:32:33 +01:00
Exzap ec6726e85c Use generic EC_POINT_get_affine_coordinates 2022-11-06 00:32:33 +01:00
goeiecool9999andGitHub 348d86648f Vulkan: Refactor swapchain code (#399) 2022-11-04 15:22:29 +01:00
ExzapandGitHub 592c9b2776 Update build_check.yml 2022-11-04 15:09:25 +01:00
qurious-pixelandGitHub 5d156672e8 CI: Add AppImage Build (#452) 2022-11-04 15:07:17 +01:00
TillsunsetandGitHub 2f86622a68 Don't go to mount point for free space check (#450) 2022-11-04 14:34:32 +01:00
ExzapandGitHub a40b226e00 CubebInput: Avoid redundant CoInitializeEx (#449) 2022-11-03 18:29:21 +01:00
TillsunsetandGitHub 521f2fb707 MacOS: Workaround for Metal stride limitation (#445) 2022-11-03 12:51:32 +01:00
goeiecool9999andGitHub a129d22a57 Vulkan: Experimental fix for self-dependency barriers during renderpass (#431) 2022-11-03 00:43:26 +01:00
Adrian GraberandGitHub d4e14d2b05 Implement proper microphone support (#251) 2022-11-03 00:24:34 +01:00
goeiecool9999andGitHub dfa7774c4c Non-windows: Link fontawesome into executable. (#442) 2022-11-03 00:23:31 +01:00
goeiecool9999andGitHub c3182aedd9 GeneralSettings: Update vsync after settings close (#401) 2022-10-31 17:54:26 +01:00
Zhaohui ShiandGitHub f41f7b63e8 DSUController: fix crash when running on offline mode (#434) 2022-10-31 14:27:35 +01:00
TillsunsetandGitHub c143950dd1 Fix fullscreen on macos (#429) 2022-10-30 01:40:53 +02:00
jn64andGitHub 4e991d603a Add libpulse-dev to CI build (#430) 2022-10-30 01:39:39 +02:00
OatmealDomeandGitHub e0aaf631c4 macOS: Set values for empty keys in Info.plist (#425) 2022-10-28 16:57:14 +02:00
TillsunsetandGitHub 9ebbfb3ae2 Fix some compiler warnings (#416) 2022-10-26 14:47:44 +02:00
gurrgurandGitHub 3869b47c35 OpenGL: Bind back buffer before clearing (#222) (#414) 2022-10-26 14:07:34 +02:00
GaryOderNichtsandGitHub d303a7f502 coreinit: Implement OSGetSystemTick (#415) 2022-10-26 14:06:16 +02:00
GaryOderNichtsandGitHub 2461464ba7 FSA: Add missing path translations (#413) 2022-10-26 00:25:46 +02:00
gurrgurandGitHub 76c75f767b Use portable format specifiers (#411)
Fixes #387
2022-10-25 20:38:29 +02:00
57 changed files with 1572 additions and 774 deletions
+38 -14
View File
@@ -22,34 +22,36 @@ jobs:
uses: actions/checkout@v3
with:
submodules: "recursive"
- name: Setup release mode parameters (for deploy)
if: ${{ inputs.deploymode == 'release' }}
run: |
echo "BUILD_MODE=release" >> $GITHUB_ENV
echo "BUILD_FLAGS=" >> $GITHUB_ENV
echo "Build mode is release"
- name: Setup debug mode parameters (for continous build)
if: ${{ inputs.deploymode != 'release' }}
run: |
echo "BUILD_MODE=debug" >> $GITHUB_ENV
echo "BUILD_FLAGS=" >> $GITHUB_ENV
echo "Build mode is debug"
- name: Setup version for experimental
if: ${{ inputs.experimentalversion != '' }}
run: |
echo "[INFO] Experimental version ${{ inputs.experimentalversion }}"
echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEXPERIMENTAL_VERSION=${{ inputs.experimentalversion }}" >> $GITHUB_ENV
- name: "Install system dependencies"
run: |
sudo apt update -qq
sudo apt install -y ninja-build cmake libgtk-3-dev libsecret-1-dev libgcrypt20-dev libsystemd-dev freeglut3-dev clang-12 nasm
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"
run: |
bash ./dependencies/vcpkg/bootstrap-vcpkg.sh
- name: 'Setup NuGet Credentials for vcpkg'
shell: 'bash'
run: |
@@ -66,15 +68,12 @@ jobs:
- name: "cmake"
run: |
mkdir -p build
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
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
- name: "Build Cemu"
run: |
cd build
ninja
cmake --build build
- name: Prepare artifact
if: ${{ inputs.deploymode == 'release' }}
run: mv bin/Cemu_release bin/Cemu
@@ -85,8 +84,33 @@ jobs:
with:
name: cemu-bin-linux-x64
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:
runs-on: windows-2022
steps:
@@ -239,4 +263,4 @@ jobs:
if: ${{ inputs.deploymode == 'release' }}
with:
name: cemu-bin-macos-x64
path: ./bin/Cemu.dmg
path: ./bin/Cemu.dmg
@@ -13,13 +13,18 @@ jobs:
runs-on: ubuntu-20.04
needs: call-release-build
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3
with:
name: 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
with:
name: cemu-bin-windows-x64
@@ -53,7 +58,14 @@ jobs:
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 }}
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
run: |
ls ./
+14 -6
View File
@@ -15,13 +15,18 @@ jobs:
runs-on: ubuntu-20.04
needs: call-release-build
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3
with:
name: 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
with:
name: cemu-bin-windows-x64
@@ -44,11 +49,7 @@ jobs:
echo "Cemu CI version: $(./getversion)"
echo "CEMU_FOLDER_NAME=Cemu_$(./getversion)" >> $GITHUB_ENV
echo "CEMU_VERSION=$(./getversion)" >> $GITHUB_ENV
- name: Create appimage
run: |
echo "to do"
- name: Create release from windows-bin
run: |
ls ./
@@ -57,6 +58,13 @@ jobs:
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 }}
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
run: |
+3 -3
View File
@@ -25,7 +25,7 @@ To compile Cemu, a recent enough compiler and STL with C++20 support is required
### Installing dependencies
#### For Ubuntu and derivatives:
`sudo apt install -y git curl cmake ninja-build nasm libgtk-3-dev libsecret-1-dev libgcrypt20-dev libsystemd-dev freeglut3-dev libpulse-dev`
`sudo apt install -y cmake curl freeglut3-dev git libgcrypt20-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev nasm ninja-build`
*Additionally, for Ubuntu 22.04 only:*
- `sudo apt install -y clang-12`
@@ -33,10 +33,10 @@ To compile Cemu, a recent enough compiler and STL with C++20 support is required
`cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DCMAKE_C_COMPILER=/usr/bin/clang-12 -DCMAKE_CXX_COMPILER=/usr/bin/clang++-12 -G Ninja -DCMAKE_MAKE_PROGRAM=/usr/bin/ninja`
#### For Arch and derivatives:
`sudo pacman -S --needed git cmake llvm clang ninja nasm base-devel linux-headers gtk3 libsecret libgcrypt systemd freeglut zip unzip libpulse`
`sudo pacman -S --needed base-devel clang cmake freeglut git gtk3 libgcrypt libpulse libsecret linux-headers llvm nasm ninja systemd unzip zip`
#### For Fedora and derivatives:
`sudo dnf install git cmake clang ninja-build nasm kernel-headers gtk3-devel libsecret-devel libgcrypt-devel systemd-devel freeglut-devel perl-core zlib-devel cubeb-devel`
`sudo dnf install clang cmake cubeb-devel freeglut-devel git gtk3-devel kernel-headers libgcrypt-devel libsecret-devel nasm ninja-build perl-core systemd-devel zlib-devel`
### Build Cemu using cmake and clang
1. `git clone --recursive https://github.com/cemu-project/Cemu`
+1 -1
View File
@@ -21,7 +21,7 @@ if (ENABLE_VCPKG)
endif()
endif()
project(Cemu VERSION 2.0)
project(Cemu VERSION 2.0.0)
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
Vendored Executable
+50
View File
@@ -0,0 +1,50 @@
#!/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} 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
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/
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

+7
View File
@@ -75,6 +75,13 @@ if (MACOS_BUNDLE)
set(RESOURCE_FILES "${CMAKE_SOURCE_DIR}/src/resource/cemu.icns")
target_sources(CemuBin PRIVATE "${RESOURCE_FILES}")
set(MACOSX_BUNDLE_ICON_FILE "cemu.icns")
set(MACOSX_BUNDLE_GUI_IDENTIFIER "info.cemu.Cemu")
set(MACOSX_BUNDLE_BUNDLE_NAME "Cemu")
set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${CMAKE_PROJECT_VERSION})
set(MACOSX_BUNDLE_BUNDLE_VERSION ${CMAKE_PROJECT_VERSION})
set(MACOSX_BUNDLE_COPYRIGHT "Copyright © 2022 Cemu Project")
set(MACOSX_BUNDLE_CATEGORY "public.app-category.games")
set_target_properties(CemuBin PROPERTIES
+2
View File
@@ -178,6 +178,8 @@ add_library(CemuCafe
HW/Latte/Renderer/Vulkan/LatteTextureVk.h
HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp
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/VKRBase.h
HW/Latte/Renderer/Vulkan/VKRMemoryManager.cpp
+2
View File
@@ -5,6 +5,7 @@
#include "Cafe/HW/Espresso/Interpreter/PPCInterpreterInternal.h"
#include "Cafe/HW/Espresso/Recompiler/PPCRecompiler.h"
#include "audio/IAudioAPI.h"
#include "audio/IAudioInputAPI.h"
#include "Cafe/HW/Espresso/Debugger/Debugger.h"
#include "config/ActiveSettings.h"
@@ -402,6 +403,7 @@ void cemu_initForGame()
GraphicPack2::ActivateForCurrentTitle();
// print audio log
IAudioAPI::PrintLogging();
IAudioInputAPI::PrintLogging();
// everything initialized
forceLog_printf("------- Run title -------");
// wait till GPU thread is initialized
+3 -3
View File
@@ -441,7 +441,7 @@ bool fsc_nextDir(FSCVirtualFile* fscFile, FSCDirEntry* dirEntry)
/*
* Create directory
*/
bool fsc_createDir(char* path, sint32* fscStatus)
bool fsc_createDir(const char* path, sint32* fscStatus)
{
fscDeviceC* fscDevice = NULL;
*fscStatus = FSC_STATUS_UNDEFINED;
@@ -461,7 +461,7 @@ bool fsc_createDir(char* path, sint32* fscStatus)
/*
* Rename file or directory
*/
bool fsc_rename(char* srcPath, char* dstPath, sint32* fscStatus)
bool fsc_rename(const char* srcPath, const char* dstPath, sint32* fscStatus)
{
std::string srcDevicePath;
std::string dstDevicePath;
@@ -481,7 +481,7 @@ bool fsc_rename(char* srcPath, char* dstPath, sint32* fscStatus)
/*
* Delete file or subdirectory
*/
bool fsc_remove(char* path, sint32* fscStatus)
bool fsc_remove(const char* path, sint32* fscStatus)
{
std::string devicePath;
fscDeviceC* fscDevice = NULL;
+3 -3
View File
@@ -167,9 +167,9 @@ void fsc_unmountAll();
FSCVirtualFile* fsc_open(const char* path, FSC_ACCESS_FLAG accessFlags, sint32* fscStatus, sint32 maxPriority=FSC_PRIORITY_MAX);
FSCVirtualFile* fsc_openDirIterator(const char* path, sint32* fscStatus);
bool fsc_createDir(char* path, sint32* fscStatus);
bool fsc_rename(char* srcPath, char* dstPath, sint32* fscStatus);
bool fsc_remove(char* path, sint32* fscStatus);
bool fsc_createDir(const char* path, sint32* fscStatus);
bool fsc_rename(const char* srcPath, const char* dstPath, sint32* fscStatus);
bool fsc_remove(const char* path, sint32* fscStatus);
bool fsc_nextDir(FSCVirtualFile* fscFile, FSCDirEntry* dirEntry);
void fsc_close(FSCVirtualFile* fscFile);
uint32 fsc_getFileSize(FSCVirtualFile* fscFile);
+2 -1
View File
@@ -11,6 +11,7 @@
#include "util/IniParser/IniParser.h"
#include "util/helpers/StringHelpers.h"
#include "Cafe/CafeSystem.h"
#include <cinttypes>
std::vector<GraphicPackPtr> GraphicPack2::s_graphic_packs;
std::vector<GraphicPackPtr> GraphicPack2::s_active_graphic_packs;
@@ -660,7 +661,7 @@ void GraphicPack2::LoadShaders()
uint64 shader_base_hash = 0;
uint64 shader_aux_hash = 0;
wchar_t shader_type[256]{};
if (filename.size() < 256 && swscanf(filename.c_str(), L"%I64x_%I64x_%ls", &shader_base_hash, &shader_aux_hash, shader_type) == 3)
if (filename.size() < 256 && swscanf(filename.c_str(), L"%" SCNx64 "_%" SCNx64 "_%ls", &shader_base_hash, &shader_aux_hash, shader_type) == 3)
{
if (shader_type[0] == 'p' && shader_type[1] == 's')
m_custom_shaders.emplace_back(LoadShader(p, shader_base_hash, shader_aux_hash, GP_SHADER_TYPE::PIXEL));
+2 -2
View File
@@ -64,8 +64,8 @@ struct LatteGPUState_t
{
bool isEnabled;
MPTR physPtr;
volatile uint32 flipRequestCount;
volatile uint32 flipExecuteCount;
std::atomic<uint32> flipRequestCount;
std::atomic<uint32> flipExecuteCount;
}screen[2];
}osScreen;
};
+2 -1
View File
@@ -13,6 +13,7 @@
#include "util/Zir/EmitterGLSL/ZpIREmitGLSL.h"
#include "util/Zir/Core/ZpIRDebug.h"
#include "util/containers/flat_hash_map.hpp"
#include <cinttypes>
struct _ShaderHashCache
{
@@ -294,7 +295,7 @@ void LatteShader_CreateRendererShader(LatteDecompilerShader* shader, bool compil
{
if (shader->hasError )
{
forceLog_printf("Unable to compile shader %I64x", shader->baseHash);
forceLog_printf("Unable to compile shader %" PRIx64, shader->baseHash);
return;
}
+2 -2
View File
@@ -78,7 +78,7 @@ bool LatteHandleOSScreen_TV()
LatteRenderTarget_copyToBackbuffer(osScreenTVTex[bufferIndexTV]->baseTexture->baseView, false);
if (LatteGPUState.osScreen.screen[0].flipExecuteCount != LatteGPUState.osScreen.screen[0].flipRequestCount)
LatteGPUState.osScreen.screen[0].flipExecuteCount = LatteGPUState.osScreen.screen[0].flipRequestCount;
LatteGPUState.osScreen.screen[0].flipExecuteCount.store(LatteGPUState.osScreen.screen[0].flipRequestCount);
return true;
}
@@ -101,7 +101,7 @@ bool LatteHandleOSScreen_DRC()
LatteRenderTarget_copyToBackbuffer(osScreenDRCTex[bufferIndexDRC]->baseTexture->baseView, true);
if (LatteGPUState.osScreen.screen[1].flipExecuteCount != LatteGPUState.osScreen.screen[1].flipRequestCount)
LatteGPUState.osScreen.screen[1].flipExecuteCount = LatteGPUState.osScreen.screen[1].flipRequestCount;
LatteGPUState.osScreen.screen[1].flipExecuteCount.store(LatteGPUState.osScreen.screen[1].flipRequestCount);
return true;
}
@@ -352,14 +352,19 @@ void OpenGLRenderer::NotifyLatteCommandProcessorIdle()
glFlush();
}
void OpenGLRenderer::EnableVSync(int state)
void OpenGLRenderer::UpdateVSyncState()
{
int configValue = GetConfig().vsync.GetValue();
if(m_activeVSyncState != configValue)
{
#if BOOST_OS_WINDOWS
if(wglSwapIntervalEXT)
wglSwapIntervalEXT(state); // 1 = enabled, 0 = disabled
if(wglSwapIntervalEXT)
wglSwapIntervalEXT(configValue); // 1 = enabled, 0 = disabled
#else
cemuLog_log(LogType::Force, "OpenGL vsync not implemented");
cemuLog_log(LogType::Force, "OpenGL vsync not implemented");
#endif
m_activeVSyncState = configValue;
}
}
bool IsRunningInWine();
@@ -438,6 +443,7 @@ void OpenGLRenderer::EnableDebugMode()
void OpenGLRenderer::SwapBuffers(bool swapTV, bool swapDRC)
{
GLCanvas_SwapBuffers(swapTV, swapDRC);
UpdateVSyncState();
if (swapTV)
cleanupAfterFrame();
@@ -548,6 +554,9 @@ void OpenGLRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutpu
renderstate_resetDepthControl();
attributeStream_reset();
// bind back buffer
rendertarget_bindFramebufferObject(nullptr);
if (clearBackground)
{
int windowWidth, windowHeight;
@@ -559,9 +568,6 @@ void OpenGLRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutpu
g_renderer->ClearColorbuffer(padView);
}
// bind back buffer
rendertarget_bindFramebufferObject(nullptr);
// calculate effective size
sint32 effectiveWidth;
sint32 effectiveHeight;
@@ -30,7 +30,7 @@ public:
void Flush(bool waitIdle = false) override;
void NotifyLatteCommandProcessorIdle() override;
void EnableVSync(int state) override;
void UpdateVSyncState();
void EnableDebugMode() override;
void SwapBuffers(bool swapTV = true, bool swapDRC = true) override;
@@ -168,6 +168,7 @@ private:
GLuint m_defaultFramebufferId;
GLuint m_pipeline = 0;
int m_activeVSyncState{};
bool m_isPadViewContext{};
// rendertarget viewport
@@ -282,4 +283,4 @@ private:
std::vector<bufferCacheReleaseQueueEntry_t> bufferCacheEntries;
}m_destructionQueues;
};
};
+1 -2
View File
@@ -58,7 +58,6 @@ public:
virtual bool GetVRAMInfo(int& usageInMB, int& totalInMB) const;
virtual void EnableDebugMode() {}
virtual void EnableVSync(int state) = 0;
virtual void ClearColorbuffer(bool padView) = 0;
virtual void DrawEmptyFrame(bool mainWindow) = 0;
@@ -176,4 +175,4 @@ protected:
#endif
};
extern std::unique_ptr<Renderer> g_renderer;
extern std::unique_ptr<Renderer> g_renderer;
@@ -0,0 +1,367 @@
#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);
swapchainExtent = ChooseSwapExtent(details.capabilities, getSize());
// 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, swapchainExtent);
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");
sizeOutOfDate = false;
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 = swapchainExtent.width;
framebufferInfo.height = swapchainExtent.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 Vector2i& size) const
{
if (capabilities.currentExtent.width != std::numeric_limits<uint32>::max())
return capabilities.currentExtent;
VkExtent2D actualExtent = { (uint32)size.x, (uint32)size.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;
}

Some files were not shown because too many files have changed in this diff Show More